x86_64 NASM汇编程序无法获取用户输入问题求助
问题根源:x86_64与32位Linux系统调用的寄存器约定差异
你猜的完全没错!问题的核心就是你混用了32位和64位Linux系统调用的寄存器规则,导致系统调用无法正确执行,所以程序看起来无输出直接终止。
关键差异说明
Linux下的32位x86和x86_64(amd64)架构,系统调用的触发方式和参数传递规则完全不同:
- 32位模式:用
int 0x80触发系统调用,参数依次存在eax(系统调用号)、ebx、ecx、edx这些32位寄存器中。 - x86_64模式:标准方式是用
syscall指令触发,参数依次存在rax(系统调用号)、rdi、rsi、rdx这些64位寄存器中。虽然x86_64也支持int 0x80调用32位系统调用,但会有寄存器截断、上下文切换的问题,很容易导致调用失败且无明显报错。
结合你的代码分析
你写的是x86_64汇编(针对64位系统),但全程用了32位的寄存器(eax、ebx、ecx)和int 0x80指令,系统调用无法正确识别你传递的参数(比如write调用需要的文件描述符、字符串地址、长度),所以实际执行时系统调用直接失败,但你没做错误检查,程序就直接走到exit调用退出了,看起来像是“无输出终止”。
当你把寄存器换成rax、rdi、rsi后,其实是切换到了x86_64的系统调用规则,系统能正确识别参数,所以程序正常运行。这里还要补充一句:最好把int 0x80换成syscall指令,这才是x86_64的标准系统调用触发方式,避免兼容问题。
修正后的代码示例(以_printMsg1为例)
_printMsg1: mov rax, 1 ; 64位sys_write的系统调用号(和32位一样是1,但寄存器不同) mov rdi, 1 ; 第1参数:stdout的文件描述符 mov rsi, msg1 ; 第2参数:要输出的字符串地址 mov rdx, len1 ; 第3参数:字符串长度 syscall ; 触发64位系统调用 ret
额外提示
- 64位Linux的系统调用号可以通过
man syscalls查看,大部分和32位一致,但寄存器传递规则完全不同。 - 写x86_64汇编时,尽量避免混用32位寄存器和
int 0x80,保持代码风格统一,减少调试麻烦。
内容的提问来源于stack exchange,提问作者NewInFireFox
相关产品推荐
相关产品推荐

