如何在64位模式下不使用64位寄存器执行x86远跳转?
64位模式下无64位寄存器依赖的远跳转实现
核心限制说明
64位AMD64架构不支持立即数形式的64位远跳转(jmp far seg:64bit_offset),指令集没有对应的编码格式,这是你之前汇编报错的原因。必须通过内存中的10字节远指针结构完成跳转,结构为:
- 低2字节:目标段选择子(小端序)
- 高8字节:64位目标虚拟地址(小端序)
实现方案(NASM + Linux内联汇编)
1. 静态数据区存储远指针(无寄存器修改)
利用RIP相对寻址直接访问静态数据区的远指针,全程不修改任何64位寄存器:
bits 64 default rel ; 启用RIP相对寻址,自动生成偏移 section .data ; 定义远指针:段选择子 + 64位目标地址 target_far_ptr: dw 0x33 ; Linux用户态代码段选择子(内核态用0x08) dq 0xdeadbeefdeadbeef ; 你要跳转的64位目标地址 section .text global main main: ; 执行远跳转,无寄存器依赖 jmp far [target_far_ptr]
2. C内联汇编版本
如果需要在C代码中嵌入,同样利用RIP相对寻址,避免修改64位寄存器:
#include <stdint.h> // 定义远指针结构(小端序) static const uint8_t far_ptr[10] = { 0x33, 0x00, // 用户态代码段选择子0x33(小端存储) 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde // 目标地址0xdeadbeefdeadbeef(小端存储) }; int main() { __asm__ volatile ( "jmp far [rip + %0]" // RIP相对寻址访问远指针 : : "i"((intptr_t)&far_ptr - (intptr_t)__builtin_extract_return_addr(__builtin_return_address(0)) - 5) // 计算RIP到far_ptr的偏移:-5是因为jmp指令长度为5字节,RIP指向指令后地址 : "memory" ); return 0; }
关键注意事项
- 段选择子必须匹配当前特权级:Linux用户态用
0x33,内核态用0x08,错误的选择子会触发异常。 - 远指针必须按小端序存储,x86架构默认是小端,直接按字节定义即可。
- RIP相对寻址属于64位模式的默认寻址方式,仅读取RIP值(不修改),符合“不破坏64位寄存器”的要求。
内容的提问来源于stack exchange,提问作者suncowiam
相关产品推荐
相关产品推荐

