汇编 --- > 栈结构的妙用

在js中双重循环,代码如下:

for(let i =0; i < l1;i++){
	for(let j=0; j< l2;j++){
		// todo...
	}
}

以上代码在汇编中是如何实现的呢.

  • 汇编中用cx和loop来代表一次循环
	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编译器是如何处理的
    在这里插入图片描述
  • 通过反编译,查看汇编源码可以发现.
  • 在遇到函数时,编译器将当前环境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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值