汇编,数组

这篇博客探讨了C语言中数组的初始化和累加操作,并展示了不同编译优化级别(-O0和-O3)下代码的实现差异。在-O0级别,代码清晰易读,而在-O3级别,编译器利用SSE指令进行了优化,提高了执行效率。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值