为什么GCC垫功能与NOP指令? [英] Why does GCC pad functions with NOPs?
问题描述
我一直用C很短的一段时间,最近开始进入ASM。当我编译的程序:
I've been working with C for a short while and very recently started to get into ASM. When I compile a program:
int main(void)
{
int a = 0;
a += 1;
return 0;
}
该objdump的反汇编有code,而RET后的NOP:
The objdump disassembly has the code, but nops after the ret:
...
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
...
这是我所学到的NOP什么都不做,自从退役后甚至不被执行。
From what I learned nops do nothing, and since after ret wouldn't even be executed.
我的问题是:何必呢?无法ELF(Linux的x86)的任何大小的.text段(+主)工作?
My question is: why bother? Couldn't ELF(linux-x86) work with a .text section(+main) of any size?
我想AP preciate任何帮助,只是想学习。
I'd appreciate any help, just trying to learn.
推荐答案
首先, GCC
并不总是这样做。填充由<受控href=\"http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options\"><$c$c>-falign-functions$c$c>,
First of all, gcc
doesn't always do this. The padding is controlled by -falign-functions
, which is automatically turned on by -O2
and -O3
:
-falign-功能
结果
-falign-功能= N
对齐函数的开始到下电源的两大于 N
,最多跳过 N
字节。例如,
-falign-功能= 32
对齐功能,到下一个32字节边界,但 -falign-功能= 24
会对准下一个32字节边界仅
如果这可以通过跳过23个字节或更少进行。
Align the start of functions to the next power-of-two greater than n
, skipping up to n
bytes. For instance,
-falign-functions=32
aligns functions to the next 32-byte boundary, but -falign-functions=24
would align to the next 32-byte boundary only
if this can be done by skipping 23 bytes or less.
-fno-ALIGN-功能
和 -falign-功能= 1
是等价的,表明函数不会对准。
-fno-align-functions
and -falign-functions=1
are equivalent and mean that functions will not be aligned.
当n为2的幂有些汇编器只支持这个标志;在
这种情况下,上舍入
Some assemblers only support this flag when n is a power of two; in that case, it is rounded up.
如果没有指定n或者为零,使用由机器决定的默认设置。
If n is not specified or is zero, use a machine-dependent default.
在级别-O2启用,-O3。
Enabled at levels -O2, -O3.
有可能是这样做的原因是多方面的,但在x86主要原因之一大概是这样的:
There could be multiple reasons for doing this, but the main one on x86 is probably this:
大多数处理器取在排列16字节或32字节的块的指令。有可能
有利的是通过16对齐临界循环条目和子程序条目,以尽量减少
16字节边界在code的数量。此外,请确保有一个关键循环条目或子程序入口后的前几个指令没有16字节边界。
Most processors fetch instructions in aligned 16-byte or 32-byte blocks. It can be advantageous to align critical loop entries and subroutine entries by 16 in order to minimize the number of 16-byte boundaries in the code. Alternatively, make sure that there is no 16-byte boundary in the first few instructions after a critical loop entry or subroutine entry.
(摘自汇编优化子程序报价
语言的瓦格纳雾。)
(Quoted from "Optimizing subroutines in assembly language" by Agner Fog.)
编辑:下面是一个说明填充一个例子:
edit: Here is an example that demonstrates the padding:
// align.c
int f(void) { return 0; }
int g(void) { return 0; }
在使用gcc 4.4.5使用默认设置编译,我得到:
When compiled using gcc 4.4.5 with default settings, I get:
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-功能
给出:
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
这篇关于为什么GCC垫功能与NOP指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!