Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 除了原始机器指令,可执行文件中还有什么?_C_Assembly_Gcc_Executable - Fatal编程技术网

C 除了原始机器指令,可执行文件中还有什么?

C 除了原始机器指令,可执行文件中还有什么?,c,assembly,gcc,executable,C,Assembly,Gcc,Executable,我正在寻求了解低级计算。我注意到我编译的二进制文件比我认为应该的要大得多。因此,我尝试在不使用任何stdlib代码的情况下构建尽可能最小的c程序,如下所示: void\u start() { 而(一){};; } gcc-nostlib-o minimal.c 当我解压二进制文件时,它会精确地显示我所期望的内容,即在三行汇编中的这段代码 $objdump-d最小值 最小:文件格式elf64-x86-64 第节的分解。正文: 0000000000001000 : 1000:55%按需付费 100

我正在寻求了解低级计算。我注意到我编译的二进制文件比我认为应该的要大得多。因此,我尝试在不使用任何stdlib代码的情况下构建尽可能最小的c程序,如下所示:

void\u start()
{
而(一){};;
}
gcc-nostlib-o minimal.c

当我解压二进制文件时,它会精确地显示我所期望的内容,即在三行汇编中的这段代码

$objdump-d最小值
最小:文件格式elf64-x86-64
第节的分解。正文:
0000000000001000 :
1000:55%按需付费
1001:48 89 e5 mov%rsp,%rbp
1004:eb-fe jmp 1004
但我的实际可执行文件的大小仍然是13856字节。是什么让这个这么大?档案里还有什么?操作系统是否需要超过这6字节的机器代码

编辑#1:
size
的输出为:

$size-最小值
最低限度:
截面尺寸地址
.interp 28680
.note.gnu.build-id 36 708
.gnu.hash 28744
dynsym 24 776
.dynstr 1800
.文本6 4096
.eh_frame_hdr 20 8192
.eh_帧52 8216
.动态208 16176
.评论18 0
总数421

有许多不同的可执行文件格式。com、.exe、.elf、.coff、a.out等。理想情况下,它们包含机器代码和其他部分(.text(code)、.data、.bss、.rodata和可能的其他部分,名称取决于工具链)以及调试信息。注意您的反汇编如何显示标签_start?这是一个字符串和其他信息,以便能够将该字符串连接到用于调试的地址。objdump的输出还表明,您使用的是elf文件,您可以轻松查找文件格式,也可以编写自己的程序来解析文件,或者尝试使用readelf和其他工具查看其中的内容(高级非原始)

在一个操作系统上,程序通常(不总是,但想想pc机)被加载到ram中,然后运行,因此您首先希望有一个操作系统支持的文件格式,它们没有理由支持多个,但它们可能支持。它取决于操作系统/系统设计,但操作系统的设计不仅可以加载代码,还可以加载/初始化数据(.data、.bss)。启动时,比如说mcu,您需要将数据嵌入二进制blob,应用程序本身将数据从闪存复制到ram,但操作系统不一定需要,但要做到这一点,您需要一种能够区分分区、目标位置和大小的文件格式。这意味着文件中有额外的字节来定义这个和文件格式

二进制文件在输入C生成的代码之前包含引导代码,这取决于系统,取决于C库(一台计算机上可以使用多个/多个C库,引导通常特定于C库,而不是目标,也不是操作系统,也不是编译器),因此,当主程序非常小时,文件中的某些部分也是引导代码,而大量文件大小是开销


例如,您可以使用strip使文件变小,方法是去掉一些符号和其他非必要的项,例如文件大小应该变小,但是objdump反汇编将没有标签,对于x86,一个可变长度的指令集(最多很难反汇编)变得更难,因此,带标签或不带标签的输出可能不会反映实际的指令,但如果没有标签,gnu反汇编程序不会在标签处重置自身,并且会使输出变得更糟。

现代编译器和链接器并没有真正针对在全规模平台上生成超小型代码进行优化。不是因为工作困难,而是因为通常没有必要这样做。编译器或链接器不一定要添加额外的代码(尽管可能),而是不会试图将数据和代码打包到尽可能小的空间中

在您的例子中,我注意到您使用的是动态链接,尽管实际上没有任何链接。使用“-static”将减少大约8kB。“-s”(strip)将去掉更多

我不知道是否有可能使用gcc来制作一个真正最小的ELF可执行文件。在您的例子中,应该是大约400字节,几乎所有的字节都是各种ELF头、节表等

我不知道我是否被允许链接我自己的网站(如果不被允许,我相信有人会纠正我的错误),但我有一篇文章是关于用二进制从零开始构建一个小ELF可执行文件的:


如果使用
clang 10.0
lld 10.0
并去掉不必要的部分,则可以将64位静态链接可执行文件的大小控制在800字节以下

$ cat minimal.c
void _start(void)
{
    int i = 0;

    while (i < 11) {
       i++;
    }

    asm( "int $0x80" :: "a"(1), "b"(i) );
}

$ clang -static -nostdlib -flto -fuse-ld=lld -o minimal minimal.c
$ ls -l minimal
-rwxrwxr-x 1 fpm fpm 1376 Sep  4 17:38 minimal

$ readelf --string-dump .comment minimal
String dump of section '.comment':
  [     0]  Linker: LLD 10.0.0
  [    13]  clang version 10.0.0 (Fedora 10.0.0-2.fc32)

$ readelf -W --section-headers minimal
There are 9 section headers, starting at offset 0x320:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.build-id NOTE            0000000000200190 000190 000018 00   A  0   0  4
  [ 2] .eh_frame_hdr     PROGBITS        00000000002001a8 0001a8 000014 00   A  0   0  4
  [ 3] .eh_frame         PROGBITS        00000000002001c0 0001c0 00003c 00   A  0   0  8
  [ 4] .text             PROGBITS        0000000000201200 000200 00002a 00  AX  0   0 16
  [ 5] .comment          PROGBITS        0000000000000000 00022a 000040 01  MS  0   0  1
  [ 6] .symtab           SYMTAB          0000000000000000 000270 000048 18      8   2  8
  [ 7] .shstrtab         STRTAB          0000000000000000 0002b8 000055 00      0   0  1
  [ 8] .strtab           STRTAB          0000000000000000 00030d 000012 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

$ strip -R .eh_frame_hdr -R .eh_frame minimal
$ strip -R .comment -R .note.gnu.build-id minimal
strip: minimal: warning: empty loadable segment detected at vaddr=0x200000, is this intentional?

$ readelf -W --section-headers minimal
There are 3 section headers, starting at offset 0x240:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000201200 000200 00002a 00  AX  0   0 16
  [ 2] .shstrtab         STRTAB          0000000000000000 00022a 000011 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

$ ll minimal
-rwxrwxr-x 1 fpm fpm 768 Sep  4 17:45 minimal
$cat minimal.c
void\u开始(void)
{
int i=0;
而(i<11){
i++;
}
asm(“int$0x80”:“a”(1),“b”(i));
}
$clang-static-nostdlib-flto-fuse ld=lld-o minimal.c
$ls-l最小值
-RWXR-x 1 fpm fpm 1376 Sep 4 17:38最小值
$readelf—字符串转储。注释最小
节“.comment”的字符串转储:
[0]链接器:LLD 10.0.0
[13]铿锵版本10.0.0(Fedora 10.0.0-2.fc32)
$readelf-W--最小节头
共有9个节标题,从偏移量0x320开始:
章节标题:
[Nr]名称类型地址大小不一致ES Flg Lk Inf Al
[0]空00000000000000000000000000
[1].note.gnu.build-id note 0000000000 200190 000190 000018 00 A 0 0 4
[2]。eh_帧_hdr程序位0000000000 2001A8 0001a8 000014 00