Хотя я знаю, что лучше использовать встроенные компиляторы и, если на то пошло, printf_chk
, а также поместить данные в разделы .rodata
, я ищу более глубокое понимание языка ассемблера и заинтересован в компактный код. Что-то о printf
я не понимаю. Я знаю, где поставить параметры, и я знаю, как использовать %al
для varargs, но, похоже, требуется дополнительное пространство стека, которое я не могу объяснить.
Эта короткая программа
.text
.globl main
main:
movsd value(%rip), %xmm0 # value to print
movl $format, %edi # format string
movl $1, %eax # one floating-point arg
call printf
movl $0, %eax # return 0 from main
ret
.align 8
value: .double 74.321
format: .asciz "%g\n"
дает segfault.
Однако, когда я добавляю дополнительное пространство стека к фрейму, он отлично работает:
.text
.globl main
main:
subq $8, %rsp # ADD SOME STACK SPACE TO FRAME (WHY?)
movsd value(%rip), %xmm0 # value to print
movl $format, %edi # format string
movl $1, %eax # one floating-point arg
call printf
movl $0, %eax # return 0 from main
addq $8, %rsp # REMOVE ADDED STACK SPACE
ret
.align 8
value: .double 74.321
format: .asciz "%g\n"
Может быть, проблема выравнивания? (Я получаю ту же проблему, когда value
и format
находятся в разделе .rodata
.)