远程调用将错误的 IP 推送到堆栈

Far call pushing wrong IP to the stack

当我在实模式下使用 VirtualBox 运行 以下代码时,我希望 call 0x9000:foo 指令将 CS 和 IP 寄存器压入堆栈。然而,当我在远调用之后查看调用堆栈(在 VirtualBox 的调试器中)时,return 地址被设置为 9000:000006c6(而不是 9000:0000078c),显然是一个任意地址。

如果我使用近调用,则调用堆栈中的 return 地址设置正确。

我正在使用 NASM 和 运行在 VirtualBox 上以 x86 实模式编译代码。

我知道在这个例子中我不需要远程调用,但我的代码的另一部分需要它。

9000:00000787    call 0x9000:foo
9000:........    ...
9000:00003bac    push bp  ; foo:
9000:........    ...
9000:00003bf0    retf

我的问题是:

使用far call调用当前段的函数可以吗?

调用堆栈中的 return 地址错误是否有已知原因?

我建议不要使用 kgk 在 VirtualBox 的调试器中遍历调用堆栈,除非你已经进入了设置函数堆栈框架的函数序言之后的某个点:

push bp 
mov bp, sp

在某些代码中,这是使用等效的 ENTER 指令完成的。

VirtualBox 的调用堆栈转储器遍历堆栈,这需要将 BP 设置为当前堆栈帧。如果你在进入一个函数后立即停止,你应该考虑像 dw ss:sp 这样的命令,它会将当前堆栈指针位置的数据原始转储为 16 位字。如果进行近距离调用,则打印的第一个单词应该是 return 到 return 的偏移量,对于远距离调用,偏移量将首先紧随其后的是 return 到

的段

注意:根据我的经验,调用堆栈是在假设已完成 FAR CALL 以到达函数的情况下遍历的,而 NEAR CALL 可能不会产生正确的调用堆栈跟踪。