GNU汇编中使用write系统调用写入文件却为空的问题排查
问题分析与解决方案
你的汇编代码中,open系统调用的标志参数仅设置了O_CREAT(八进制0100),这是导致写入失败的核心原因:
- 单独使用
O_CREAT时,open默认会以只读模式打开文件(隐含O_RDONLY),此时得到的文件描述符没有写入权限,后续的write调用实际执行失败(只是你未检查系统调用返回值,没发现这个错误)。 - 当你把文件描述符换成1(标准输出)或2(标准错误)时,这两个描述符本身就具备写入权限,所以
write能正常输出到终端。
修复步骤
1. 修改open的标志参数
在O_CREAT基础上添加写入相关的标志:
O_WRONLY(八进制01):以只写模式打开文件O_TRUNC(八进制01000):如果文件已存在,清空原有内容(可选,根据需求添加)
示例:将mov rsi, 0100改为mov rsi, 0101(O_CREAT | O_WRONLY),或者mov rsi, 010101(O_CREAT | O_WRONLY | O_TRUNC)。
2. 补充错误检查(可选但推荐)
系统调用可能因权限不足等原因失败,添加检查逻辑可以快速定位问题:
open调用后,若返回值rax小于0,说明调用失败,直接退出并返回错误码。
修正后的完整代码
.global _start .intel_syntax noprefix .text _start: /* 创建并以只写模式打开文件 */ mov rax, 2 // open系统调用号 lea rdi, [rip+file] // 文件路径 mov rsi, 0101 // O_CREAT | O_WRONLY mov rdx, 0700 // 文件权限 syscall /* 检查open是否成功 */ cmp rax, 0 jl exit_error // fd小于0则跳转到错误处理 mov rdi, rax // 传递文件描述符给write lea rsi, [rip+message] // 写入内容的缓冲区指针 mov rdx, 13 // 写入内容长度 mov rax, 1 // write系统调用号 syscall /* 可选:关闭文件(进程退出时系统会自动关闭,但显式关闭是好习惯) */ mov rax, 3 // close系统调用号 syscall exit_success: mov rax, 60 // exit系统调用号 mov rdi, 0 // 正常退出码 syscall exit_error: mov rax, 60 mov rdi, 1 // 错误退出码 syscall .data message: .ascii "Hello sailor\n" // 要写入的内容 file: .asciz "main" // 空终止文件名
额外说明
- 如果需要保留文件原有内容并在末尾追加写入,可以把标志换成
O_CREAT | O_WRONLY | O_APPEND(八进制0201)。 - 所有标志的八进制值对应Linux系统定义的宏,可通过
man 2 open查看完整标志列表。
内容的提问来源于stack exchange,提问作者Jack Delahunt
相关产品推荐
相关产品推荐

