First push a problem running a sub-function of the stack occurs when the assembly language is not set up to explore and address of stack space

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文件

Before execution value of each push registers
Here Insert Picture Descriptioncan see that this time the register ss = 0769, sp = 0000
after performing the push operation
Here Insert Picture Description
can be seen ss = 0769, sp = fffe
then continue execution

Here Insert Picture Description
Ss = 0769 before calling this function, sp = fffe, the stack segment and the segment address of the address does not change
after the calling function
Here Insert Picture Description
can be seen from the original sp fffe to now fffc, offset within the stack forward by subtracting sp two bytes,
since the starting address of the function call push the operating system will function, so that the stack offset change occurs sp
so when you want to use a stack of local variables, the best way is in the program header and leave room for the push out of the stack, the address to assign the corresponding ss and sp, and then to push a stack operation.

Published 17 original articles · won praise 7 · views 2985

Guess you like

Origin blog.csdn.net/znevegiveup1/article/details/103831930