0

我编译以下程序gcc并接收输出可执行文件a.out。:

#include <stdio.h>
int main () {
  printf("hello, world\n");
}

当我执行cat a.out时,为什么文件是“乱码”(这叫什么?)而不是 0s 和 1s 的机器语言:

??????? H__PAGEZERO(__TEXT__text__TEXT?`??__stubs__TEXT 
P__unwind_info__TEXT]P]__eh_frame__TEXT?H??__DATA__program_vars [continued]
4

5 回答 5

13

该文件在 0 和 1 中,但是当您使用文本编辑器打开它时,这些位以字节为单位分组,然后被视为文本;)在 Linux 中,您可以尝试反汇编输出文件以确保它包含机器指令(x86 架构) :

objdump -D -mi386 a.out

示例输出:

1:  83 ec 08                sub    $0x8,%esp
4:  be 01 00 00 00          mov    $0x1,%esi
9:  bf 00 00 00 00          mov    $0x0,%edi 

第二列包含十六进制表示的 0 和 1,第三列包含助记汇编指令。

如果要显示那些 0 和 1,只需键入:

xxd -b a.out

示例输出:

 0000000: 01111111 01000101 01001100 01000110 00000010 00000001  .ELF..
 0000006: 00000001 00000000 00000000 00000000 00000000 00000000  ......
于 2012-12-27T20:40:16.717 回答
5

它是某种可执行文件格式。在 Linux 上,它可能是ELF,在 Mac OS X 上它可能是Mach-O,等等。甚至还有a.out格式,但它不再那么常见了。

它不能只是简单的机器指令——操作系统需要一些关于如何加载它、附加哪些动态库等信息。

于 2012-12-27T20:40:22.820 回答
1

字符也是由 0 和 1 组成的,计算机无法分辨。你要求它显示文件,它确实做到了。

除了机器指令外,二进制文件还包含布局和可选的调试信息,这些信息可以是可读的字符串。

于 2012-12-27T20:40:57.853 回答
1

a.out 是您正在使用的操作系统的加载程序可以理解的格式。您看到的那些不同文本是您期望的 0 和 1 的不同部分的标记。

?` 显示存在二进制不可打印数据的位置。

于 2012-12-27T20:41:08.217 回答
0

如今,Linux 系统上的典型格式是 ELF。ELF 文件可能包含机器代码,您可以使用该objdump实用程序对其进行检查。

$ gcc main.c
$ objdump -d -j .text a.out

a.out:文件格式elf64-x86-64


部分.text的反汇编:
(为简洁起见省略代码)
00000000004005ac:
  4005ac:55 推 %rbp
  4005ad: 48 89 e5 移动 %rsp,%rbp
  4005b0: bf 6c 06 40 00 移动 $0x40066c,%edi
  4005b5:e8 d6 fe ff ff callq 400490
  4005ba: 5d 流行 %rbp
  4005bb:c3 retq   
  4005bc: 0f 1f 40 00 nopl 0x0(%rax)

看?机器码。该objdump实用程序有用地以十六进制打印它,右侧是相应的反汇编代码,左侧是地址。

于 2012-12-27T20:48:27.103 回答