使用汇编语言完成下列C的数组赋值,汇编中的数组分配和指针的实现代码

数组简介

如果各位猿友是一路跟着LZ看到这里的,那么数组的定义就非常简单了,它就是一个相同数据类型的数据集合。数组存储在一系列逻辑上连续的内存块当中,之所以说是逻辑上连续,是因为整个内存或者说存储器本身就是逻辑上连续的一个大内存数组。如果我们用Java语言的类型来表示我们的存储器的话,可以看做是byte[] memory这样的类型。

数组的定义非常简单,它遵循以下这样简单的规则。

T N[L];

这当中T表示数据类型,N是变量名称,L是数组长度。这样的声明会做两件事,首先是在内存当中开辟一个长为L*length(T)的内存空间(其中length(T)是指数据类型的字节长度),然后将这块内存空间的起始地址赋给变量N。当我们使用N[index]去读取数组元素的时候,我们会去读N+index*length(T)的内存位置,这一点并不难理解。

指针操作数组

在C语言当中,*符号可以取一个指针指向的内存区域的值,而对于数组来说,*符号依然可以这样做。因此,我们可以很轻松地想到,对于上面的声明来说,*N就相当于N[0],类似的,*(N+1)就相当于N[1],以此类推。

在上面*(N+1)这样的方式当中,我们其实对指针进行了运算,即对数组的起始地址N加了上1。在这一过程中,编译器会帮我们自动乘上数据类型的长度(比如int为4),如此一来,我们的指针运算才算是正确了,比如对于*(N+1)来说,假设T为int类型,则 【实际地址(N+1)】 = N + 1 * 4。对于这一点,我们可以用以下这个小程序来验证一下,从这个程序可以很明显的看出来,当我们对指针进行加1操作的时候,实际的地址会被乘以数据类型的长度。

19904153c4cd41bea4c07ae9193401ff.png

定长和变长数组

要理解定长和变长数组,我们必须搞清楚一个概念,就是说这个“定”和“变”是针对什么来说的。在这里我们说,这两个字是针对编译器来说的,也就是说,如果在编译时数组的长度确定,我们就称为定长数组,反之则称为变长数组。

比如上图当中的示例,就是一个定长数组,它的长度为10,它的长度在编译时已经确定了,因为长度是一个常量。之前的C编译器不允许在声明数组时,将长度定义为一个变量,而只能是常量,不过当前的C/C++编译器已经开始支持动态数组,但是C++的编译器依然不支持方法参数。另外,C语言还提供了类似malloc和calloc这样的函数动态的分配内存空间,我们可以将返回结果强转为想要的数组类型。

接下来,LZ和各位一起分析一个有关数组的C程序,我们先来一个简单的,也就是一个定长数组,我们看下在汇编级别是如何操作定长数组的。需要一提的是,由于数组的长度固定,所以有的时候编译器会根据实际情况作出一些优化,以下是一个简单的小程序。

int main(){

int a[5];

int i,sum;

for(i = 0 ; i < 5; i++){

a[i] = i * 3;

}

for(i = 0 ; i < 5; i++){

sum += a[i];

}

return sum;

}

以上这个小程序的功能LZ就不介绍了,如果哪位猿友看不懂,请自觉面壁吧。下面我们来看下-S和-O1下的汇编代码,如下所示。

main:

pushl %ebp

movl %esp, %ebp//到此准备好栈帧

subl $32, %esp//分配32个字节的空间

leal -20(%ebp), %edx//将帧指针减去20赋给%edx寄存器?为什么?你能猜到吗?

movl $0, %eax//将%eax设置为0,这里的%eax寄存器是重点

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用汇编语言定义数组并为其赋值的示例代码: ``` section .data array db 1, 2, 3, 4, 5 ; 定义一个长度为5的字节数组并赋初值 section .text global _start _start: ; 访问数组元素 mov al, [array] ; 将数组第一个元素赋给 al 寄存器 mov bl, [array + 1] ; 将数组第二个元素赋给 bl 寄存器 mov cl, [array + 2] ; 将数组第三个元素赋给 cl 寄存器 mov dl, [array + 3] ; 将数组第四个元素赋给 dl 寄存器 mov ah, [array + 4] ; 将数组第五个元素赋给 ah 寄存器 ; 输出数组元素 ; 假设已经定义了输出整数的函数,函数名为print_int push dword [array] ; 将数组第一个元素的地址压入栈 call print_int ; 调用输出函数 add esp, 4 ; 栈指针回退4个字节 push dword [array + 1] ; 将数组第二个元素的地址压入栈 call print_int ; 调用输出函数 add esp, 4 ; 栈指针回退4个字节 push dword [array + 2] ; 将数组第三个元素的地址压入栈 call print_int ; 调用输出函数 add esp, 4 ; 栈指针回退4个字节 push dword [array + 3] ; 将数组第四个元素的地址压入栈 call print_int ; 调用输出函数 add esp, 4 ; 栈指针回退4个字节 push dword [array + 4] ; 将数组第五个元素的地址压入栈 call print_int ; 调用输出函数 add esp, 4 ; 栈指针回退4个字节 ; 程序结束 mov eax, 1 ; 系统调用号为1表示退出程序 xor ebx, ebx ; 返回值为0 int 0x80 ; 执行系统调用 ``` 在上述代码数组的定义和赋值在 `.data` 段进行,使用 `db` 指令定义了一个长度为5的字节数组,并为其赋初值。在 `.text` 段使用 `mov` 指令访问数组元素,并使用函数 `print_int` 输出数组元素。最后,使用系统调用,退出程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值