我正在尝试学习如何用汇编语言调用程序。下面是一个显示我的问题的简单示例。我7
压栈,调用程序;当程序从堆栈中弹出时,该值不是我推送的那个。有人可以帮我了解正在发生的事情以及我可以做些什么来完成这项工作吗?
PUSH 7
CALL FOOBAR
MOV AH, 4CH
INT 21H
FOOBAR PROC
POP AX ; Not 7
RET
FOOBAR ENDP
该call
指令将返回地址放在堆栈上,因此当您pop ax
在程序中时,它不会获得您推送的 7,而是返回地址。也不起作用(它希望在ret
那里找到返回地址!)尝试类似...
FOOBAR proc
push bp ; save caller's reg
mov bp, sp
mov ax, [bp + 4]
; do something with it
; leave - equivalent to:
mov sp, bp
pop bp
ret
这里有一个可能的“陷阱”。“远”过程在堆栈上同时具有段(cs)和偏移量,因此返回地址有 4 个字节,push bp
第一个参数 at 有两个字节[bp + 6]
。我想只是proc
默认为proc near
- 你可能想说,只是为了清楚起见。如果您需要proc far
,可能是时候升级到 32 位代码(或 64 位)了。16 位代码就是这样一个 PITA - 我们真的很高兴忘记它!:)
这是从 main 调用过程并传递两个参数值分别为 1 和 2 时的堆栈状态:
Address : Value
----------------------
0xbffff3b0 : 0x0011e030
0xbffff3b4 : 0x08049ff4
esp --> 0xbffff3b8 : 0xbffff3e8
0xbffff3bc : 0x08048419
0xbffff3c0 : 0x00284324
0xbffff3c4 : 0x00000003
ebp --> 0xbffff3c8 : 0xbffff3e8 <-- old ebp
0xbffff3cc : 0x080483e5 <-- return address
ebp + 0x8 --> 0xbffff3d0 : 0x00000001 <-- first parameter
ebp + 0xc --> 0xbffff3d4 : 0x00000002 <-- second parameter
0xbffff3d8 : 0x0804840b
0xbffff3dc : 0x00283ff4
此代码取自 32 位程序,因此寄存器实际上是 bp 和 sp,相对偏移量是 0x4 和 0x6: