Последовательные системные вызовы sys_write не работают должным образом, ошибка NASM в OS X?
Я пытаюсь изучить сборку MacOS с помощью NASM и не могу заставить работать тривиальную программу. Я пробую вариант "Hello, World", где два слова независимо вызываются макросом. Мой исходный код выглядит так:
%macro printString 2
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
mov rsi, %1
mov rdx, %2
syscall
%endmacro
global start
section .text
start:
printString str1,str1.len
printString str2,str2.len
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
str1: db "Hello,",10,
.len: equ $ - str1
str2: db "world",10
.len: equ $ - str2
Ожидаемый результат должен быть:
$./hw
Hello,
World
$
Вместо этого я получаю:
$./hw
Hello,
$
Что мне не хватает? Как мне это исправить?
РЕДАКТИРОВАТЬ: я собираю и работаю со следующими командами:
/usr/local/bin/nasm -f macho64 hw.asm
ld -macosx_version_min 10.7.0 -lSystem -o hw hw.o
./hw
1 ответ
У NASM 2.11.08 и 2.13.02+ есть ошибки с macho64
выход. То, что вы наблюдаете, кажется, что-то, что я видел специально с 2.13.02+ недавно, когда использовал абсолютные ссылки. В последней связанной программе применены неверные исправления, поэтому ссылка на str2
это неверно. Неправильное исправление заставляет нас печатать память, которая не str2
,
NASM имеет отчет об ошибке в своей системе. Я добавил конкретный пример этой ошибки на основе кода в вопросе. Надеемся, что разработчики NASM смогут воспроизвести ошибку и создать исправление.
Обновление: по состоянию на июнь 2018 года, я считаю, что в NASM достаточно много повторяющихся ошибок и регрессий, поэтому я не рекомендую NASM на данный момент для разработки Macho-64.
Еще одна рекомендация, которую я имею для разработки Macho-64, - использовать относительную адресацию RIP, а не абсолютную. Относительная RIP-адресация используется по умолчанию для 64-битных программ в более поздних версиях MacOS.
В NASM вы можете использовать default rel
в вашем файле указание изменить адрес по умолчанию с абсолютного на относительный адрес RIP. Чтобы это работало, вам придется отказаться от использования mov register, variable
в lea register, [variable]
при попытке переместить адрес переменной в регистр. Ваш исправленный код может выглядеть так:
default rel
%macro printString 2
mov rax, 0x2000004 ; write
mov rdi, 1 ; stdout
lea rsi, [%1]
mov rdx, %2
syscall
%endmacro
global start
section .text
start:
printString str1,str1.len
printString str2,str2.len
mov rax, 0x2000001 ; exit
mov rdi, 0
syscall
section .data
str1: db "Hello,",10
.len: equ $ - str1
str2: db "world",10
.len: equ $ - str2