assembly - 为什么编译这个简单的汇编代码并链接到 ELF 会导致比平面二进制文件更大的大小?

标签 assembly linker elf low-level

我正在使用类似嵌入式操作系统的环境,因此二进制文件的大小需要尽可能小。我一直在使用简单的平面二进制文件作为可执行文件,但现在我正在尝试使用 ELF。我只是使用汇编代码,但与 ld 链接。汇编代码:

CPU i386
BITS 32
SECTION .text progbits alloc exec nowrite
GLOBAL start


start:
mov eax, 0 
add eax, 1
inc eax
mov eax, 0x12345678 
mov dword [0x100000], eax
mov ebx, dword [0x100000]
mov eax, ebx

out 0xF3, al ;dump memory API call

out 0xF0, ax
cli
hlt

构建命令:

yasm -o testbench/test.o testbench/test.asm -f elf32
i386-elf-gcc -T testbench/linker.ld -o test.elf -ffreestanding -nostdlib testbench/test.o -Wl,--gc-sections -dead_strip -fdata-sections -ffunction-sections -Os -nostartfiles -nodefaultlibs
strip --strip-all test.elf

最后,链接器脚本:

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x1000;
scratch = 0x100000;
MEMORY
{
  coderom (rx) : ORIGIN = phys, LENGTH = 128K
  scratchram (!rx) : ORIGIN = scratch, LENGTH = 1024K
}
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text.start);
    *(.text*)
    *(.rodata)
    . = ALIGN(4);
  } > coderom
  __text_end=.;
  .data : AT(scratch)
  {
    data = .;
    *(.data)
    . = ALIGN(4);
  } > scratchram
  __data_end=.;
  __binary_end = .;
  .bss : AT(scratch + (bss - data))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4);
  } > scratchram
}

这导致了这个 readelf 列表:

earlz@earlz-ubdev:~/x86LibSC$ readelf -a test.elf
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x1000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4160 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         5
  Section header string table index: 4

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00001000 001000 000024 00  AX  0   0 16
  [ 2] .data             PROGBITS        00100000 001024 000000 00  WA  0   0  1
  [ 3] .bss              NOBITS          00100000 000000 000000 00  WA  0   0  1
  [ 4] .shstrtab         STRTAB          00000000 001024 00001c 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x00001000 0x00001000 0x00024 0x00024 R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text 

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Intel 80386 is not currently supported.

No version information found in this file.

如您所见,这应该最多编译为 100 或 200 字节(使用平面二进制格式时也是如此)。但由于某种原因,这占用了超过 4Kb。

除了在汇编器中手动构建 ELF 文件外,如何尽可能地减小 ELF 程序的大小?

作为引用,在此操作系统环境中没有重定位或动态代码。它只是加载平面程序部分。

最佳答案

我最终通过使用“-n”(也称为“-nmagic”)链接器选项解决了这个问题。这基本上告诉 ld 不要担心在页面边界上对齐程序部分。这让我从 4K 到大约 700(剥离后 400)。然后我用了 sstrip将其进一步减少到大约 150 个字节。这是我希望为此用例实现的大小类型。

关于assembly - 为什么编译这个简单的汇编代码并链接到 ELF 会导致比平面二进制文件更大的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47517571/

相关文章:

c++ - 神秘的相对路径库依赖

c - 如何使用 ld 脚本在 elf 目标中设置入口点

c - 在C中读取ELF文件的正确方法

c - 了解一些汇编代码

assembly - ARM算术加法和标志更新

c++ - 如何从 x64 程序集中的堆栈获取参数?

linux - 对于微型程序,链接后最小的可执行文件大小现在比 2 年前大 10 倍?

Linux 上的 C++ 开发 - 我从哪里开始?

c - ld链接器在创建共享库时从静态库中删除目标文件

linux - 确定 Linux 二进制文件的直接共享对象依赖关系?