x86-64汇编报错:IMAGE_REL_AMD64_ADDR32 against '.bss' 求解
解决Win64下NASM+GNU ld访问.bss变量的重定位截断错误
问题分析
你遇到的Relocation truncated to fit: IMAGE_REL_AMD64_ADDR32 against '.bss'错误,和变量尺寸无关——handle resq 1确实能存下64位的HANDLE(PVOID)。错误根源是Win64 PE程序的默认基地址超出32位范围,而你用的绝对寻址方式会触发32位重定位,导致地址截断。
Win64程序的默认加载基地址是0x140000000,这个值大于32位能表示的最大值0xFFFFFFFF。当你用mov [handle], rax这种绝对寻址时,GNU ld会尝试生成IMAGE_REL_AMD64_ADDR32重定位(32位绝对地址),但目标地址超过32位,因此报错。
解决方案
最直接的修复是改用RIP相对寻址,这也是Win64 ABI推荐的全局变量访问方式。NASM中可以通过rel前缀实现:
修改代码中的两处错误位置:
; 错误位置1 修改为 mov [rel handle], rax ; 错误位置2 修改为 mov rcx, [rel handle]
为什么这样有效?
RIP相对寻址是基于当前指令地址的32位有符号偏移,Win64程序的代码段和数据段(包括.bss)之间的偏移不会超过2GB,因此32位有符号偏移完全能覆盖。这种方式会生成IMAGE_REL_AMD64_REL32重定位,避免了32位绝对地址的截断问题。
验证步骤
修改后重新执行编译链接命令:
nasm -f win64 main.asm ld main.o -o main.exe -e _start C:/Windows/System32/kernel32.dll
此时链接应该能正常完成,程序也能正确运行。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

