编译Win64汇编代码时遇IMAGE_REL_AMD64_ADDR32错误求助
解决汇编编译错误:relocation truncated to fit: IMAGE_REL_AMD64_ADDR32 against `.data'
错误原因
你的代码和编译环境完全不匹配:
- 代码是Linux 32位汇编:依赖
int 0x80调用Linux系统调用,使用32位寄存器(eax/ebx/ecx/edx),这套逻辑在Windows系统下完全无效——Windows不支持int 0x80的系统调用方式。 - 编译目标是Windows 64位(win64):64位PE程序的地址是64位宽度,32位指令里的地址引用(比如
mov ecx, msg)会触发32位重定位截断错误,因为64位进程的.data段地址无法用32位偏移完整表示。
解决方案
根据需求提供两种可行方案:
方案1:编写Windows 64位标准汇编代码
改用Windows API调用,适配64位指令集和调用约定:
section .data msg db 'Hello, world!', 0dh, 0ah ; 包含回车换行的字符串 msg_len equ $ - msg ; 计算字符串长度 section .text global main ; 声明需要调用的Windows API extern GetStdHandle, WriteConsoleA, ExitProcess main: ; 1. 获取标准输出控制台句柄(STD_OUTPUT_HANDLE = -11) mov rcx, -11 call GetStdHandle ; 2. 调用WriteConsoleA写入字符串 ; Win64调用约定:前4个参数用rcx/rdx/r8/r9传递,栈要对齐到16字节 mov rcx, rax ; 第1个参数:控制台句柄 mov rdx, msg ; 第2个参数:字符串指针 mov r8, msg_len ; 第3个参数:字符串长度 sub rsp, 16 ; 分配影子空间+对齐栈(Win64要求) mov r9, rsp ; 第4个参数:接收实际写入字节数的指针(这里忽略结果) call WriteConsoleA add rsp, 16 ; 恢复栈空间 ; 3. 调用ExitProcess退出程序 mov rcx, 0 ; 退出码为0 call ExitProcess
对应的编译脚本(需要链接Windows kernel32库):
all: nasm -o asm.o -f win64 main.asm ld asm.o -o asm.exe -lkernel32 -subsystem:console
方案2:编译为Windows 32位程序
如果想贴近原代码结构,可改为32位Windows汇编,调用32位API:
section .text global _main ; 声明32位Windows API(函数名带@参数个数后缀) extern _GetStdHandle@4, _WriteConsoleA@20, _ExitProcess@4 _main: ; 1. 获取标准输出句柄 push -11 ; STD_OUTPUT_HANDLE call _GetStdHandle@4 ; 2. 调用WriteConsoleA写入字符串 push 0 ; 参数5:保留的指针(忽略实际写入字节数) push msg_len ; 参数4:字符串长度 push msg ; 参数3:字符串指针 push eax ; 参数2:控制台句柄 call _WriteConsoleA@20 ; 3. 退出程序 push 0 call _ExitProcess@4 section .data msg db 'Hello, world!', 0dh, 0ah msg_len equ $ - msg
对应的编译脚本:
all: nasm -o asm.o -f win32 main.asm ld asm.o -o asm.exe -lkernel32 -subsystem:console
内容的提问来源于stack exchange,提问作者Golden Star
相关产品推荐
相关产品推荐

