【发布时间】:2020-04-22 02:05:43
【问题描述】:
我很难找到在 MacOS 上编写 64 位程序集的好文档。
64-bit SysV ABI 在 A.2.1 节中说了以下内容,this SO post 引用了它:
系统调用是通过 syscall 指令完成的。内核破坏 注册 %rcx 和 %r11。
从系统调用返回,寄存器 %rax 包含 系统调用。 -4095 和 -1 之间的值表示错误, 它是-errno。
这两句话在 Linux 上是可以的,但在 macOS Sierra 上是错误的,代码如下:
global _start
extern _exit
section .text
_start:
; Align stack to 16 bytes for libc
and rsp, 0xFFFFFFFFFFFFFFF0
; Call write
mov rdx, 12 ; size
mov rsi, hello ; buf
mov edi, 1 ; fd
mov rax, 0x2000004 ; write ; replace to mov rax, 0x1 on linux
syscall
jc .err ; Jumps on error on macOS, but why?
jnc .ok
.err:
mov rdi, -1
call _exit ; exit(-1)
.ok:
; Expect rdx to be 12, but it isn't on macOS!
mov rdi, rdx
call _exit ; exit(rdx)
; String for write
section .data
hello:
.str db `Hello world\n`
.len equ $-hello.str
使用 NASM 编译:
; MacOS: nasm -f macho64 syscall.asm && ld syscall.o -lc -macosx_version_min 10.12 -e _start -o syscall
; Linux: nasm -f elf64 syscall.asm -o syscall.o && ld syscall.o -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o syscall
在 macOS 上运行:
./syscall # Return value 0
./syscall >&- # Return value 255 (-1)
我发现:
- 系统调用返回
errno并设置错误时的进位标志,而不是在rax中返回-errno -
rdx寄存器被syscall破坏 - 在 Linux 上,一切正常
为什么rdx 被破坏了?为什么系统调用不返回-errno?我在哪里可以找到真正的文档?
我发现有人谈论系统调用错误的进位标志的唯一地方是here
【问题讨论】:
-
因为这是标题为A.2 AMD64 Linux Kernel Conventions的部分的摘录?
-
好问题。我对您链接到的the SO post 进行了快速编辑,因此它不再声称该部分也适用于 *BSD(它之前没有提到 OS X,达尔文算作 *BSD 吗?@Jean-BaptisteYunès,你呢?碰巧知道 FreeBSD 或 OpenBSD 在 x86-64 上是否使用与 Linux 或 OS X 相同的约定?)
-
@PeterCordes 唉,似乎不同的 BSD 风格不使用相同的 ABI。 FreeBSD 似乎与 Linux 兼容。 Minix 和 NetBSD 是兼容的。很难找到有关它的信息(多年来我没有读过这些东西,所以可能我只是不知道在哪里搜索)。还有一个unix.stackexchange.com/questions/3322/…
标签: macos assembly x86-64 system-calls abi