Последовательная sys write syscalls не работает, как ожидалось, ошибка NASM на OS X?
Я пытаюсь изучить сборку MacOS с помощью NASM, и я не могу заставить работать тривиальную программу. Я пробую вариант "Привет, мир", где два слова независимо вызываются макросом. Мой исходный код выглядит следующим образом:
%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,
$
Что я упускаю? Как мне это исправить?
EDIT : я компилирую и запускаю следующие команды:
/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 смогут воспроизвести сбой и создать исправление.
Update : по состоянию на июнь 2018 года я считаю, что в NASM достаточно повторяющихся ошибок и регрессий, поэтому я не рекомендую NASM на данный момент для разработки Macho-64.
Еще одна рекомендация, которую я имею для разработки Macho-64, - использовать относительную адресацию RIP, а не абсолютную. Относительная адресация RIP используется по умолчанию для 64-разрядных программ более поздних версий из Макоса.В 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