如何使用 x86-64 Linux 系统调用附加到文件?

мај*_*мех 0 linux assembly x86-64 nasm system-calls

我正在创建一个文件,然后使用系统调用打开它。

创建:

mov rax, 85
mov rdi, path
mov rsi, 400
syscall
Run Code Online (Sandbox Code Playgroud)

开幕:

mov rax, 2
mov rdi, path
mov rsi, 2 ; I found somewhere that I should use 400 to append
syscall
mov r8, rax ; save the file handle
Run Code Online (Sandbox Code Playgroud)

写作:

mov rax, 1
mov rdi, r8
mov rsi, output
mov rdx, length
syscall
Run Code Online (Sandbox Code Playgroud)

完成这些步骤后,我自然地关闭了文件,但是我无法附加到它,每次执行这些操作时它只会重写文件的内容,但是例如我计算了前 n 个素数并将它们存储在一些内存块,现在我想在文件中写下这 n 个素数,但如果不附加更多行,我就无法这样做。

还有一种方法可以不为writein指定字符串的长度rdx,而是让字符串以/0?

zx4*_*485 5

对于追加到一个文件中使用的O_APPEND = 0x400标志作为int flags参数rsi。所以你很接近:它是一个十六进制 400 的值,而不是你怀疑的十进制 400。

以下是int flags十六进制原始值的列表:

O_ACCMODE                        = 0x3
O_APPEND                         = 0x400
O_ASYNC                          = 0x2000
O_CLOEXEC                        = 0x80000
O_CREAT                          = 0x40
O_DIRECT                         = 0x4000
O_DIRECTORY                      = 0x10000
O_DSYNC                          = 0x1000
O_EXCL                           = 0x80
O_FSYNC                          = 0x101000
O_LARGEFILE                      = 0x0
O_NDELAY                         = 0x800
O_NOATIME                        = 0x40000
O_NOCTTY                         = 0x100
O_NOFOLLOW                       = 0x20000
O_NONBLOCK                       = 0x800
O_RDONLY                         = 0x0
O_RDWR                           = 0x2
O_RSYNC                          = 0x101000
O_SYNC                           = 0x101000
O_TRUNC                          = 0x200
O_WRONLY                         = 0x1
Run Code Online (Sandbox Code Playgroud)

所以这应该有效:

mov   rax, 2
lea   rdi, [rel path]
mov   rsi, 0x441        ; O_CREAT| O_WRONLY | O_APPEND
mov   edx, 0q666        ; octal permissions in case O_CREAT has to create it
syscall
mov   r8, rax      ; save the file descriptor
Run Code Online (Sandbox Code Playgroud)

如果文件不存在,我添加了三个值来创建文件,或者如果存在则以 write_only 模式打开它。您可以将它们定义为汇编equ时常量,以便您可以mov esi, O_CREAT| O_WRONLY | O_APPEND在源代码中实际编写。

此外,确保在包含 O_CREAT 时为第三个参数(权限)提供值。否则,该文件可能会使用随机垃圾创建其权限,包括可能的 setuid + exec。通常,您传递八进制666(NASM 0q666) 并让用户的 umask 取消其他组和可选组的写权限。

如果您实际上不想在它不存在的情况下 open 来创建它,请省略 O_CREAT。然后它会返回-ENOENT


还有没有办法在 rdx 中不指定字符串的长度,而是让字符串以 /0 结尾?

简而言之:不。
创建一个strlen函数并将结果传递给rdx. 内核系统调用将要在文件描述符上读取/写入的数据作为缓冲区 + 长度,仅将路径名作为 C 隐式长度字符串。

  • 郑重声明:“mov rdi, path”是将标签地址放入寄存器的蹩脚方法。使用 `lea rdi, [rel path]` 作为标准的位置无关方式,或者使用 `mov edi, path` 作为优化的 Linux 非 PIE 可执行方式。您基本上永远不想使用 64 位绝对地址;这是低效的。[如何在 GNU 汇编器中将函数或标签的地址加载到寄存器中](/sf/ask/4004840871/) (2认同)