x64汇编实现可JIT复制的64位绝对跳转:Linux转Windows遇阻
Windows下NASM汇编64位绝对跳转的链接错误解决方法
问题场景
将Linux下的Forth解释器汇编代码移植到Windows时,原代码通过间接引用绝对地址实现跳转:
jmp [.n+0] .n: DQ pushparam ALIGN 8 doestargetlen EQU $ - doestarget pushparam: mov [r12], rbx add r12, 8
使用MSVC链接器时出现以下错误:
64th.obj : error LNK2017: 'ADDR32' relocation to '.rodata' invalid without /LARGEADDRESSAWARE:NO
原因是Windows默认启用/LARGEADDRESSAWARE,允许进程使用4GB以上内存,此时32位地址重定位无效,而原代码生成的是32位ADDR32重定位。
解决方案
方案1:显式生成64位绝对地址重定位
修改代码,显式指定64位地址引用,避免NASM生成32位重定位:
jmp qword [.n] ; 显式指定qword,确保跳转操作数是64位 .n: DQ qword pushparam ; 强制生成64位绝对地址的重定位项 ALIGN 8 doestargetlen EQU $ - doestarget pushparam: mov [r12], rbx add r12, 8
此方案保留了原有的间接跳转结构,确保代码复制到任意内存位置后,只要.n中的pushparam绝对地址正确,就能正常跳转。
方案2:寄存器加载64位绝对地址后跳转
更简洁的方式是直接将pushparam的64位绝对地址加载到寄存器,再跳转:
mov rax, qword pushparam ; 加载64位绝对地址到rax寄存器 jmp rax ALIGN 8 doestargetlen EQU $ - doestarget pushparam: mov [r12], rbx add r12, 8
NASM会为mov rax, qword pushparam生成64位立即数重定位,MSVC链接器可正常处理,且代码逻辑清晰,同样支持内存任意位置的复制执行。
额外注意事项
- 若必须限制进程使用4GB以内内存,可添加链接选项
/LARGEADDRESSAWARE:NO绕过错误,但会限制程序的内存扩展性,不推荐。 - 编译时需确保NASM使用
-f win64参数生成64位Windows目标文件:nasm -f win64 yourcode.asm -o yourcode.obj
内容的提问来源于stack exchange,提问作者pm100
相关产品推荐
相关产品推荐

