我在64位Linux机器上编译了以下程序:
#include <stdio.h>
main()
{
int a = 12345;
if (a == 12346)
printf ("YES\n");
return;
}
如果我使用hexdump输出二进制文件,我可以找到12346(十六进制为303a),但不能找到12345值(0x3039)。那是为什么?
(小端或大端应该在找到该值时没有区别)
答案 0 :(得分:6)
这是我在普通hexdump
输出中的值的位置;看看粗体区域。
0000500 39fc 0030 8100 fc7d 303a 0000 0a75 a4bf
如果您希望将3039
视为一个群组,则可以解释这种混淆。实际的字节是:
fc 39 30 00 00 81 7d fc 3a 30 00 00 75 0a bf a4
如果您不希望hexdump执行其“有用”的默认输出,并将输入重新解释为一系列小端双字节字,您可能需要花费一个小时来确定如何使用其格式字符串或只是选择xxd。
答案 1 :(得分:4)
回答这类问题的最简单方法是使用-S
命令行选项对其进行编译,该选项将您的C程序输出为汇编代码。
这是您的main()
函数在没有任何优化的情况下编译的(即使用-O0
命令行开关)。我删除了一些冗余的标记语句并添加了一些注释:
main:
leal 4(%esp), %ecx # Create local storage on stack
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $12345, -12(%ebp) # Initialize `a` to 12345
cmpl $12346, -12(%ebp) # Compare with 12346
jne .L4
subl $12, %esp # If equal, ...
pushl $.LC0
call puts # print "YES"
addl $16, %esp
.L4:
nop
nop
movl -4(%ebp), %ecx # Tidy up and exit
leave
leal -4(%ecx), %esp
ret
您可以在movl
和cmpl
说明中看到代码中包含数字12345和12346。
通过优化,代码变得更加简单。编译器可以看到if
语句永远不会计算为true。它还可以看到变量a
从未使用过。这是main()
在使用硬优化(-O3
)编译时的样子:
main:
rep ret
(注意:我是在32位Ubuntu Xenial上编译的,但在64位计算机上会发生完全相同的优化。)