为什么我在二进制文件中找不到 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

您可以在 movlcmpl 指令中看到数字 12345 和 12346 包含在您的代码中。

经过优化,代码变得简单了很多。编译器可以看到 if 语句的计算结果永远不会为真。它还可以看到从未使用过变量 a。这是 main() 使用硬优化 (-O3) 编译时的样子:

main:
        rep ret

(注意: 我在 32 位 Ubuntu Xenial 上编译了这个,但在 64 位机器上会发生完全相同的优化。)