了解基指针和堆栈指针:在gcc输出的上下文中

Mat*_*gan 11 c assembly gcc gnu-assembler

我有以下C程序:

int main()
{
    int c[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2};
    return c[0];
}
Run Code Online (Sandbox Code Playgroud)

当使用带有gcc的-S指令编译时,我得到以下程序集:

    .file   "array.c"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $0, -48(%rbp)
    movl    $0, -44(%rbp)
    movl    $0, -40(%rbp)
    movl    $0, -36(%rbp)
    movl    $0, -32(%rbp)
    movl    $0, -28(%rbp)
    movl    $0, -24(%rbp)
    movl    $0, -20(%rbp)
    movl    $1, -16(%rbp)
    movl    $2, -12(%rbp)
    movl    -48(%rbp), %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)"
    .section        .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我不明白为什么早期的数组元素远离bp?几乎看起来阵列上的元素以相反的顺序放置.

另外为什么gcc不使用push而不是movl来将数组元素推入堆栈?


不同的视图

将数组作为静态变量移动到全局命名空间到我得到的模块:

    .file   "array.c"
    .data
    .align 32
    .type   c, @object
    .size   c, 40
c:
    .long   0
    .long   0
    .long   0
    .long   0
    .long   0
    .long   0
    .long   0
    .long   0
    .long   1
    .long   2
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    c(%rip), %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

使用以下C程序:

static int c[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2};

int main() 
{
    return c[0];
}
Run Code Online (Sandbox Code Playgroud)

这不会给堆栈带来更多洞察力.但是,使用稍微不同的语义来查看汇编的差异输出是很有趣的.

NPE*_*NPE 9

首先,x86堆栈向下增长.按照惯例,rbp存储原始值rsp.因此,函数的参数位于相对于的偏移处rbp,并且其自动变量位于偏移处.自动数组的第一个元素的地址低于所有其他元素,因此距离最远rbp.

以下是此页面上显示的方便图表:

堆栈布局

我认为没有理由为什么编译器不能使用一系列push指令来初始化你的数组.这不是一个好主意,我不确定.