x86-64长模式下远JMP与远CALL指令差异及细节咨询
x86-64 Long Mode: Far CALL vs Far JMP Differences & Clarifications
刚好对x86-64长模式下的远CALL和远JMP指令细节比较熟悉,来帮你理清两者的核心差异,以及你提到的几个关键疑问点——远JMP的规格细节、跨特权级调用门跳转,还有64位到32位兼容模式的跳转支持情况。
Far CALL (48 FF /3)
先确认你已经了解的信息,再补充些细节:
- 汇编形式是
call tbyte ptr [rcx],这里的tbyte ptr指向一个10字节的结构,包含目标段选择子和64位的RIP地址。 - 它的行为分两种情况:
- 目标是普通代码段:只能在相同特权级(CPL)下调用,支持跳转到32位兼容模式代码(只要段描述符的L位为0、D位为1)或者同64位长模式代码(L位为1)。调用时会自动把当前的CS和RIP压入栈,后续可以用
retf指令返回。 - 目标是调用门:支持同特权级或跨特权级调用,但只能跳转至64位长模式代码(调用门描述符的L位必须设为1)。跨特权级调用时,会自动切换到目标特权级的栈,同时把旧栈的SS/RSP、旧CS/RIP压入新栈,完成特权级的安全切换。
- 目标是普通代码段:只能在相同特权级(CPL)下调用,支持跳转到32位兼容模式代码(只要段描述符的L位为0、D位为1)或者同64位长模式代码(L位为1)。调用时会自动把当前的CS和RIP压入栈,后续可以用
Far JMP (48 FF /5)
这部分是你疑惑的核心,详细说明下它的规则:
- 汇编形式是
jmp tbyte ptr [rcx],同样指向10字节的段选择子+RIP结构。 - 和远CALL的核心差异及关键规则:
- 没有返回机制:远JMP是一次性跳转,不会把返回地址压入栈,所以不存在对应的
retf返回路径,跳过去就没法直接原路返回了。 - 普通代码段跳转:这部分和远CALL基本一致——只能在同CPL下跳转,既可以跳转到32位兼容模式(段描述符L=0、D=1),也可以跳转到64位长模式(L=1)的代码,只要CPL和段的DPL匹配就行。
- 调用门跳转的限制:
- 跨特权级跳转:远JMP完全不支持通过调用门进行跨特权级跳转!调用门的跨CPL功能是专门给远CALL设计的,如果用远JMP尝试通过调用门跳转到不同CPL,会直接触发#GP(一般保护异常)。
- 模式限制:和远CALL一样,通过调用门跳转时,只能进入64位长模式(调用门描述符的L位必须为1),没办法跳转到32位兼容模式。
- 64位到32位兼容模式的跳转:如果是直接跳转到32位兼容模式的代码段(不是通过调用门),只要是同CPL,是可以正常从64位长模式切换过去的——这一点和远CALL的代码段规则是一样的。
- 没有返回机制:远JMP是一次性跳转,不会把返回地址压入栈,所以不存在对应的
Quick Summary of Key Differences
- 远CALL支持调用门跨特权级跳转,远JMP不支持,跨CPL调用门JMP会触发异常。
- 远CALL会压入返回信息到栈,远JMP不会,是单向跳转。
- 两者在同CPL的普通代码段跳转时,都支持64位到32位兼容模式的切换;但通过调用门跳转时,都只能进入64位长模式。
内容的提问来源于stack exchange,提问作者c00000fd
相关产品推荐
相关产品推荐

