当我在 Ubuntu 上使用 gcc 4.6.1 编写一个与 C 库链接的简单汇编语言程序并尝试打印一个整数时,它工作正常:
.global main
.text
main:
mov $format, %rdi
mov $5, %rsi
mov $0, %rax
call printf
ret
format:
.asciz "%10d\n"
正如预期的那样,这将打印 5。
但是现在如果我做一个小改动,并尝试打印一个浮点值:
.global main
.text
main:
mov $format, %rdi
movsd x, %xmm0
mov $1, %rax
call printf
ret
format:
.asciz "%10.4f\n"
x:
.double 15.5
这个程序段错误而不打印任何东西。只是一个可悲的段错误。
但我可以通过 push 和 pop 来解决这个问题%rbp
。
.global main
.text
main:
push %rbp
mov $format, %rdi
movsd x, %xmm0
mov $1, %rax
call printf
pop %rbp
ret
format:
.asciz "%10.4f\n"
x:
.double 15.5
现在它可以工作了,并打印 15.5000。
我的问题是:为什么推送和弹出%rbp
使应用程序工作?根据 ABI,%rbp
是被调用者必须保留的寄存器之一,因此printf
不能搞砸。事实上,printf
在第一个程序中工作,当只有一个整数被传递给printf
. 那么问题一定出在其他地方吗?