如何使用ml64汇编链接支持LARGEADDRESSAWARE的纯64位程序?
问题根因
- 关于
.data/.code伪指令的疑问:官方文档标注为32位使用属于文档更新滞后,ml64完全支持这两个伪指令用于64位程序开发,无需替换。 - 关于LNK2017报错的原因:x64指令集的RIP相对寻址仅支持固定常量偏移,不支持叠加通用寄存器值,你写的
lea r8,[text+rsi]会被ml64判定为需要使用32位静态基地址+寄存器偏移的寻址模式,对应ADDR32重定位。开启/LARGEADDRESSAWARE后程序允许加载到4GB以上地址空间,32位基地址无法覆盖全地址范围,链接器直接拦截非法重定位报错。 - 为什么
lea r8,[text+1]可以正常链接:该写法仅包含固定常量偏移,ml64会自动生成RIP相对寻址,不需要ADDR32重定位,兼容全64位地址空间。 - 关于
/LARGEADDRESSAWARE:NO的效果:64位程序开启该选项后,系统会将程序的加载地址、内存分配范围都限制在低4GB空间,无法使用完整64位寻址能力,不满足你的需求,不要用该配置。
修复方案
修改汇编代码里的寻址写法,先拿到text的64位地址,再叠加寄存器偏移即可,两种常用写法都可以:
写法1:用RIP相对寻址先取text地址
.data text db 'xHello 64', 0 .code main proc mov rsi,1 lea rax, [text] ; 自动用RIP相对寻址取text的64位地址,无32位重定位 lea r8, [rax + rsi] ; 寄存器+寄存器寻址,无重定位问题 ret main endp end
写法2:直接加载text的64位绝对偏移
.data text db 'xHello 64', 0 .code main proc mov rsi,1 mov rax, offset text ; 生成64位重定位,加载text的全地址到rax lea r8, [rax + rsi] ret main endp end
修改后用link /entry:main /machine:x64 /LARGEADDRESSAWARE test.obj即可正常链接,生成的程序支持完整64位寻址,无4GB空间限制。
内容的提问来源于stack exchange,提问作者Vikors
相关产品推荐
相关产品推荐

