Ответ 1
Вы не сказали точно, в чем проблема, которую вы видите, но я предполагаю, что вы терпите крах в точке вызова printf
. Это связано с тем, что OS X (как 32-, так и 64-разрядная) требует, чтобы указатель стека имел выравнивание по 16 байт в точке любого вызова внешней функции.
Указатель стека был выровнен по 16 байт при вызове _main
; этот вызов переместил 8-байтовый обратный адрес в стек, поэтому стек не выравнивается по 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 $8, %rsp // align rsp to 16B boundary
mov $0, %rax
lea _hello(%rip), %rdi // load address of format string
call _printf // call printf
add $8, %rsp // restore rsp
ret