Как написать ассемблер hello world program для 64 бит Mac OS X с помощью printf?

Я пытаюсь научиться писать язык ассемблера для 64-битной Mac OS. У меня нет проблем с 32-битной Mac OS и 32-битной и 64-битной Linux.

однако Mac OS 64 бит отличается, и я не мог понять. Поэтому я здесь, чтобы просить о помощи.

У меня нет проблем с использованием системного вызова для печати. Тем не менее, я хотел бы узнать, как вызвать функции C, используя 64-битный язык сборки Mac OS.

пожалуйста, посмотрите на следующее код

.data
_hello:
    .asciz "Hello, worldn"


.text
.globl _main
_main:
    movq , %rax
    movq _hello(%rip), %rdi
    call _printf

Я использую $ gcc-arch x86_64 Здравствуйте.s

собрать и связать.

Он генерирует двоичный код. Однако, я получил ошибку сегментации при запуске.

Я попытался добавить "subq $8, %rsp" перед вызовом _printf, все тот же результат, что и раньше.

что я сделал не так?

кстати, это какой-нибудь способ отладки этого кода на Mac? Я попытался добавить -ggdb или-gstab или-gDWARF, и $ gdb ./а.и не вижу код и установить точки останова.

1 ответов


вы не сказали точно, в чем проблема, которую вы видите, но я предполагаю, что вы разбиваетесь в точке вызова printf. Это связано с тем, что OS X (32 - и 64-разрядная) требует, чтобы указатель стека имел 16-байтовое выравнивание в точке любого внешнего вызова функции.

указатель стека был выровнен по 16 байтам, когда _main был вызван; этот вызов толкнул восьмибайтовый обратный адрес в стек, поэтому стек не выровнен по 16 байтам в точке вызова _printf. Вычесть восемь из %rsp перед вызовом, чтобы правильно выровнять его.


поэтому я пошел вперед и отладил это для вас (без магии, просто используйте gdb,break main, display/5i $pc, stepi и т. д.). Другая проблема-то здесь:

movq _hello(%rip), %rdi

это загружает первые восемь байтов вашей строки в %rdi, что совсем не то, что вы хотите (в частности, первые восемь байтов вашей строки крайне маловероятно составляют допустимый указатель на строку формата, что приводит к сбою в printf). Вместо этого вы хотите загрузить адрес строки. Отлаженная версия вашей программы:

.cstring
_hello: .asciz "Hello, world\n"

.text
.globl _main
_main:
    sub  , %rsp           // align rsp to 16B boundary
    mov  , %rax
    lea  _hello(%rip), %rdi // load address of format string
    call _printf            // call printf
    add  , %rsp           // restore rsp
    ret