Why the disasembly of `printf("%f",6.4);` so complex?
(gdb) l main
1 #include <stdio.h>
2
3 int main(void)
4 {
5 //int i = 6;
6 printf("%f",6.4);
7 return 0;
8 }
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400498 <main+0>: push %rbp
0x0000000000400499 <main+1>: mov %rsp,%rbp
0x000000000040049c <main+4>: sub $0x10,%rsp
0x00000000004004a0 <main+8>: mov $0x401999999999999a,%rax
0x00000000004004aa <main+18>: mov %rax,-0x8(%rbp)
0x00000000004004ae <main+2开发者_如何学C2>: movsd -0x8(%rbp),%xmm0
0x00000000004004b3 <main+27>: mov $0x4005c8,%edi
0x00000000004004b8 <main+32>: mov $0x1,%eax
0x00000000004004bd <main+37>: callq 0x400398 <printf@plt>
Why so complicated(I noticed the complexity is caused by float
)?
BTW,what's the difference between $0x1
and 0x1
?
(gdb) p 0x10
$4 = 16
(gdb) p $0x10
$5 = void
The first float parameters are given to a subroutine in xmm0, xmm1... in the x86-64 ABI. There is no instruction to move a immediate (the float representation of 6.4) directly to a xmm register, so it is first placed on the stack and than moved into xmm0. The other parameter is of course the address of the format string.
The difference between $1 and 1 ist the first is used as a immediate constant and the second is used as address offset or address.
Because you compiled without any optimization. Try -Os
:
pushq %rbp // save old frame pointer
movq %rsp, %rbp // establish new frame pointer
leaq 0x0000004d(%rip), %rdi // load address of format string ("%f")
movsd 0x0000003d(%rip), %xmm0 // load 6.4
movb $0x01, %al // load number of VA_ARGS (1)
callq _printf // call printf
xorl %eax, %eax // conjure return value (0)
popq %rbp // restore frame pointer
ret // return
What's so complex about that?
精彩评论