0xh*_*ker 4 c floating-point x86-64
我在64位机器上写了一个简单的代码
int main() {
printf("%d", 2.443);
}
Run Code Online (Sandbox Code Playgroud)
所以,这就是编译器的行为方式.它将第二个参数标识为double,因此它将在堆栈上推送8个字节,或者可能只是在调用之间使用寄存器来访问变量.%d期望一个4字节的整数值,因此它打印一些垃圾值.
有趣的是,每次执行此程序时,打印的值都会发生变化.那么发生了什么?我希望它每次打印相同的垃圾值,而不是每次都不同.
当然,这是未定义的行为,传递与格式不对应的参数,因此语言无法告诉我们输出更改的原因.我们必须查看实现,它生成的代码,以及可能的操作系统.
我的设置与你的不同,
Linux 3.1.10-1.16-桌面x86_64 GNU/Linux(openSuSE 12.1)
用gcc-4.6.2.但它足够相似,怀疑相同的机制是合理的.
查看生成的程序集(-O3出于习惯),相关部分(main)是
.cfi_startproc
subq $8, %rsp # adjust stack pointer
.cfi_def_cfa_offset 16
movl $.LC1, %edi # move format string to edi
movl $1, %eax # move 1 to eax, seems to be the number of double arguments
movsd .LC0(%rip), %xmm0 # move the double to the floating point register
call printf
xorl %eax, %eax # clear eax (return 0)
addq $8, %rsp # adjust stack pointer
.cfi_def_cfa_offset 8
ret # return
Run Code Online (Sandbox Code Playgroud)
如果不是double,我通过了一个int,没有太大的变化,但那显着
movl $47, %esi # move int to esi
movl $.LC0, %edi # format string
xorl %eax, %eax # clear eax
call printf
Run Code Online (Sandbox Code Playgroud)
我已经看过所生成的代码的类型和传递的参数计数许多变型printf,并且一致地,第一double(或推动float)参数被传递在xmmN,N = 0, 1, 2和整数(int,char,long,无论符号性的)被传递于esi,edx,ecx,r8d,r9d然后堆栈.
因此,我冒险尝试printf寻找宣布int的内容esi,然后打印出现在发生的任何事情.
esi当没有任何东西被移动时,内容是否以任何方式可预测main,以及它们可能表示什么,我不知道.