1)
#include <stdio.h>
void main()
{
int ss=0;
int arr[100];
for(int i=0;i<100;i++)
{
arr[i]=i;
}
for(int i=0;i<100;i++)
{
ss=ss+arr[i];
}
printf("%d\n",ss);
}
2) -O0 -S
差不多能够看懂,不知道alloc是怎么分配数组的。目前arr[100]在堆栈中。
.file "b6.array.c"
.text
.section .rodata
.LC0:
.string "%d\n"
.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
subq $432, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movl $0, -428(%rbp) # ss
movl $0, -424(%rbp) # i值的判断
jmp .L2
.L3:
movl -424(%rbp), %eax # eax=i
cltq # 它的符号将4个字节扩展为8个字节
movl -424(%rbp), %edx # edx=i
movl %edx, -416(%rbp,%rax,4) # rax*4 + rbp -416 =i,对数组赋值
addl $1, -424(%rbp) # i=i+1
.L2:
cmpl $99, -424(%rbp) # i和99进行比较
jle .L3
movl $0, -420(%rbp) # -420干嘛?
jmp .L4
.L5: # L5怎么和L3差不多,搞两遍吗?前面是赋值,后面是求和
movl -420(%rbp), %eax #i
cltq
movl -416(%rbp,%rax,4), %eax # eax = arr[i]
addl %eax, -428(%rbp) # ss=ss+arr[i]
addl $1, -420(%rbp) # i=i+1
.L4:
cmpl $99, -420(%rbp)
jle .L5
# 下面几句是打印 printf("%d\n",ss);
movl -428(%rbp), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl $0, %eax # 没有啥用吧?
call printf@PLT
nop
# 后面两在确认咐?
movq -8(%rbp), %rax
xorq %fs:40, %rax
je .L6
call __stack_chk_fail@PLT
.L6:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
3)
-O3后完全看不懂了,自动转化成SSE指令或者AVX指令,编译器真的还是比较牛逼。
.file "b6.array.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC2:
.string "sum=%d\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
.cfi_startproc
subq $424, %rsp
.cfi_def_cfa_offset 432
movq %rsp, %rdx
# MOVDQA - 移动对齐的双四字
# 将双四字从源操作数(第二个操作数)移到目标操作数(第一个操作数)。
# 此指令可以用于在 XMM 寄存器与 128 位内存位置之间移入/移出双四字,或是在两个 XMM 寄存器之间移动。
# 源操作数或目标操作数是内存操作数时,操作数必须对齐 16 字节边界,否则将生成一般保护性异常 (#GP)。
movdqa .LC0(%rip), %xmm0
leaq 400(%rdx), %rcx
movdqa .LC1(%rip), %xmm1
movq %fs:40, %rax
movq %rax, 408(%rsp)
xorl %eax, %eax
movq %rdx, %rax
.p2align 4,,10
.p2align 3
.L2:
movaps %xmm0, (%rax) # 要移动挤满单precision浮点值或从 未对齐的内存位置,使用MOVUPS指令。
paddd %xmm1, %xmm0
addq $16, %rax #每次4个
cmpq %rax, %rcx # 100个?
jne .L2
pxor %xmm0, %xmm0
.p2align 4,,10
.p2align 3
.L3:
paddd (%rdx), %xmm0
addq $16, %rdx
cmpq %rax, %rdx
jne .L3
movdqa %xmm0, %xmm1
movq 408(%rsp), %rax
xorq %fs:40, %rax
psrldq $8, %xmm1
paddd %xmm1, %xmm0
movdqa %xmm0, %xmm1
psrldq $4, %xmm1
jne .L10
paddd %xmm1, %xmm0
leaq .LC2(%rip), %rsi
movd %xmm0, %edx
movl $1, %edi
xorl %eax, %eax
addq $424, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 8
jmp __printf_chk@PLT
.L10:
.cfi_restore_state
call __stack_chk_fail@PLT
.cfi_endproc
.LFE23:
.size main, .-main
.section .rodata.cst16,"aM",@progbits,16
.align 16
.LC0:
.long 0
.long 1
.long 2
.long 3
.align 16
.LC1:
.long 4
.long 4
.long 4
.long 4
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
这篇博客探讨了C语言中数组的初始化和累加操作,并展示了不同编译优化级别(-O0和-O3)下代码的实现差异。在-O0级别,代码清晰易读,而在-O3级别,编译器利用SSE指令进行了优化,提高了执行效率。
5058

被折叠的 条评论
为什么被折叠?



