c - 对齐堆栈是什么意思?

标签 c assembly gcc x86 memory-alignment

我一直是一名高级编码员,架构对我来说还很陌生,所以我决定在这里阅读关于汇编的教程:

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

解释是:

This code "and"s ESP with 0xFFFFFFF0, aligning the stack with the next lowest 16-byte boundary. An examination of Mingw's source code reveals that this may be for SIMD instructions appearing in the "_main" routine, which operate only on aligned addresses. Since our routine doesn't contain SIMD instructions, this line is unnecessary.

我不明白这一点。有人可以解释一下将堆栈与下一个 16 字节边界对齐的含义以及为什么需要这样做吗? andl 是如何做到这一点的?

最佳答案

假设堆栈在 _main 的入口处看起来像这样(堆栈指针的地址只是一个示例):

|    existing     |
|  stack content  |
+-----------------+  <--- 0xbfff1230

压入%ebp,并从%esp中减去8,为局部变量保留一些空间:

|    existing     |
|  stack content  |
+-----------------+  <--- 0xbfff1230
|      %ebp       |
+-----------------+  <--- 0xbfff122c
:    reserved     :
:     space       :
+-----------------+  <--- 0xbfff1224

现在,andl 指令将 %esp 的低 4 位清零,这可能会减少它;在此特定示例中,它具有保留额外 4 个字节的效果:

|    existing     |
|  stack content  |
+-----------------+  <--- 0xbfff1230
|      %ebp       |
+-----------------+  <--- 0xbfff122c
:    reserved     :
:     space       :
+ - - - - - - - - +  <--- 0xbfff1224
:   extra space   :
+-----------------+  <--- 0xbfff1220

重点是有一些“SIMD”(单指令,多数据)指令(在 x86 领域也称为“SSE”,表示“流式 SIMD 扩展”)可以对多个字执行并行操作内存,但要求这些多个字是一个 block ,起始地址是 16 字节的倍数。

一般来说,编译器不能假定 %esp 的特定偏移量会产生一个合适的地址(因为 %esp 在函数入口处的状态取决于调用代码)。但是,通过以这种方式有意对齐堆栈指针,编译器知道将 16 字节的任意倍数添加到堆栈指针将产生 16 字节对齐的地址,这对于这些 SIMD 指令的使用是安全的。

关于c - 对齐堆栈是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26783564/

相关文章:

c - 从内核获取当前驱动器路径

c - C:如何阅读网页

c - 合并其他 .c 文件时 Makefile 返回错误

c - 我如何告诉 gcc 不要内联函数?

c - 一个直接、简单的 api 作为系统运行?

c++ - 配置gmp时出错

linux nasm 程序集不断地打印字符

c++ - 获取内存段信息

assembly - 为什么switch_to使用push+jmp+ret来改变EIP,而不是直接jmp?

c - 如何扩展C程序中嵌入的文件资源