我得到的结果与您在我的机器上所做的相同(Mac OS X,所以 AMD/Linux ABI)。浮点参数在 XMM 寄存器中传递,整数参数在整数寄存器中传递。当printf
使用 抓取它们va_arg
时,它会在看到%f
格式时从 XMM 中提取,而在看到 时从其他寄存器中提取%lld
。-O0
这是在我的机器上编译()的程序的反汇编:
1 _main:
2 pushq %rbp
3 movq %rsp,%rbp
4 subq $0x20,%rsp
5 movq $0x3f1e68a0d349be90,%rax
6 move %rax,0xf8(%rbp)
7 movq $0x00000000,0xf0(%rbp)
8 movq 0xf0(%rbp),%rdx
9 movq 0xf0(%rbp),%rsi
10 movsd 0xf8(%rbp),%xmm0
11 movq 0xf8(%rbp),%rax
12 movapd %xmm0,%xmm1
13 movq %rax,0xe8(%rbp)
14 movsd 0xe8(%rbp),%xmm0
15 lea 0x0000001d(%rip),%rdi
16 movl $0x00000002,%eax
17 callq 0x100000f22 ; symbol stub for: _printf
18 movl $0x00000000,%eax
19 leave
20 ret
在那里你可以看到发生了什么 - 格式字符串被传递%rdi
,然后你的参数被传递(按顺序): %xmm0
,%xmm1
,%rsi
和%rdx
。获取它们时printf
,它会以不同的顺序(格式字符串中指定的顺序)弹出它们。这意味着它会弹出它们: %rsi
, %xmm0
, %rdx
, %xmm1
, 给出你看到的结果。2
in%eax
是表示传递的浮点参数的数量。
编辑:
这是一个优化版本 - 在这种情况下,较短的代码可能更容易理解。解释与上面相同,但样板噪音要少一些。浮点值由第movsd
4 行加载。
1 _main:
2 pushq %rbp
3 movq %rsp,%rbp
4 movsd 0x00000038(%rip),%xmm0
5 xorl %edx,%edx
6 xorl %esi,%esi
7 movaps %xmm0,%xmm1
8 leaq 0x00000018(%rip),%rdi
9 movb $0x02,%al
10 callq 0x100000f18 ; symbol stub for: _printf
11 xorl %eax,%eax
12 leave
13 ret