x86_64 AT&T汇编代码运行异常,疑foo函数为问题根源?
问题分析与解决
你的程序返回无效/随机退出码的核心原因不是foo函数,而是Windows平台下程序入口和退出方式不符合系统要求:
- 入口与退出机制不匹配:Windows控制台程序直接使用
_start作为入口时,无法依赖C运行时(msvcrt)的退出流程,且直接ret返回会导致程序回到系统未预期的地址,进而产生随机退出码。Windows要求程序通过调用ExitProcess函数正常终止,而非简单返回。 - foo函数本身无错误:foo的栈帧操作(push rbp、mov rsp,rbp、sub/add rsp、pop rbp、ret)是标准的x86_64函数栈帧维护逻辑,不存在问题。
解决方案一:改用C运行时入口(推荐)
将入口从_start改为main,让msvcrt自动处理程序的初始化与退出流程:
修改后的代码
;#; This file was generated by the MZ compiler. .section .data b: .space 8 a: .space 8 .section .text foo: push %rbp mov %rsp, %rbp sub $32, %rsp add $32, %rsp pop %rbp ret .global main main: push %rbp mov %rsp, %rbp sub $32, %rsp lea a(%rip), %rax movq $420, (%rax) lea b(%rip), %rax movq $42, (%rax) mov $10, %rcx mov $3, %rdx call foo add $32, %rsp pop %rbp movq $0, %rax ret
编译链接命令
可以直接用gcc简化链接(自动处理依赖库与入口):
gcc -o test.exe test.S
或者继续用ld链接(需指定kernel32库):
as .\test.S -o test.out ld -o test.exe -subsys=console test.out -L "C:\TDM-GCC-64\x86_64-w64-mingw32\lib" -lmsvcrt -lkernel32
解决方案二:手动调用ExitProcess终止程序
保留_start入口,通过调用Windows系统函数ExitProcess正常退出程序:
修改后的代码
;#; This file was generated by the MZ compiler. .section .data b: .space 8 a: .space 8 .section .text foo: push %rbp mov %rsp, %rbp sub $32, %rsp add $32, %rsp pop %rbp ret .extern ExitProcess .global _start _start: push %rbp mov %rsp, %rbp sub $32, %rsp lea a(%rip), %rax movq $420, (%rax) lea b(%rip), %rax movq $42, (%rax) mov $10, %rcx mov $3, %rdx call foo add $32, %rsp pop %rbp mov $0, %rcx ; ExitProcess的退出码参数放在rcx(x86_64 fastcall约定) call ExitProcess
编译链接命令
as .\test.S -o test.out ld -o test.exe -subsys=console test.out -L "C:\TDM-GCC-64\x86_64-w64-mingw32\lib" -lmsvcrt -lkernel32
内容的提问来源于stack exchange,提问作者Mihir Patel
相关产品推荐
相关产品推荐

