Aym*_*uma 17 linux compiler-construction x86 assembly gcc
嗨,我已经拆解了一些程序(linux),我写的是为了更好地理解它是如何工作的,我注意到主要功能始终以:
lea ecx,[esp+0x4] ; I assume this is for getting the adress of the first argument of the main...why ?
and esp,0xfffffff0 ; ??? is the compiler trying to align the stack pointer on 16 bytes ???
push DWORD PTR [ecx-0x4] ; I understand the assembler is pushing the return adress....why ?
push ebp
mov ebp,esp
push ecx ;why is ecx pushed too ??
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:为什么所有这些工作都完成了?我只了解使用:
push ebp
mov ebp,esp
Run Code Online (Sandbox Code Playgroud)
其余对我来说似乎毫无用处......
Ins*_*lah 27
我已经开始了:
;# As you have already noticed, the compiler wants to align the stack
;# pointer on a 16 byte boundary before it pushes anything. That's
;# because certain instructions' memory access needs to be aligned
;# that way.
;# So in order to first save the original offset of esp (+4), it
;# executes the first instruction:
lea ecx,[esp+0x4]
;# Now alignment can happen. Without the previous insn the next one
;# would have made the original esp unrecoverable:
and esp,0xfffffff0
;# Next it pushes the return addresss and creates a stack frame. I
;# assume it now wants to make the stack look like a normal
;# subroutine call:
push DWORD PTR [ecx-0x4]
push ebp
mov ebp,esp
;# Remember that ecx is still the only value that can restore the
;# original esp. Since ecx may be garbled by any subroutine calls,
;# it has to save it somewhere:
push ecx
Run Code Online (Sandbox Code Playgroud)
这样做是为了使堆栈与16字节边界对齐.某些指令要求某些数据类型与16字节边界对齐.为了满足这一要求,GCC确保堆栈最初是16字节对齐的,并以16字节的倍数分配堆栈空间.这可以使用选项-mpreferred-stack-boundary = num来控制.如果使用-mpreferred-stack-boundary = 2(对于2 2 = 4字节对齐),则不会生成此对齐代码,因为堆栈始终至少对齐4个字节.但是,如果您的程序使用任何需要更强对齐的数据类型,那么您可能会遇到麻烦.
根据gcc手册:
在Pentium和PentiumPro上,double和long double值应与8字节边界对齐(请参阅-malign-double)或遭受严重的运行时性能损失.在Pentium III上,如果不是16字节对齐,则流式SIMD扩展(SSE)数据类型__m128可能无法正常工作.
为了确保在堆栈上正确对齐这些值,堆栈边界必须与存储在堆栈中的任何值所需的对齐.此外,必须生成每个函数,使其保持堆栈对齐.因此,从使用较低优选堆栈边界编译的函数调用使用较高优选堆栈边界编译的函数很可能使堆栈不对齐.建议使用回调的库始终使用默认设置.
这种额外的对齐会消耗额外的堆栈空间,并且通常会增加代码大小.对堆栈空间使用敏感的代码(例如嵌入式系统和操作系统内核)可能希望将首选对齐减少到-mpreferred-stack-boundary = 2.
由于堆栈指针即将被修改,因此lea将原始堆栈指针(从调用之前main)加载ecx到其中.这用于两个目的:
main函数的参数,因为它们是相对于原始堆栈指针的main| 归档时间: |
|
| 查看次数: |
3966 次 |
| 最近记录: |