为了账号安全,请及时绑定邮箱和手机立即绑定

对齐堆栈是什么意思?

对齐堆栈是什么意思?

C
江户川乱折腾 2019-11-11 15:45:11
我一直是高级编码人员,而体系结构对我来说还很新,所以我决定在此处阅读有关Assembly的教程:http://en.wikibooks.org/wiki/X86_Assembly/Print_Version在教程的最下方,提供了有关如何转换Hello World的说明!程序#include <stdio.h>int main(void) {    printf("Hello, world!\n");    return 0;}给出了等效的汇编代码,并生成了以下代码:        .textLC0:        .ascii "Hello, world!\12\0".globl _main_main:        pushl   %ebp        movl    %esp, %ebp        subl    $8, %esp        andl    $-16, %esp        movl    $0, %eax        movl    %eax, -4(%ebp)        movl    -4(%ebp), %eax        call    __alloca        call    ___main        movl    $LC0, (%esp)        call    _printf        movl    $0, %eax        leave        ret对于其中一条线,andl    $-16, %esp原因是:此代码用0xFFFFFFF0“和” ESP,使堆栈与下一个最低的16字节边界对齐。对Mingw的源代码进行检查后发现,这可能适用于出现在“ _main”例程中的SIMD指令,该指令仅在对齐的地址上运行。由于我们的例程不包含SIMD指令,因此此行是不必要的。我不明白这一点。有人可以给我解释一下将堆栈与下一个16字节边界对齐是什么意思,为什么要这样做?以及如何andl实现这一目标?
查看完整描述

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指令而言,这是安全的。


查看完整回答
反对 回复 2019-11-11
?
慕妹3146593

TA贡献1820条经验 获得超9个赞

想象一下这个“绘图”


地址

 xxx0123456789abcdef01234567 ...

    [------] [------] [------] ...

寄存器

地址的值容易以8“ slide”的倍数进入(64位)寄存器


地址

         56789abc ...

    [------] [------] [------] ...

寄存器

当然要以8字节为步长来注册“遍历”


现在,如果您要将地址xxx5的值放入寄存器,则要困难得多:-)


编辑和-16


-16是二进制的11111111111111111111111111110000


当您用-16进行“和”运算时,您将得到一个最后4位设置为0 ...或16的倍数的值。


查看完整回答
反对 回复 2019-11-11
  • 3 回答
  • 0 关注
  • 973 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信