汇编语言探究不设置栈空间与地址时先压栈在运行子函数的时候出栈发生的问题

assume cs:code
data segment
	db 10 dup(0)
	;运行完程序后数据分布为36 36 36 32 31
data ends
code segment
;g001b程序运行结束
start:mov ax,12666
	  mov bx,data
	  mov ds,bx;ds=data
	  ;ds = 076a
	  mov si,0;si = 0
	  call dtoc
	  ;看运行到mov dh,8时ip的值
	  mov dh,8;等第一个函数运行完之后
	  ;再放入第二个运行函数
	  mov dl,3
	  mov cl,2;cl为对应的颜色
	  
	  
	  ;mov di,si;si为循环次数
	  ;push之前ss = 0769,sp = 0000
	  ;push之后ss = 0769,sp = fffe
	  

	***push si;***这里面通过push将si寄存器里面的值压入栈中
	  
	  mov si,0;将si设置为起始位置
	  
	  ;运行到call show_str之前时可以
	  ;直接设置g 0019
	  call show_str
	  ;使用call show_str之后ss = 0769,sp = fffc
	  ;这说明压栈的时候必须指定内存空间,不能
	  ;压栈之后调用一个函数再出栈
	  
	  mov ax,4c00h
	  int 21h
	  
dtoc: mov bx,10
	  ;bl = 0ah
	s1:mov dx,0
	  div bx
	  ;8086除法指令正确执行有条件
	  ;被除数的高位寄存器数值,必须小于除数
	  ;如果出现??? [BX+SI]的结果,说明这一步
	  ;出现了除法的溢出,使用div bl指令会出现除法溢出
	  ;12666/10 = 1266,而1266>2的8次方-1=256
	  ;所以8位寄存器存不下1266
	  mov cx,ax;商放在cx寄存器之中
	  ;方便后面的jcxz判断
	  ;第一次循环,dx = 0006(余数),ax = 04F2()
	  ;第二次循环,dx = 0006(余数),ax = 007E()
	  add dl,30h;将dl加上30h形成ascii码
	  ;第一次循环,dx = 0036
	  ;第二次循环,dx = 0036
	  mov ds:[si],dl;将dl的内容放入data:[si];ax继续存储商,接着运行下一步
	  inc si
	  jcxz ok
	  jmp short s1
   ok:ret
   
show_str:
;函数功能:将相应的字符以ascii码的形式显示出
	   mov bx,0b800h;显示图像的区域
	   mov es,bx
	   ;es = b800h
	   ;下面几行代码实现mov bp,dh*160+dl
	   mov ah,dh
	   mov al,160
	   mul ah
	   mov dh,0000
	   add ax,dx
	   mov bp,ax;这一段代码实现了mov bp,dh*160+dl功能
	   ;bp = 0503
	   mov dl,cl;将颜色赋值给dl寄存器
	   ;dl = 0002
	   
	   
	   ;mov cx,di;设置循环次数,
	   ;程序的bug,cx出来时数据错误
	   ;cx = 001B
	   ;mov cx,0006h时可以全显示出来
	   ;该用di传输数据时就无法显示出来字符串了。。。
	   ;这一句改为mov cx,di时就无法显示字符串
	   ;di = 0005h,cx = 0005h
	   ;di设置为0006h时才能全部显示,di设置为0005h时无法全部显示
	   
	   ;之前这段改为pop cx可以运行出来数据
	   ;改为mov cx,di就不可以运行出来数据

	   ***pop cx***主要是观察这个pop之后的地址变化
	   
	   
	 s:mov bh,ds:[si];高位存储ascii码
	   mov bl,dl;低位存储颜色
	   ;bx = 0257
	   ;显示数据:36 36 36 32 31
	   
	   mov es:[bp],bx
	   inc si
	   add bp,2
	   loop s
	   ret
code ends
end start
;结论,采用g命令调试的时候对于打印字符串来说不易显示正确
;直接输入t17时直接运行exe文件

执行push之前各个寄存器中的值
在这里插入图片描述可以看出这个时候寄存器的ss=0769,sp=0000
执行了push操作之后
在这里插入图片描述
可以看出ss = 0769,sp = fffe
接下来继续执行

在这里插入图片描述
调用函数之前ss = 0769,sp = fffe,栈的段地址和段内地址不发生变化
调用函数之后
在这里插入图片描述
可以看到sp由原先的fffe改为现在的fffc,栈内的偏移量sp往前减去了两个字节,
因为调用函数时操作系统会将函数的起始地址压栈,从而使得栈内偏移量sp发生变化
所以想要使用栈保存局部变量的时候,最好的方法是在程序首部留出压栈与出栈的空间,将相应地址赋值给ss与sp,然后再进行出栈入栈的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值