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

5kgi1eie  于 2022-11-13  发布在  Linux
关注(0)|答案(1)|浏览(211)

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

mov rax, 85
mov rdi, path
mov rsi, 400
syscall

开场白:

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

书写:

mov rax, 1
mov rdi, r8
mov rsi, output
mov rdx, length
syscall

在我完成这些步骤后,我自然地关闭了文件,但是我无法向其追加内容,每次我执行这些操作时,它只是重写了文件的内容,但例如,我计算了前n个素数,并将它们存储在某个内存块中,现在我想将这n个素数写入文件,但如果不追加更多行,我就无法这样做。
另外,是否有办法不在rdx中指定write的字符串长度,而是用/0来终止该字符串?

i2loujxw

i2loujxw1#

O_APPEND本身意味着O_RDONLY(因为它是0),而不是O_WRONLYO_RDWR。打开只读的append通常没有用。在C中,你需要OR多个标志来得到一个文件描述符,你可以用它来写在文件的结尾,即使它的长度被你写以外的东西改变了。
要追加到文件中,请使用O_APPEND = 0x400标志作为rsi中的int flags参数。它是一个十六进制值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

因此,这应该可行:

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

我添加了这三个值,以便在文件不存在时创建它,或者在文件存在时以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中。内核系统调用在文件描述符上读取/写入的数据为buffer + length,只有路径名为C隐式长度字符串。

相关问题