sek*_*hor 5 c assembly executable gcc
我正在寻求了解底层计算。我注意到我编译的二进制文件比我想象的要大得多。所以我尝试构建尽可能最小的 c 程序,而不使用任何 stdlib 代码,如下所示:
void _start()
{
while(1) {};
}
Run Code Online (Sandbox Code Playgroud)
gcc -nostdlib -o minimal minimal.c
当我反汇编二进制文件时,它准确地显示了我所期望的内容,即三行汇编代码中的确切代码。
$ objdump -d minimal
minimal: file format elf64-x86-64
Disassembly of section .text:
0000000000001000 <_start>:
1000: 55 push %rbp
1001: 48 89 e5 mov %rsp,%rbp
1004: eb fe jmp 1004 <_start+0x4>
Run Code Online (Sandbox Code Playgroud)
但我的实际可执行文件大小仍然是 13856 字节。到底是什么,让它变得这么大?该文件中还有什么内容?操作系统是否需要超过这 6 字节的机器代码?
编辑 #1:
的输出size是:
$ size -A minimal
minimal :
section size addr
.interp 28 680
.note.gnu.build-id 36 708
.gnu.hash 28 744
.dynsym 24 776
.dynstr 1 800
.text 6 4096
.eh_frame_hdr 20 8192
.eh_frame 52 8216
.dynamic 208 16176
.comment 18 0
Total 421
Run Code Online (Sandbox Code Playgroud)
现代编译器和链接器并未真正针对在全尺寸平台上生成超小型代码进行优化。不是因为这项工作很难,而是因为通常没有必要。编译器或链接器不一定会添加额外的代码(尽管可能会),而是它不会努力将数据和代码打包到尽可能小的空间中。
就您而言,我注意到您正在使用动态链接,即使实际上没有任何链接。使用“-static”将减少大约 8kB。“-s”(剥离)会去掉更多一点。
我不知道是否有可能使用 gcc 制作一个真正最小的 ELF 可执行文件。在你的例子中,这应该是大约 400 个字节,几乎所有这些都是各种 ELF 头、节表等。
我不知道我是否可以链接我自己的网站(我相信如果不可以的话有人会纠正我),但我有一篇文章介绍如何通过从头开始以二进制方式构建一个小型 ELF 可执行文件:
http://kevinboone.me/elfdemo.html
有许多不同的可执行文件格式。.com、.exe、.elf、.coff、a.out 等。理想情况下,它们包含机器代码和其他部分(.text(代码)、.data、.bss、.rodata 和可能的其他部分,名称取决于工具链)加上它们包含调试信息。注意你的反汇编是如何显示标签 _start 的吗?这是一个字符串以及其他信息,以便能够将该字符串连接到地址进行调试。objdump 的输出还表明您正在使用 elf 文件,您可以轻松查找文件格式,并且可以轻松编写自己的程序来解析该文件,或者尝试使用 readelf 和其他工具来查看其中的内容(高水平不是原始的)。
在一般情况下(并非总是如此,但想想个人电脑)的操作系统上,程序被加载到内存中然后运行,因此您首先希望拥有操作系统支持的文件格式,没有理由他们支持不止一个,但他们可能会支持。它取决于操作系统/系统设计,但操作系统可能被设计为不仅加载代码,还加载/初始化数据(.data、.bss)。启动 MCU 时,您需要将数据嵌入到二进制 blob 中,应用程序本身将数据从闪存复制到 RAM,但在操作系统中不一定需要,但为了做到这一点,您需要一种文件格式可以区分部分、目标位置和大小。这意味着文件中有额外的字节来定义它和文件格式。
二进制文件在输入 C 生成的代码之前包含引导代码,具体取决于系统、C 库(计算机上可以使用多个/许多 C 库,引导程序通常特定于 C 库,而不是目标) ,也不是操作系统,不是编译器的东西),所以文件的一部分是引导代码,当你的主程序非常小时,很多文件大小都是开销。
例如,您可以使用 strip 通过删除一些符号和其他非必要项目来缩小文件,例如文件大小应该变小,但 objdump 反汇编将没有标签,对于 x86 的情况,可变长度最好的情况下难以反汇编的指令集会变得更加困难,因此带或不带标签的输出可能无法反映实际的指令,但如果没有标签,gnu 反汇编器不会在标签处重置自身,并且可能会使输出变得更糟。