为什么 GCC pad 与 NOP 一起起作用?
我使用 C 语言已经有一段时间了,最近才开始接触 ASM。当我编译程序时:
int main(void)
{
int a = 0;
a += 1;
return 0;
}
objdump 反汇编有代码,但在 ret 之后 nops:
...
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)吗?
我很感激任何帮助,只是想学习。
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;
}
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
...
From what I learned nops do nothing, and since after ret wouldn't even be executed.
My question is: why bother? Couldn't ELF(linux-x86) work with a .text section(+main) of any size?
I'd appreciate any help, just trying to learn.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,
gcc
并不总是这样做。填充由-falign-functions
,由-O2
和-O3
自动开启:这样做可能有多种原因,但 x86 上的主要原因可能是:
(引自《优化汇编中的子程序
语言”由 Agner Fog 编写。)
编辑:这是一个演示填充的示例:
当使用默认设置的 gcc 4.4.5 进行编译时,我得到:
指定
-falign-functions
给出: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
:There could be multiple reasons for doing this, but the main one on x86 is probably this:
(Quoted from "Optimizing subroutines in assembly
language" by Agner Fog.)
edit: Here is an example that demonstrates the padding:
When compiled using gcc 4.4.5 with default settings, I get:
Specifying
-falign-functions
gives:这样做是为了按 8、16 或 32 字节边界对齐下一个函数。
摘自 A.Fog 的“用汇编语言优化子例程”:
This is done to align the next function by 8, 16 or 32-byte boundary.
From “Optimizing subroutines in assembly language” by A.Fog:
据我记得,指令在CPU中进行流水线处理,不同的CPU块(加载器、解码器等)处理后续指令。当
RET
指令被执行时,接下来的指令很少已经加载到CPU管道中。这是一个猜测,但您可以在这里开始挖掘,如果您找到了(也许是安全的NOP
的具体数量,请分享您的发现。As far as I remember, instructions are pipelined in cpu and different cpu blocks (loader, decoder and such) process subsequent instructions. When
RET
instructions is being executed, few next instructions are already loaded into cpu pipeline. It's a guess, but you can start digging here and if you find out (maybe the specific number ofNOP
s that are safe, share your findings please.