OSX теперь требует, чтобы ваш исполняемый файл имел доступный для записи сегмент данных с содержимым, чтобы он мог перемещать и связывать ваш код динамически. Не знаю почему, может быть, из-за соображений безопасности, может быть из-за нового регистра RIP. Если вы поместите туда сегмент .data (с некоторым поддельным содержимым), вы избежите ошибки «нет доступного для записи сегмента». ИМО это ошибка ld.
Что касается 64-битного системного вызова, вы можете сделать это двумя способами. GCC-стиль, который использует _syscall PROCEDURE из libSystem.dylib или raw. Raw использует инструкцию syscall, а не ловушку int 0x80. "int 0x80" - недопустимая инструкция в 64-битной версии.
«Метод GCC» позаботится о классификации системного вызова для вас, поэтому вы можете использовать те же 32-битные числа, что и в sys / syscall.h. Но если вы пойдете по-сырому, вам придется классифицировать, какой это системный вызов, ИЛИ с помощью идентификатора типа. Вот пример того и другого. Обратите внимание, что соглашение о вызовах отличается! (извинения за синтаксис NASM; газ меня раздражает)
; assemble with
; nasm -f macho64 -o syscall64.o syscall64.asm && ld -lc -ldylib1.o -e start -o syscall64 syscall64.o
extern _syscall
global start
[section .text align=16]
start:
; do it gcc-style
mov rdi, 0x4 ; sys_write
mov rsi, 1 ; file descriptor
mov rdx, hello
mov rcx, size
call _syscall ; we're calling a procedure, not trapping.
;now let's do it raw
mov rax, 0x2000001 ; SYS_exit = 1 and is type 2 (bsd call)
mov rdi, 0 ; Exit success = 0
syscall ; faster than int 0x80, and legal!
[section .data align=16]
hello: db "hello 64-bit syscall!", 0x0a
size: equ $-hello
проверьте http://www.opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/syscall_sw.h для получения дополнительной информации о том, как набирается системный вызов.