对齐堆栈是什么意思?

我一直是高级编码人员,而体系结构对我来说还很新,所以我决定在此处阅读有关Assembly的教程:


http://en.wikibooks.org/wiki/X86_Assembly/Print_Version


在教程的最下方,提供了有关如何转换Hello World的说明!程序


#include <stdio.h>


int main(void) {

    printf("Hello, world!\n");

    return 0;

}

给出了等效的汇编代码,并生成了以下代码:


        .text

LC0:

        .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实现这一目标?


江户川乱折腾
浏览 979回答 3
3回答

吃鸡游戏

假设堆栈在进入时看起来像这样_main(堆栈指针的地址只是一个示例):|&nbsp; &nbsp; existing&nbsp; &nbsp; &nbsp;||&nbsp; stack content&nbsp; |+-----------------+&nbsp; <--- 0xbfff1230按下%ebp,然后减去8,%esp为局部变量保留一些空间:|&nbsp; &nbsp; existing&nbsp; &nbsp; &nbsp;||&nbsp; stack content&nbsp; |+-----------------+&nbsp; <--- 0xbfff1230|&nbsp; &nbsp; &nbsp; %ebp&nbsp; &nbsp; &nbsp; &nbsp;|+-----------------+&nbsp; <--- 0xbfff122c:&nbsp; &nbsp; reserved&nbsp; &nbsp; &nbsp;::&nbsp; &nbsp; &nbsp;space&nbsp; &nbsp; &nbsp; &nbsp;:+-----------------+&nbsp; <--- 0xbfff1224现在,andl指令将的低4位清零%esp,这可能会减少它;在此特定示例中,它具有保留额外的4个字节的效果:|&nbsp; &nbsp; existing&nbsp; &nbsp; &nbsp;||&nbsp; stack content&nbsp; |+-----------------+&nbsp; <--- 0xbfff1230|&nbsp; &nbsp; &nbsp; %ebp&nbsp; &nbsp; &nbsp; &nbsp;|+-----------------+&nbsp; <--- 0xbfff122c:&nbsp; &nbsp; reserved&nbsp; &nbsp; &nbsp;::&nbsp; &nbsp; &nbsp;space&nbsp; &nbsp; &nbsp; &nbsp;:+ - - - - - - - - +&nbsp; <--- 0xbfff1224:&nbsp; &nbsp;extra space&nbsp; &nbsp;:+-----------------+&nbsp; <--- 0xbfff1220这样做的重点是存在一些“ SIMD”(单指令,多数据)指令(在x86-land中也称为“流SIMD扩展”的“ SSE”),它们可以对内存中的多个字执行并行操作,但是要求这些多个字成为从16字节倍数的地址开始的块。通常,编译器无法假定的特定偏移量%esp会导致产生合适的地址(因为%esp该函数的进入状态取决于调用代码)。但是,通过以这种方式故意对齐堆栈指针,编译器知道向堆栈指针添加16字节的任何倍数将导致16字节对齐的地址,对于这些SIMD指令而言,这是安全的。

慕妹3146593

想象一下这个“绘图”地址&nbsp;xxx0123456789abcdef01234567 ...&nbsp; &nbsp; [------] [------] [------] ...寄存器地址的值容易以8“ slide”的倍数进入(64位)寄存器地址&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;56789abc ...&nbsp; &nbsp; [------] [------] [------] ...寄存器当然要以8字节为步长来注册“遍历”现在,如果您要将地址xxx5的值放入寄存器,则要困难得多:-)编辑和-16-16是二进制的11111111111111111111111111110000当您用-16进行“和”运算时,您将得到一个最后4位设置为0 ...或16的倍数的值。
打开App,查看更多内容
随时随地看视频慕课网APP