汇编 —— 数组

基本原则

对于数据类型T和整型常数N,声明如下即为数组:

T a[N];

起始位置表示为Xa,这个声明有两个效果:

  • 在内存中分配一个sizeof(T)*N字节的连续的区域
  • 引入标识符a,可以用a来作为指向数组开头的指针,这个指针的值就是Xa

而在x86-64中的内存引用指令可以用来简化数组访问,比如说,E是一个int型的数组,而我们想要计算E[i],假设E的地址放在寄存器%rdx中,i 放在寄存器%rcx中,那么访问E[i]的汇编指令便是这个:

movl (%rdx,%rcx,4),%eax

这个指令会执行计算Xe+4i,之后读出这个内存的值,将结果放到寄存器%eax中。

指针运算

可以说C/C++ 的灵魂就是就是指针了,指针计算出来的值会根据该指针引用的数据类型的大小进行伸缩。也就是说,如果 p 是一个指向类型为T的数据的指针,p的值为Xp,那么表达式 p+i 的值为Xp+sizeof(T)+i

单个操作数操作符&*可以产生指针和间接引用指针。下表是刚刚例子的扩展:
在这里插入图片描述

练习题

在这里插入图片描述
在这里插入图片描述

练习题答案

在这里插入图片描述

嵌套数组

当我们创建嵌套数组的时候,数组分配和引用的规则其实也是成立的。比如下面的声明:

int A[5][3];

等价于下面的声明:

typedef int row3_t[3];
row3_t A[5];

要访问这样的多维数组的元素,编译器会以数组起始为基地址,偏移量为索引,产生计算期望的元素的偏移量,然后使用某种mov指令。
在这里插入图片描述

通常来说,对于一个如下声明的数组:

T D[R][C];

它的数组元素D[i][j]的内存地址为:

&D[i][j] = Xd + sizeof(T)*(C*i + j)

那么假设Xd、i、j 分别在寄存器%rdi%rsi%rdx中,那么可以看一下下面的汇编:

//A in %rdi,i in %rsi,j in %rdx
leaq	(%rsi, %rsi,2), %rax		//3i
leaq	(%rdi , %rax,4), %rax		//Xd+12i
movl	(%rax , %rdx,4), %eax		//M[Xd+12i+4j]

练习题

在这里插入图片描述

练习题答案

在这里插入图片描述

参考文献

[1] 深入理解计算机系统 第三章 程序的机器级表示
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shenmingik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值