我已经使用C了很短的时间,最近才开始涉足ASM。当我编译程序时:

int main(void)
  {
  int a = 0;
  a += 1;
  return 0;
  }


objdump反汇编具有代码,但在重新输入后会提示:

...
08048394 <main>:
 8048394:       55                      push   %ebp
 8048395:       89 e5                   mov    %esp,%ebp
 8048397:       83 ec 10                sub    $0x10,%esp
 804839a:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%ebp)
 80483a1:       83 45 fc 01             addl   $0x1,-0x4(%ebp)
 80483a5:       b8 00 00 00 00          mov    $0x0,%eax
 80483aa:       c9                      leave
 80483ab:       c3                      ret
 80483ac:       90                      nop
 80483ad:       90                      nop
 80483ae:       90                      nop
 80483af:       90                      nop
...


从我学到的知识,nops什么都不做,因为ret后甚至不会被执行。

我的问题是:为什么要打扰? ELF(linux-x86)不能与任何大小的.text部分(+ main)一起使用吗?

我将不胜感激,只是尝试学习。

最佳答案

首先,gcc并不总是这样做。填充由-falign-functions控制,由-O2-O3自动打开:


  -falign-functions
  -falign-functions=n
  
  将函数的开头与下一个大于n的2的幂数对齐,最多跳过n个字节。例如,
  -falign-functions=32将函数与下一个32字节边界对齐,但是-falign-functions=24仅将函数与下一个32字节边界对齐
  如果可以跳过23个字节或更少的字节来完成此操作。
  
  -fno-align-functions-falign-functions=1是等效的,表示函数将不对齐。
  
  某些汇编程序仅在n为2的幂时才支持此标志。在
  那样的话,就四舍五入了。
  
  如果未指定n或为n,则使用与机器有关的默认值。
  
  在-O2,-O3级别启用。


这样做可能有多种原因,但是x86上的主要原因可能是:


  大多数处理器以对齐的16字节或32字节块来获取指令。有可能
  有利于将关键循环条目和子例程条目对齐16以最小化
  代码中16字节边界的数量。或者,请确保关键循环条目或子例程条目之后的前几条指令中没有16字节边界。


(引自“优化汇编中的子例程
语言”,作者:Agner Fog。

编辑:这是一个演示填充的示例:

// align.c
int f(void) { return 0; }
int g(void) { return 0; }


当使用带有默认设置的gcc 4.4.5进行编译时,我得到:

align.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <f>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 00 00 00 00          mov    $0x0,%eax
   9:   c9                      leaveq
   a:   c3                      retq

000000000000000b <g>:
   b:   55                      push   %rbp
   c:   48 89 e5                mov    %rsp,%rbp
   f:   b8 00 00 00 00          mov    $0x0,%eax
  14:   c9                      leaveq
  15:   c3                      retq


指定-falign-functions给出:

align.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <f>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 00 00 00 00          mov    $0x0,%eax
   9:   c9                      leaveq
   a:   c3                      retq
   b:   eb 03                   jmp    10 <g>
   d:   90                      nop
   e:   90                      nop
   f:   90                      nop

0000000000000010 <g>:
  10:   55                      push   %rbp
  11:   48 89 e5                mov    %rsp,%rbp
  14:   b8 00 00 00 00          mov    $0x0,%eax
  19:   c9                      leaveq
  1a:   c3                      retq

关于c - 为什么GCC垫可与NOP一起使用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41033978/

10-12 15:59