loop指令实现循环
执行过程:
①(cx)=(cx)-1
②判断 cx 中的值,不为零则转至标号处执行程序,如果为零则向下执行。
例:计算2^12
assume cs:codesegcodeseg segmentmov ax,2#-------做11次add ax,ax----------mov cx,11
s:add ax,axloop s#--------------------------------mov ax,4c00hint 21hcodeseg ends
end
框架
mov cx,循环次数
s:循环的程序段loop s
考虑这么一个问题:计算ffff:0006单元中的数乘以3,结果储存在dx中
分析:
- 结果不能储存在一个8位的寄存器中,存在越界的可能,存在16位的寄存器中显然则不会越界,所以需要存在dx中而不是dl或者dh
- 基本思路:dx=0,把(ffff:0006)中的字节型数据放入ax中,执行三次
add dx,ax
- 八位的内存单元如何给16位的ax赋值? 令(ah)=0,赋值给al
assume cs:code
code segmentmov ax,0ffffhmov ds,axmov bx,6hmov ah,0mov al,[bx]mov dx,0mov cx,3
s:add dx,axloop smov ax,4c00hint 21h
code ends
end
当写入 mov al,[dx]
时,编译器报错
debug调试循环的方式
g ip地址
: 直接执行到某条指令
p
: 可以用来结束int 21h,也可以用来跳过循环
注:debug调试程序时,文件名要带上后缀 -debug p.exe
Debug和汇编编译器masm对指令的不同处理
mov ax,[0]
Debug解释为 mov ax,((ds)*16+0)
masm解释为 mov ax,0
所以在masm要写为
# 显示指明段前缀
mov ax,ds:[0]# 用寄存器
mov bx,0
mov ax,[bx]
loop 和 [bx]的联合运用
考虑这样一个问题,计算ffff:0 ~ ffff:b 单元中的数据的和,结果储存在bx中
8位数据存入al,以ax为中转赋值给bx【bx不会越界进位】
assume cs:code
code segmentmov ax,0ffffhmov ds,axmov bx,0 ;初始化ds:bx指向ffff:0mov dx,0 ;初始化累加器dx, (dx)=0mov cx,12 ;初始化循环计数寄存器cx
s:mov ah,0mov al,ds:[bx] ;ax为中介传递数据add dx,axinc bx ;ds:bx指向下一个元素loop smov ax,4c00hint 21h
code ends
end
一段安全的空间
assume cs:code
code segmentmov ax,0mov ds,axmov ds:[26h],axmov ax,4c00hint 21h
code ends
end
执行上述的程序,系统会死机
因为在实模式下,我们可以自由地操纵真实的硬件;
在保护模式下,则是在操作系统的保护下,无法操纵真实的硬件
所以在实模式下编程时,要使用安全的内存空间
一般是 0:200 ~ 0:2ff
这256字节的空间
段前缀的使用
考虑一个问题,把内存ffff:0 ~ ffff:b中的数据复制到 0:200 ~ 0:20b中
assume cs:code
code segment;设置两个段前缀mov ax,0ffffhmov ds,axmov ax,20hmov es,axmov bx,0mov cx,12
s:mov dl,ds:[bx]mov es:[bx],dlinc bxloop smov ax,4c00hint 21h
code ends
end
为什么要使用 dl
而不是 mov es:[bx], ds:[bx]
因为 直接mov的话,没有指定内存大小,会报错
其实可以用 dx
但是那样的话 bx就不是 inc
而是 add bx,2
实验四 [bx]和loop的使用
第四章 第一个程序