使用sys_write的汇编代码为何无输出且未触发段错误?
问题分析:汇编代码无输出也无段错误的原因
先贴出你的汇编代码方便分析:
.SECTION .data msg: .string "AAAA" .SECTION .text .globl _start _start: mov $1, %rax ; sys_write 系统调用号 mov $1, %rdi ; 文件描述符:stdout mov msg, %rsi ; 错误:传递的是字符串内容而非地址 mov $4, %rdx ; 写入长度 syscall
1. 为什么没有输出?
核心问题在mov msg, %rsi这一行。以x86-64的NASM语法为例,直接写符号msg会引用该地址存储的数据,而不是地址本身。你的msg指向字符串"AAAA"的首字节(十六进制值0x41),所以这行代码会把0x41加载到%rsi寄存器里——但sys_write系统调用要求%rsi是指向输出缓冲区的指针。
你传递的0x41是用户空间无法访问的低地址,sys_write会直接执行失败(返回值为-EFAULT,对应错误码14),自然不会有任何输出。正确的写法应该是用$msg获取符号地址,或者用lea指令加载有效地址:
mov $msg, %rsi ; 正确:将msg的地址加载到rsi ; 或者更高效的写法 lea msg, %rsi
2. 为什么没有触发段错误,也不需要显式调用sys_exit?
在Linux的x86-64环境中,_start是程序的特殊入口点,和普通函数逻辑不同:
- 当
_start的指令流执行完毕后,内核会自动接管进程的退出流程,调用exit_group系统调用终止整个进程,不需要你显式写sys_exit调用。 - 至于没触发段错误:虽然
syscall之后没有指令,CPU会尝试执行下一个内存位置的代码,但这个位置要么属于.text段末尾(可能被内核标记为不可执行),要么是未映射的内存,但内核会在进程入口点执行完毕后直接终止进程,不会让非法执行触发的段错误暴露给用户。
总结一下:内核帮你处理了退出,而你的sys_write因为参数错误执行失败,所以才会出现既没输出也没崩溃的情况。
内容的提问来源于stack exchange,提问作者Dan Joe
相关产品推荐
相关产品推荐

