如何使用x86-64 Linux系统调用实现文件追加写入及相关疑问
你的Linux汇编文件操作问题解答
一、为什么追加写入总是覆盖内容?
这个问题的根源是你打开文件时用错了flags参数,把创建文件的权限mode和打开模式的flags搞混啦:
- 你用
mov rsi, 2调用sys_open,这里的2对应O_WRONLY(只写模式),这种模式下写入操作会从文件起始位置开始,直接覆盖原有内容,自然没法追加。 - 你听到的“用400实现追加”是个误解——400是创建文件时的权限值(对应八进制的
0400,表示所有者只读),和打开文件的追加flag完全不是一回事。
要实现追加写入,打开文件时必须在flags里加上O_APPEND(十进制64,十六进制0x40),正确的打开代码应该是这样:
; 打开已存在的文件,以追加模式写入 mov rax, 2 ; sys_open的系统调用号 mov rdi, path ; 文件路径的地址 mov rsi, 0x42 ; O_WRONLY | O_APPEND (2 | 64 = 66) syscall mov r8, rax ; 保存文件句柄(记得检查返回值,负数表示出错哦)
另外,其实你可以把「创建文件」和「打开文件」合并成一次sys_open调用,省掉多余的步骤:
; 一次性完成文件创建+追加打开,权限设为0400 mov rax, 2 mov rdi, path mov rsi, 0x242 ; O_WRONLY | O_CREAT | O_APPEND(2 + 0x200 + 0x40 = 578) mov rdx, 0400o ; 文件权限(八进制,只有当指定O_CREAT时这个参数才生效) syscall mov r8, rax
二、能不能用\0终止字符串,不用手动指定rdx长度?
可惜的是,Linux的sys_write系统调用本身并不支持以\0作为字符串终止符。它是非常底层的调用,只会严格按照你在rdx里传入的字节数写入数据,不会主动扫描字符串去找末尾的\0。
如果想要实现类似C语言里puts那种自动识别\0的功能,你得自己先写一段代码计算字符串长度,比如这样:
; 计算以\0结尾的字符串长度,结果存到rdx中 mov rdx, 0 mov rcx, output ; output是你的字符串起始地址 count_loop: cmp byte [rcx], 0 ; 检查当前字节是否为\0 je count_finish ; 是\0就跳出循环 inc rdx ; 长度加1 inc rcx ; 指针移到下一个字节 jmp count_loop count_finish: ; 现在rdx就是字符串长度,可以调用sys_write了 mov rax, 1 mov rdi, r8 mov rsi, output syscall
这样就能通过\0来自动确定写入长度啦。
内容的提问来源于stack exchange,提问作者мајдејсаремех
相关产品推荐
相关产品推荐

