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

Assembly 远端调用将错误的IP推送到堆栈,assembly,virtualbox,nasm,x86-16,callstack,Assembly,Virtualbox,Nasm,X86 16,Callstack,当我使用VirtualBox以实模式运行以下代码时,我希望调用0x9000:foo指令将CS和IP寄存器推送到堆栈中。但是,当我在far调用之后查看调用堆栈(在VirtualBox的调试器中)时,返回地址被设置为9000:000006c6(而不是9000:0000078c),显然是一个任意地址 如果使用near调用,则调用堆栈中的返回地址设置正确 我正在使用NASM进行组装,并在VirtualBox上以x86实模式运行代码 我知道在本例中不需要远调用,但我需要在代码的另一部分中使用远调用 900

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

如果使用near调用,则调用堆栈中的返回地址设置正确

我正在使用NASM进行组装,并在VirtualBox上以x86实模式运行代码

我知道在本例中不需要远调用,但我需要在代码的另一部分中使用远调用

9000:00000787    call 0x9000:foo
9000:........    ...
9000:00003bac    push bp  ; foo:
9000:........    ...
9000:00003bf0    retf
我的问题是:

使用远调用调用当前段中的函数可以吗


调用堆栈中错误的返回地址是否存在已知原因?

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

push bp 
mov bp, sp
在某些代码中,这是使用等效指令完成的

VirtualBox的调用堆栈转储程序遍历堆栈,这需要将BP设置为当前堆栈帧。如果在输入一个函数后立即停止,则应该考虑一个命令,例如“代码> dw SS:sp <代码>,它将从当前堆栈指针位置原始转储数据作为16位字。如果进行近距离呼叫,打印的第一个字应该是要返回的偏移量,而进行远距离呼叫时,偏移量将首先跟在要返回的段之后



注意:根据我的经验,调用堆栈是遍历的,假设已完成远调用以到达函数,则近调用可能不会生成正确的调用堆栈跟踪。

当然,您可以在同一段中使用远调用。验证您的值,因为推送的值是返回地址,所以它永远不能是
767
。它应该是
76c
您确定正在正确地检查堆栈,并且在调用
之前您有正确的CS:IP值吗?它应该在调用后推送指令的CS:IP,而不是
00000767
,因此如果我没有记错
call ptr16:16
有5个字节长,那么可能
9000:0000076c
6c
与您声称看到的
c6
非常接近。记住,它是一个小端点,偏移量在低位地址,段在高位地址。这看起来不像一个,因为您描述的与可能的不匹配。我正在使用VirtualBox调试器。我将断点设置为9000:00003bac,并在执行到达断点时打印堆栈。您不能在近调用中看到
9000:
,因为这甚至不会将段放在堆栈上。另外,近距离调用只有3个字节,因此如果在
787
处,则应该在堆栈上看到
78a
。我建议不要使用
kg
k
来遍历调用堆栈,除非您已经走到了同时执行
推送bp
mov-bp,sp
的点。VB的调用堆栈转储程序在堆栈中遍历,假设远调用,并且BP是当前堆栈帧。如果您在输入函数后立即停止,则应该考虑一个命令,例如“代码> dw SS:sp <代码>,它将从当前堆栈指针位置开始原始的倾倒数据。如果进行近距离呼叫,打印的第一个字应该是要返回的偏移量,而进行远距离呼叫时,偏移量将首先跟在要返回的段之后