Последовательная 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