所以我需要使用x86_64程序集再次删除目录中的文件。这是我的代码,我知道这很糟糕。我的问题是每个系统调用都是单独工作的(我可以单独删除目录或文档),但是一旦我将它们合并在一起,它就不起作用了。 #edit:正如@fuz指出的那样,问题不够具有描述性。所以我想要它打开包含名为“test.txt”的文件的目录,删除该文件,然后删除包含该文件的目录。但是当我用nasm编译它时它就退出了程序。我正在使用Linux薄荷
global _start
section .text
_start:
;open directory
mov rax, 2 ;sys_open
mov rdi, dir ;pointer to the directory
mov rsi, 0 ;read only
syscall
;delete document
mov rax, 87 ;sys_unlink
mov rdi, doc ;points to the document
syscall
;delete directory
mov rax, 84 ;sys_rmdir
mov rdi, dir
syscall
_exit:
mov rax, 60
mov rdi, 80
syscall
section .data
dir: db 'test',0
doc: db 'test.txt',0
你的问题不在于汇编,而在于理解基本的POSIX / Unix文件操作系统调用。 open("dir")
以后不会相对于该目录进行unlink / rmdir系统调用,它们仍然相对于您当前的工作目录。你可以用chdir()
改变它。
(而且使用C语言比使用asm更容易。对于大多数系统调用,glibc包装器是微不足道的,并将所有args传递给内核。当不是这种情况时,Linux手册页的NOTES部分记录了这一点。 )
系统调用相对于打开的目录文件描述符(而不是CWD)执行操作,其名称为传统的系统调用名称添加了...at
后缀。该文档使用C语法来描述系统调用,但是给定ABI,它告诉您如何在asm中调用它们。
unlinkat(int dirfd, const char *pathname, int flags)
rmdir
实际上是用unlinkat(fd, path, AT_REMOVEDIR)
完成的。 (否则,使用flags=0
,unlinkat表现得像常规的unlink
)。linkat
,symlinkat
,readlinkat
,statat
,mkdirat
,execveat
,...renameat
,以及一个有趣的renameat2
,它带有标志,允许你在同一个文件系统上原子地交换两个路径名。openat
man page解释了为什么这些at
系统调用首先存在于Rationale for openat()
下 - 避免readdir和open之间的竞争条件,如果其他人rename
s是路径的目录组件。由于chdir()
是按进程而不是每个线程,因此允许不同的线程同时在不同的目录中执行相对的操作。就像Jester所说的那样,使用strace find test -name 'test.txt' -delete
或类似的东西来看看如何通过qazxswpoi,open(O_DIRECTORY)
和getdents
实际递归目录。
unlinkat
是在Linux上构建POSIX getdents
接口的原始系统调用。手册页记录了这一点。在asm中,你可以使用对readdir
的libc函数调用,或者你必须自己使用readdir
。
或者因为你实际上没有递归,只是硬编码一些相对路径,你可以只做getdents
和unlink("test/test.txt")
系统调用。