为什么我在二进制文件中找不到 int 值
Why can't I find the int value in a binary
我在 64 位 linux 机器上编译了以下程序:
#include <stdio.h>
main()
{
int a = 12345;
if (a == 12346)
printf ("YES\n");
return;
}
如果我使用 hexdump 输出二进制文件,我可以找到 12346(十六进制为 303a),但找不到 12345 值 (0x3039)。这是为什么?
(小端或大端在查找该值时应该没有区别)
对我来说,这里是纯 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 执行其“有用的”默认输出,将输入重新解释为 little-endian two-byte 个单词的序列,您可以花一个小时来弄清楚如何使用它的格式字符串或只选择 xxd。
回答此类问题的最简单方法是使用 -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 , %esp
movl 345, -12(%ebp) # Initialize `a` to 12345
cmpl 346, -12(%ebp) # Compare with 12346
jne .L4
subl , %esp # If equal, ...
pushl $.LC0
call puts # print "YES"
addl , %esp
.L4:
nop
nop
movl -4(%ebp), %ecx # Tidy up and exit
leave
leal -4(%ecx), %esp
ret
您可以在 movl
和 cmpl
指令中看到数字 12345 和 12346 包含在您的代码中。
经过优化,代码变得简单了很多。编译器可以看到 if
语句的计算结果永远不会为真。它还可以看到从未使用过变量 a
。这是 main()
使用硬优化 (-O3
) 编译时的样子:
main:
rep ret
(注意: 我在 32 位 Ubuntu Xenial 上编译了这个,但在 64 位机器上会发生完全相同的优化。)
我在 64 位 linux 机器上编译了以下程序:
#include <stdio.h>
main()
{
int a = 12345;
if (a == 12346)
printf ("YES\n");
return;
}
如果我使用 hexdump 输出二进制文件,我可以找到 12346(十六进制为 303a),但找不到 12345 值 (0x3039)。这是为什么?
(小端或大端在查找该值时应该没有区别)
对我来说,这里是纯 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 执行其“有用的”默认输出,将输入重新解释为 little-endian two-byte 个单词的序列,您可以花一个小时来弄清楚如何使用它的格式字符串或只选择 xxd。
回答此类问题的最简单方法是使用 -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 , %esp
movl 345, -12(%ebp) # Initialize `a` to 12345
cmpl 346, -12(%ebp) # Compare with 12346
jne .L4
subl , %esp # If equal, ...
pushl $.LC0
call puts # print "YES"
addl , %esp
.L4:
nop
nop
movl -4(%ebp), %ecx # Tidy up and exit
leave
leal -4(%ecx), %esp
ret
您可以在 movl
和 cmpl
指令中看到数字 12345 和 12346 包含在您的代码中。
经过优化,代码变得简单了很多。编译器可以看到 if
语句的计算结果永远不会为真。它还可以看到从未使用过变量 a
。这是 main()
使用硬优化 (-O3
) 编译时的样子:
main:
rep ret
(注意: 我在 32 位 Ubuntu Xenial 上编译了这个,但在 64 位机器上会发生完全相同的优化。)