我有下一个代码在TASM:
.MODEL SMALL
.STACK 128
.DATA
msg DB 'Message$'
crlf DB 0Dh, 0Ah, '$'
.CODE
print_string proc
pop dx
mov ah, 09h
int 21h
ret
print_string endp
Entry:
mov ax, @data
mov ds, ax
push offset msg
call print_string
mov ax, 4c00h
int 21h
END Entry
我有一个从堆栈中检索消息并打印出来的过程,但是如果我把这个过程内联到如下代码中,它会把奇怪的符号打印到控制台中:
push offset msg
pop dx
mov ah, 09h
int 21h
它将正常工作,并输出我的消息到控制台,有人能解释为什么弹出相同的值从堆栈内的过程导致非预期的行为?
1条答案
按热度按时间vuktfyat1#
push
、call
、pop
、ret
都影响堆栈执行这两条指令后,堆栈如下所示:
接下来运行的指令是
pop dx
。堆栈现在看起来如下所示:与您的预期相反,DX寄存器现在包含
call
/ret
指令的返回地址,这不是一个有效的消息指针,因此您会看到屏幕上出现垃圾。当
ret
指令运行时,它会从堆栈中弹出一些根本不是返回地址的字。溶液1
暂时把返回地址移走,下一段代码把它弹出到AX中,我们无论如何都要清除它:
溶液2
使用堆栈帧指针。
因为我们希望保留BP,所以使用了
push bp
指令,使堆栈看起来像:我们在新堆栈指针的偏移量**+4**处检索消息指针。
溶液3
使用堆栈帧指针。
这里我们保留了AX寄存器中的BP,代码无论如何都要清除它。堆栈如下所示:
我们在新堆栈指针的偏移量**+2**处检索消息指针。
最后一个例子使用
ret 2
来移除堆栈参数,或者,您可以在参数返回给调用者后移除该参数: