我使用gcc
编译以下程序并接收输出可执行文件a.out
。:
#include <stdio.h>
int main () {
printf("hello, world\n");
}
当我执行cat a.out
时,为什么文件处于“乱码”(这叫做什么?)而不是0和1的机器语言:
??????? H__PAGEZERO(__TEXT__text__TEXT?`??__stubs__TEXT
P__unwind_info__TEXT]P]__eh_frame__TEXT?H??__DATA__program_vars [continued]
答案 0 :(得分:10)
该文件为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 ......
答案 1 :(得分:5)
这是某种executable file format。在Linux上,它可能是ELF,在Mac OS X上它可能是Mach-O,依此类推。甚至还有a.out格式,但它不再常见了。
它不仅仅是裸机指令 - 操作系统需要一些有关如何加载它的信息,附加到它的动态库等等。
答案 2 :(得分:1)
字符也由0和1组成,计算机无法知道差异。你要求它显示文件,但确实如此。
除了机器指令外,二进制文件还包含布局和可选的调试信息,这些信息可以是可读的字符串。
答案 3 :(得分:1)
a.out采用的格式是您正在使用的操作系统的加载程序可以理解。您看到的那些不同的文本是您期望的0和1的不同部分的标记。
?
和`显示存在二进制不可打印数据的位置。
答案 4 :(得分:0)
目前Linux系统的典型格式是ELF。 ELF文件可能包含机器代码,您可以使用objdump
实用程序检查它。
$ gcc main.c $ objdump -d -j .text a.out a.out: file format elf64-x86-64 Disassembly of section .text: (code omitted for brevity) 00000000004005ac : 4005ac: 55 push %rbp 4005ad: 48 89 e5 mov %rsp,%rbp 4005b0: bf 6c 06 40 00 mov $0x40066c,%edi 4005b5: e8 d6 fe ff ff callq 400490 4005ba: 5d pop %rbp 4005bb: c3 retq 4005bc: 0f 1f 40 00 nopl 0x0(%rax)
请参阅?机器代码。 objdump
实用程序以十六进制格式帮助打印,右侧显示相应的反汇编代码,左侧显示地址。