NASM x86_64长模式下无直接RIP访问获取运行时重定位偏移方法问询
解决方案
方案1:修正NASM配置启用RIP寻址(优先选择)
NASM本身完全支持x86_64长模式下的RIP相对寻址,不识别rip关键字的问题绝大多数场景下是未在汇编文件头部声明64位模式。只需要在start.asm最顶部添加BITS 64声明,就可以正常使用RIP寻址代码:
lea rax, [rip + 0x1020304] sub rax, 0x1020304 ; rax 中即为加载偏移量
若NASM版本低于2.10,升级到2.10及以上版本即可支持该语法。
方案2:使用call指令特性获取运行时地址(无RIP依赖)
如果确实无法使用RIP寻址,可以利用x86架构call指令的固有特性实现,不需要依赖任何寄存器关键字:
; 确保此时rsp已经指向合法的栈空间,若未初始化可先临时设置栈指针 call _get_current_ip _get_current_ip: pop rax ; 此时rax存储的是`_get_current_ip`标签的实际运行时内存地址 sub rax, _get_current_ip ; 减去该标签在静态ELF中的链接地址,得到的差值就是所需的加载偏移量
原理:call指令执行时会自动将下一条指令的地址压入栈中,pop操作直接取出该地址,即可得到当前代码的实际加载位置,计算差值即可得到偏移。
方案3:读取Multiboot2标准tag直接获取加载基地址
GRUB加载符合Multiboot2规范的内核时,会在返回的信息结构中包含加载基地址tag,类型值为21(MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR),遍历Multiboot2信息块读取该tag的addr字段值,减去ELF静态链接基地址即可得到偏移,该方案不需要编写汇编代码,用C语言即可实现。
内容的提问来源于stack exchange,提问作者phip1611
相关产品推荐
相关产品推荐

