loop指令为循环指令, 所有的循环指令都是短转移, ip修改范围-128~127
指令格式:
loop 标号
隐含条件, 若cx不等于0, 则跳转到标号处执行, 若cx=0, 则什么都不做
loop指令实例
data segment
mynum dw ? ; 定义一个字变量,未初始化
db '$'
data ends
code segment
assume cs:code
start:
mov ax, data
mov ds, ax
mov ax,0 ; 结果
mov cx, 100 ; 循环100次
s:
add ax, cx
loop s
mov mynum, ax
mov dx, 0
mov ah, 09h
int 21h
mov ax, 4c00h
int 21h
code ends
end start
在定义数据变量时, 可以使用?替代未初始化的值, 在使用变量前, 应该先把ds关联到data段, 否则后续可能异常
在这里, mynum是一个字变量, mov mynum, ax可以把ax的值赋值给变量, 如果没有定义变量, 则可以直接 mov word ptr ds:[0], ax, 明显前者更方便且不需要手动计算偏移
汇编屏幕显示整数
在这里, 并不能输出1+100的值, 原因是5050转换为13BA, 即最终为13BA, 并不符合ASCII的5050, 要查看结果需要使用debug调试
我们如何把一个整数显示到屏幕呢?
首先要把整数的每个位取出, 比如 6789 这个数, 那么千位6, 百位7, 十位8, 个位9, 然后把它们加上30h就得到它们的ASCII, 合并为一个字符串就可以调用字符串显示功能了
那么怎么取每个位?
- 把6789/10, 得到商678, 余数9即是个位
- 把678/10, 得到商67, 余数8即是十位
- 把67/10, 得到商6, 余数7即是百位
- 把6/10, 得到商为0, 循环结束, 余数是6即千位
code segment
assume cs:code
start:
mov ax,0 ; 存放循环结果
mov cx, 100 ; 循环100次,将得到结果5050
s:
add ax, cx
loop s
mov dx, 0 ; 必须要定义为0,作为被除数高位
mov bx, 10 ;每次要/10,因为结果大于256必须16位
mov si, 0 ; 记录位数
t:
div bx ; 执行一次除法,如ax为商505, dx为余数0
add dx, 30h
push dx ; 压栈,再弹栈,否则反序
add si,1
mov cx, ax
mov dx,0
jcxz ok
add cx, 1 ; 先执行+1,因为loop先-1再执行的
loop t
ok:
mov cx, si ; 设置总弹栈循环次数
mov di, 0 ; 当前弹栈次数计数
topop:
pop ax
mov ds:[di], al
add di,1
jcxz toshow
loop topop
toshow:
mov ax, 24h
mov ds:[di],ax ; 结束标记, 并以字符串显示
lea dx, ds:[0]
mov ah, 09h
int 21h
mov ax, 4c00h
int 21h
code ends
end start
执行上述代码, 会在屏幕以十进制输出1~100的和, 当然你可以换成其他累加次数, 或数字
在上述代码中, 你需要注意cx的值, 在执行loop循环时, 它会先进行cx-1, 然后判断是否为0, 若为0则不执行, 也就是说若cx为1, 那么loop执行了也并没有执行? 实际是执行了cx-1, 但又没执行循环代码