【发布时间】:2012-01-18 16:38:32
【问题描述】:
我有以下 C 程序:
int main()
{
int c[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2};
return c[0];
}
当使用带有 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
我不明白的是为什么较早的数组元素离 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
使用以下 C 程序:
static int c[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2};
int main()
{
return c[0];
}
这并没有提供对堆栈的更多了解。但是看到汇编的不同输出使用略有不同的语义是很有趣的。
【问题讨论】:
-
那是使用 gcc 命令生成的代码,通常编译器会生成执行相同操作的不同代码。基本上,一个问题有多种解决方案。编译时是否使用 -o 进行了优化?可能是因为这个(或缺乏)。
-
这实际上是编译器生成的代码,和编译器生成的代码不能有区别。优化标志是
-O而不是-o,是的,马修使用了-Os,正如他在问题中明确指出的那样...... -
他说
-S(将程序集生成为文本),而不是-Os(优化大小)。这个程序集似乎是在没有优化的情况下生成的;在-O的任何级别,我看到数组存储完全消失了。
标签: c gcc assembly gnu-assembler