assembly TASM在手术中弹出,未按预期工作

b91juud3  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(140)

我有下一个代码在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

它将正常工作,并输出我的消息到控制台,有人能解释为什么弹出相同的值从堆栈内的过程导致非预期的行为?

vuktfyat

vuktfyat1#

pushcallpopret都影响堆栈

push offset msg
call print_string

执行这两条指令后,堆栈如下所示:

R, R, M, M, ...          R = Return address (2 bytes)
^                        M = Message pointer (2 bytes)
sp

接下来运行的指令是pop dx。堆栈现在看起来如下所示:

M, M, ...
      ^
      sp

与您的预期相反,DX寄存器现在包含call/ret指令的返回地址,这不是一个有效的消息指针,因此您会看到屏幕上出现垃圾。
ret指令运行时,它会从堆栈中弹出一些根本不是返回地址的字。

溶液1

暂时把返回地址移走,下一段代码把它弹出到AX中,我们无论如何都要清除它:

print_string proc
  pop  ax            ; return address
  pop  dx            ; message pointer (removes the argument from the stack)
  push ax            ; return address
  mov  ah, 09h
  int  21h
  ret
print_string endp

溶液2

使用堆栈帧指针。

print_string proc
  push bp            ; preserving BP
  mov  bp, sp
  mov  dx, [bp+4]    ; message pointer
  mov  ah, 09h
  int  21h
  pop  bp            ; restoring BP
  ret  2             ; remove the argument from the stack
print_string endp

因为我们希望保留BP,所以使用了push bp指令,使堆栈看起来像:

B, B, R, R, M, M, ...
^           ^
sp          |
bp          |
<--- +4 --->|

我们在新堆栈指针的偏移量**+4**处检索消息指针。

溶液3

使用堆栈帧指针。

print_string proc
  xchg bp, ax        ; preserving BP in the AX register
  mov  bp, sp
  mov  dx, [bp+2]    ; message pointer
  xchg bp, ax        ; restoring BP from the AX register
  mov  ah, 09h
  int  21h
  ret  2             ; remove the argument from the stack
print_string endp

这里我们保留了AX寄存器中的BP,代码无论如何都要清除它。堆栈如下所示:

R, R, M, M, ...
^     ^
sp    |
bp    |
< +2 >|

我们在新堆栈指针的偏移量**+2**处检索消息指针。
最后一个例子使用ret 2来移除堆栈参数,或者,您可以在参数返回给调用者后移除该参数:

push offset msg
call print_string
add  sp, 2

相关问题