When I write a simple assembly language program, linked with the C library, using gcc 4.6.1 on Ubuntu, and I try to print an integer, it works fine:
.global main
.text
main:
mov $format, %rdi
mov $5, %rsi
mov $0, %rax
call printf
ret
format:
.asciz "%10d
"
This prints 5, as expected.
But now if I make a small change, and try to print a floating point value:
.global main
.text
main:
mov $format, %rdi
movsd x, %xmm0
mov $1, %rax
call printf
ret
format:
.asciz "%10.4f
"
x:
.double 15.5
This program seg faults without printing anything. Just a sad segfault.
But I can fix this by pushing and popping %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
"
x:
.double 15.5
Now it works, and prints 15.5000.
My question is: why did pushing and popping %rbp
make the application work? According to the ABI, %rbp
is one of the registers that the callee must preserve, and so printf
cannot be messing it up. In fact, printf
worked in the first program, when only an integer was passed to printf
. So the problem must be elsewhere?
Question&Answers:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…