0

阅读英特尔的大手册,我看到如果你想从一个远调用返回,即对另一个代码段中的过程的调用,你只需发出一个返回指令(可能带有一个立即参数,将堆栈指针向上移动 n指针弹出后的字节)。

显然,如果我解释正确,这足以让硬件将段选择器和偏移量弹出到正确的寄存器中。

但是,系统如何知道返回应该是远返回并且需要弹出偏移量和选择器?

如果硬件只是弹出偏移量指针而不是它之后的选择器,那么您将指向正确的偏移量但错误的段。

与近返回版本相比,远返回命令没有什么特别之处。

据我所知,它们看起来都一样。

然后我假设处理器,可能在微架构级别,跟踪哪些调用是远的,哪些是近的,以便当它们从返回时,系统知道要弹出多少字节以及在哪里弹出它们(指针寄存器和段选择器寄存器)。

我的假设正确吗?

大家对这个机制了解多少?

4

1 回答 1

1

处理器不跟踪呼叫是远还是近;编译器决定如何编码函数调用并使用远或近操作码返回。

事实上,FAR 调用在现代处理器上没有用,因为您不需要更改任何段寄存器值;这就是平面内存模型的意义所在。段寄存器仍然存在,但操作系统将它们设置为 base=0 和 limit=0xffffffff,因此只需一个普通的 32 位指针即可访问所有内存。一切都近在咫尺,如果您需要为其命名。

通常,您甚至都不会考虑分段,因此您实际上也不会调用它。但是该手册仍然将我们用于普通代码的 call/ ret操作码描述为 NEAR 版本。


FAR 和 NEAR 用于旧的 86 处理器,它使用分段内存模型。当时的程序需要选择他们希望支持的架构类型,从“小”到“大”。如果您的程序足够小以适合单个段,则可以使用 NEAR 调用对其进行编译并以独占方式返回。如果它是“大”的,则相反。对于介于两者之间的任何事情,您有权选择本地函数是否需要能够从另一个段中的代码调用/返回。

大多数现代程序(除了引导加载程序等)都运行在不同的结构上:它们期望平坦的内存模型。在幕后,操作系统将根据需要换出内存(分页而不是分段),但就程序而言,它的虚拟地址空间完全属于自己。


但是,要回答您的问题,调用/返回的区别在于使用的操作码;处理器服从给它的命令。如果你弄错了(比如说,在平面模式下给它一个 FAR 返回操作码),它就会失败。

于 2017-09-13T01:31:54.923 回答