assembly - 为什么组装后的可执行文件大小相同

标签 assembly x86-64 intel instructions

在 x86_64 体系结构中,可以将一些指令操作数组合更改为更短的指令操作数组合,以达到相同的效果,但可执行文件更小。 例如,通常这样写:

xor eax, eax

代替:

xor rax, rax

我想测试一下,用汇编写了一个简单的程序:

    segment .text
    global main
main:
    push rbp
    mov rbp, rsp
    xor rax, rax ; line in question
    leave
    ret

build :

yasm -f elf64 -m amd64 -g dwarf2 main.asm; clang -o main main.o

检查尺寸:

stat main

得到:

....
Size: 9184
...

好的,将有问题的行更改为:

xor eax, eax

希望得到更小的可执行文件,但得到了相同的 9184 字节大小。 为什么使用较短的指令表尺寸没有减小?

最佳答案

当目标文件链接在一起时,链接器会在 main.o 的 .text 部分末尾插入填充,因此文本部分的开头是 crt0.o 从 16B 对齐边界开始。

如果你像我建议的那样反汇编你的二进制文件,你会看到这个:

$ objdump -Mintel -drw main
...
0000000000400500 <main>:
  400500:       55                      push   rbp
  400501:       48 89 e5                mov    rbp,rsp
  400504:       48 31 c0                xor    rax,rax
  400507:       c9                      leave  
  400508:       c3                      ret    
  400509:       0f 1f 80 00 00 00 00    nop    DWORD PTR [rax+0x0]    <--- padding inserted by linker

0000000000400510 <__libc_csu_init>:
  400510:       41 57                   push   r15
  ...

更改 main() 的大小只会更改 NOP 填充的大小,直到您超过 16B 边界。


有趣的是,如果你反汇编main.o,在ret之后没有填充,所以我认为NOP一定是链接器插入的。

使用 readelf -aW main.o 显示:

Section Headers:
  [Nr] Name       Type            Address          Off    Size   ES Flg Lk Inf Al
...
  [ 4] .text      PROGBITS        0000000000000000 000040 000009 00  AX  0   0 16
....

如果没有 -W,您可以看到完整的列名,而不是将它们打包在一行中。最后一列是“对齐”。这就是 yasm 告诉链接器该对象的 .text 部分需要 32B 或链接器输出的文本段内的任何其他对齐方式的方式。

main: 之前添加 ALIGN 4096 会导致 .o 在 .text 的对齐列中具有 4096。它将 NOP 填充添加到链接二进制文件中 before main 函数的末尾,因此 main 位于 0x00402000。这确实会改变二进制文件的大小。

关于assembly - 为什么组装后的可执行文件大小相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39403872/

相关文章:

assembly - 在 ARM 程序集中将立即值放入括号中的目的是什么?

c++ - 使用英特尔PIN修改寄存器

assembly - rip 可以与具有 RIP 相对寻址的另一个寄存器一起使用吗?

assembly - x86-64 MOV r/m64,imm32 = io?

opencv - 谷歌本地客户端(NaCl、PNaCl)中的英特尔线程构建 block (TBB)

assembly - 如何编写汇编语言使 DMA 工作

无法在 C 程序中预加载函数

linux - 具有相对偏移的短跳未使用我期望的偏移

driver - Debian 10 (Buster) 桌面/GUI 速度慢

assembly - 使用 TI 代码编写器工作室(用于 ARM)在 C 代码中进行内联汇编