阅读英特尔的大手册,我看到如果你想从远程调用返回,也就是调用另一个代码段中的过程,你只需发出一个返回指令(可能带有一个立即参数来移动栈指针弹出后指针向上n个字节。
显然,如果我正确地解释事物,那么硬件就足以让段选择器和偏移量都弹出到正确的寄存器中。
但是,系统如何知道返回应该是一个远程返回,并且需要弹出偏移AND和选择器?
如果硬件刚刚弹出偏移指针而不是后面的选择器,那么你将指向正确的偏移但是错误的段。
与近返回版本相比,far return命令没有什么特别之处。
就我所知,它们看起来都相同。
我假设处理器(可能在微架构级别)跟踪哪些调用是远的,哪些是接近的,以便当它们返回时,系统知道要弹出多少字节以及弹出的位置它们(指针寄存器和段选择寄存器)。
我的假设是否正确?
你们对这种机制了解多少?
答案 0 :(得分:1)
处理器不会跟踪呼叫是远距离还是近距离; 编译器决定如何编码函数调用并使用远程或近似操作码返回。
实际上,FAR调用对现代处理器没有用处,因为您不需要更改任何段寄存器值;这就是平坦记忆模型的重点。段寄存器仍然存在,但操作系统使用base = 0和limit = 0xffffffff设置它们,因此只需一个普通的32位指针就可以访问所有内存。如果你需要在上面写一个名字,一切都很近。
通常你甚至不考虑分段,所以你实际上也没有调用它。但是手册仍然将我们用于普通代码的调用/ ret操作码描述为NEAR版本。
FAR和NEAR用于旧的86处理器,后者使用分段存储器模型。当时的程序需要选择他们希望支持的架构,从“小”到“大”。如果您的程序足够小以适合单个段,那么它可以使用NEAR调用进行编译并且仅返回。如果它是“大”,则情况恰恰相反。对于介于两者之间的任何事物,您有权选择本地函数是否需要能够从另一个段中的代码调用/返回。
大多数现代程序(除了引导加载程序之类)都运行在不同的构造上:它们期望一个平坦的内存模型。在幕后操作系统将根据需要更换内存(分页不分段),但就程序而言,它的虚拟地址空间全部都是自己的。
但是,为了回答你的问题,调用/返回的不同之处在于使用的操作码;处理器服从给它的命令。如果你错了(比如,在平面模式下给它一个FAR返回操作码),它就会失败。