把C语言编译成汇编是什么样子:4、如何用低级的汇编程序实现高级语言中【数组】功能?

158 阅读1分钟

汇编指令中是没有数组概念的,数组是高级语言中抽象出来的一个一块内存数据的概念,它有数据类型,也有自己的长度,那如何用简单的汇编指令实现抽象的数组功能的?

老规矩,先上一段简单的一看就懂的C语言代码:

#include<stdio.h>
int main(){
    int arr[5] = {1, 2, 3, 4, 5};
    arr[2] = 22;
    arr[4] = 44;
    return 0;
}

下面是上述代码对应的汇编代码:

	subq	$32, %rsp
	movq	%fs:40, %rax
	movq	%rax, -8(%rbp)
	xorl	%eax, %eax
	movl	$1, -32(%rbp)
	movl	$2, -28(%rbp)
	movl	$3, -24(%rbp)
	movl	$4, -20(%rbp)
	movl	$5, -16(%rbp)
	movl	$22, -24(%rbp)
	movl	$44, -16(%rbp)
	movl	$0, %eax
	movq	-8(%rbp), %rdx
	xorq	%fs:40, %rdx
	je	.L3
	call	__stack_chk_fail@PLT
.L3:
	leave
        

上面是一维数组,下面是二维数组:

#include<stdio.h>
int main(){

   int arr[2][5] = {{1, 2, 3, 4, 5},
                   {6,7,8,9,10}};
   arr[0][2] = 222;
   arr[1][4] = 444;  
   return 0;
}

********************** 汇编程序 ************************
subq	$48, %rsp
   movq	%fs:40, %rax
   movq	%rax, -8(%rbp)
   xorl	%eax, %eax
   movl	$1, -48(%rbp)
   movl	$2, -44(%rbp)
   movl	$3, -40(%rbp)
   movl	$4, -36(%rbp)
   movl	$5, -32(%rbp)
   movl	$6, -28(%rbp)
   movl	$7, -24(%rbp)
   movl	$8, -20(%rbp)
   movl	$9, -16(%rbp)
   movl	$10, -12(%rbp)
   movl	$222, -40(%rbp)
   movl	$444, -12(%rbp)
   movl	$0, %eax
   movq	-8(%rbp), %rdx
   xorq	%fs:40, %rdx
   je	.L3
   call	__stack_chk_fail@PLT
.L3:
   leave

数组操作没什么好说的,总的来说就是直接分配了好几个int,而当你用指针下标去读取或修改数组内的某个元素时,比如这里的arr[4] = 44,这里是怎么找到arr[4]这个元素的?实际上是编译器计算的,编译器把arr[4]对应的关于栈帧rbp的相对地址算出来了,然后提供一条指令直接给这个内存单元赋值44,也就是汇编代码里的movl $44, -16(%rbp),一切都是编译器计算好了的。

因此,所谓数组概念,其实就是编译器提前算好的地址,并将这块内存地址当成这个数组,以后操作数组,就利用简单的汇编指令操作这块内存就是了。那么,其它复杂的数组操作时怎么做到的呢?我们会在后面指针部分做详细揭晓。