x86汇编代码打印字符h无输出 运行异常问题求助
代码存在的问题
- 系统调用规范完全混乱:你同时混用了32位x86的
int $0x80调用约定和64位x86_64的syscall约定,二者的系统调用号、传参寄存器完全不兼容。32位Linux下write的系统调用号是4,用ebx/ecx/edx传参,通过int $0x80触发;64位Linux下write的系统调用号是1,用rdi/rsi/rdx传参,通过syscall触发,你的代码把二者混着写,自然不可能正常执行。 - write系统调用需要的第二个参数是字符串的内存地址,你直接把字符
h的ASCII值0x68压栈,但根本没有把这个值所在的栈地址传给对应的寄存器,相当于你给内核传了个无效的字符串地址。 - 你设置的输出长度是5,但是你只需要打印1个字符,长度参数完全错误。
- 你在执行系统调用前就执行了
movq %rbp, %rsp,直接把刚压入栈的0x68数据清掉了,栈恢复到了刚进入main函数的状态,之前的push操作完全无效。 _start入口处的mov %eax, %edi完全无用,程序刚启动时%eax的值是不确定的,你也没有给main函数传参的需求,这行代码是冗余的。
修正后的64位汇编代码
.section .text .global _start _start: call main # 64位exit系统调用,调用号60,退出状态0 movl $60, %eax movl $0, %edi syscall main: pushq %rbp movq %rsp, %rbp # 把'h'压入栈 push $0x68 # 64位write系统调用,调用号1 movl $1, %eax # 第一个参数:标准输出文件描述符=1 movl $1, %edi # 第二个参数:字符串地址,即刚压入字符的栈顶地址 movq %rsp, %rsi # 第三个参数:输出长度为1 movl $1, %edx syscall # 恢复栈帧 movq %rbp, %rsp popq %rbp ret
编译运行说明
你原来的编译命令可正常使用:
as $(BIN_DIR)/assembly.asm -o $(BIN_DIR)/a.o ld $(BIN_DIR)/a.o -o $(BIN_DIR)/a
运行生成的a程序即可在终端输出字符h。
内容的提问来源于stack exchange,提问作者ilittlebig
相关产品推荐
相关产品推荐

