在js中双重循环,代码如下:
for(let i =0; i < l1;i++){
for(let j=0; j< l2;j++){
// todo...
}
}
以上代码在汇编中是如何实现的呢.
mov cx, 4
s: mov ax,1
loop s
assume cs:codesg, ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
codesg segment
start: mov ax, datasg
mov ds, ax
mov bx, 0 ; 用BX来定位行
mov cx, 4
s0: mov si, 0 ; 用si来定位列
mov cx, 3
s: mov al, [bx+si]
and al, 11011111b
mov [bx+si], al
inc si
loop s ; 此时的 cx 已经为0
add bx, 16
loop s0 ; cx = cx -1 , 再判断 cx 为是否为0
mov ax, 4c00h
int 21h
end codesg
end start
- 原因如下:
- 每当执行 loop 语句时, 实际是执行 cx = cx -1 然后判断 cx 是否为0. 于是在内层循环后(loop s), cx =0 , 然后再到 loop s0时,此时先执行 cx = cx - 1, 即此时 cx = FFFF 因此会陷入死循环
- 改进办法.用寄存器dx来保存进入内层循环的cx,然后再内存循环结束时,将寄存器dx中的值赋给cx
start: mov ax, datasg
mov ds, ax
mov bx, 0
mov cx, 4
s0: mov dx, cx
mov si, 0
mov cx, 3
s: mov al, [bx+si]
and al, 11011111b
mov [bx+si], al
inc si
loop s
add bx, 16
mov cx, dx
loop s0
mov ax, 4c00h
int 21h
- 以上方法可以解决两层循环的问题,但是CPU中的寄存器毕竟是有限的,当循环次数多的时候,寄存器将不够用.
- 考虑到内存,可以将寄存器cx的值存入内存中.然后在内存循环结束后,在从内存中读取值给cx
assme cs:codesg, ds: datasg
datasg segment
; 其他代码略
dw 0 ; 定义一个字单元, 用来保存cx
datasg ends
codesg segment
start: mov ax, datasg
mov ds, ax ; 汇编中用ds来定位数据地址
mov bx, 0 ; 偏移量为0
mov cx, 4 ; 外层循环为4
s0: mov ds:[40H], cx ; 将外层循环的次数保存到内存datasg:40H单元中
mov si, 0
mov cx, 3
s: mov al, [bx+si]
and al, 11011111b
mov [bx+si], al
inc si
loop s
add bx, 16 ; 移到下一个字单元
mov cx, ds:[40H] ; 从内存中取出当前循环的次数
loop s0
mov ax, 4c00h
int 21h
end codesg
end start
- 以上方法可以解决CPU中寄存器不够用的情况,但对于保存的多个数据,程序猿们必须要记住数据保存在哪个内存单元中.当代码量大的时候,需要写很多注释,也不利于阅读与维护
- 看VC++ 6.0编译器是如何处理的
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a018154f158f0fb5261effac43ccc813.png)
- 通过反编译,查看汇编源码可以发现.
- 在遇到函数时,编译器将当前环境push进一个栈中,当执行完毕,将栈中的环境pop出来
- 于是上面的代码可以改为如下:
stack segment ; 栈空间
dw 0,0,0,0,0,0,0,0 ; 16字节(根据需要定)
stack ends
codesg segment
start: mov ax, stacksg
mov ss, ax
mov sp, 16 ; 汇编中ss 指向栈端, sp代表偏移量为16
mov ax, datasg
mov ds, ax
mov bx, 0
mov cx, 4
s0: push cx
mov si,0
mov cx, 3
s: mov al, [bx+si]
and al, 11011111b
mov [bx+si], al
inc si
loop s
add bx, 16
pop cx
loop s0
mov ax, 4c00h
int 21h
codesg ends
end start