Consider this assembly code on x86-64 MacOS:
global start
section .text
start:
mov rax, 0x02000005 ; MacOS syscall: "open"
mov rdi, filename ; open; 1st parameter: file path
mov rsi, 0 ; open; 2nd parameter: flags
mov rdx, 0 ; open; 3rd parameter: in case of a newly created file, the file permissions
syscall
mov rdi, rax ; set the return value of open (the file descriptor or the error code)
; as the 1st parameter of the next syscall, "exit": exit status
mov rax, 0x02000001 ; MacOS syscall: "exit"
syscall
section .data
filename: db "doesntexist", 0 ; a non-existing filename
It calls just "open" and then "exit", returning the return code of the "open" syscall as the exit status.
For convenience, here's how to assemble and run it: nasm -f macho64 simple.asm && ld simple.o -static -o simple && ./simple. And right after running, to see the exit status: echo $?.
What surprises me, is that as of MacOS Monterey (12.2.1(21D62)), this program prints out 2 instead of a negative number converted to the exit status range. (Returning -1 would generate the exist status of 255; this is easy to test, tweaking above code, but I also made separately sure that the rax register on return is actually in the low positive range.) "open" is supposed to return a file descriptor or an error code, but a positive number corresponding to the file descriptor of stderr doesn't look like either of those. To be sure that the code above is working just touch doesntexist, run again and see that it returns a valid file descriptor of 3.
Officially, MacOS supports only doing syscalls through the OS-provided API, not directly via an ABI like this. Is this just a case of undocumented/unstable behaviour of MacOS syscalls, or do I have a mistake or a misunderstanding somewhere?
Edit: In the comments, there was a valid concern of whether the return value was turned from negative to positive in the conversion from the return value of the syscall (a 64-bit register) to the exit status of the process (0-255). Here's an attempt to prove that this isn't the case:
global start
section .text
start:
mov rax, 0x02000005 ; MacOS syscall: open
mov rdi, filename ; open; 1st parameter: file path
mov rsi, 0 ; open; 2nd parameter: flags
mov rdx, 0 ; open; 3rd parameter: in case of a newly created file, the file permissions
syscall
cmp rax, 0 ; if the result was negative or positive
mov rax, 0x02000001 ; MacOS syscall: exit
jg ok ; if the result was positive, jump to "ok" and return 99
error:
mov rdi, 66
syscall
ok:
mov rdi, 99
syscall
section .data
filename: db "doesntexist", 0 ; a non-existing filename
The process returns 99, which means that rax was positive.