3 回答
TA贡献1829条经验 获得超7个赞
假设堆栈在进入时看起来像这样_main(堆栈指针的地址只是一个示例):
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
按下%ebp,然后减去8,%esp为局部变量保留一些空间:
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
| %ebp |
+-----------------+ <--- 0xbfff122c
: reserved :
: space :
+-----------------+ <--- 0xbfff1224
现在,andl指令将的低4位清零%esp,这可能会减少它;在此特定示例中,它具有保留额外的4个字节的效果:
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
| %ebp |
+-----------------+ <--- 0xbfff122c
: reserved :
: space :
+ - - - - - - - - + <--- 0xbfff1224
: extra space :
+-----------------+ <--- 0xbfff1220
这样做的重点是存在一些“ SIMD”(单指令,多数据)指令(在x86-land中也称为“流SIMD扩展”的“ SSE”),它们可以对内存中的多个字执行并行操作,但是要求这些多个字成为从16字节倍数的地址开始的块。
通常,编译器无法假定的特定偏移量%esp会导致产生合适的地址(因为%esp该函数的进入状态取决于调用代码)。但是,通过以这种方式故意对齐堆栈指针,编译器知道向堆栈指针添加16字节的任何倍数将导致16字节对齐的地址,对于这些SIMD指令而言,这是安全的。
TA贡献1820条经验 获得超9个赞
想象一下这个“绘图”
地址
xxx0123456789abcdef01234567 ...
[------] [------] [------] ...
寄存器
地址的值容易以8“ slide”的倍数进入(64位)寄存器
地址
56789abc ...
[------] [------] [------] ...
寄存器
当然要以8字节为步长来注册“遍历”
现在,如果您要将地址xxx5的值放入寄存器,则要困难得多:-)
编辑和-16
-16是二进制的11111111111111111111111111110000
当您用-16进行“和”运算时,您将得到一个最后4位设置为0 ...或16的倍数的值。
- 3 回答
- 0 关注
- 1016 浏览
添加回答
举报