【发布时间】:2015-02-20 21:34:44
【问题描述】:
我正在尝试在汇编中进行一些基本的系统调用(OSX 上的 NASM 中的 x86-64),但到目前为止还没有成功。
到目前为止,我在网上看到的唯一示例是从标准输入读取或写入标准输出,例如:
global main
section .text
main:
call write
write:
mov rax, 0x2000004
mov rdi, 1
mov rsi, message
mov rdx, length
syscall
section .data
message: db 'Hello, world!', 0xa
length: equ $ - message
但是,当我尝试使用相同的模式进行另一个系统调用时,它不起作用(它说Bus error: 10):
global main
section .text
main:
call mkdir
mkdir:
mov rax, 0x2000136 ; mkdir system command number
mov rdi, rax ; point destination to system command
mov rsi, directory ; first argument
mov rdx, 755 ; second argument
syscall
section .data
directory: db 'tmp', 0xa
调用系统命令的一般结构是什么(理想情况下在 NASM 中的 OSX 上)?
基本上你应该做的是在这里找到你想要的系统调用:http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master。所以“写”的看起来像这样:
4 AUE_NULL ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); }
也就是说:
- 系统调用号:4
- 参数数量:3(文件描述符、字符串/缓冲区的内存地址、缓冲区长度)
所以我开始认为一般模式是这样的:
rax: system call number
rdi: maybe? point to system call ("destination index"), but why the `1` in the write example?
rsi: first argument to system call ("source index", the string in this case)
rdx: second argument to system call
rcx: third argument (if necessary, but not in the system write case)
那么就好像您可以直接映射任何系统命令。所以mkdir:
136 AUE_MKDIR ALL { int mkdir(user_addr_t path, int mode); }
将被翻译成:
rax: 0x20000136 ; 136 + 20000000
rdi: i dunno, maybe `rax`?
rsi: directory (first argument)
rdx: 755 (mode, second argument)
但是是的,那行不通。
我做错了什么?如何执行此操作的一般模式是什么,以便我可以在syscalls.master 中的任何其他系统命令上对其进行测试?你能描述一下不同寄存器在这里扮演的角色吗?这将有助于澄清我的想法。
【问题讨论】:
-
我不会假装对 OSX 有任何了解,但 write 调用中的 '1' 可能是标准输出的文件描述符。这告诉我 rdi 是第一个应该是目录的参数,而 rsi 是第二个应该是模式的参数。如果我错了,请告诉我,我会闭嘴。
-
是的,我不知道,你是怎么弄清楚这些东西的? (比如有不同操作系统的文件描述符值列表吗?)
-
Posix 标准 stdout = 1,stderr = 2,stdin = 0。http://pubs.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html.
标签: macos assembly nasm x86-64