如上图程序所示,程序运行流程为:
1.跳转至main所在地址
2.加载全局变量counter地址??main_2到R0
3.将变量值存入R0
4.R0自增指令载入
5.加载counter地址到R1
6.通过R1的地址,R0取到counter的值
??main_1最终结果R0存值,R1存地址。
《深入理解计算机系统》中写道:
大多数指令有一个或多个操作数(operand),指示出执行一个操作中要使用的源数据值,以及放置结果的目的位置。x86-64 支持多种操作数格式(参见图 3-3)。源数据值可以以常数形式给出,或是从寄存器或内存中读出。结果可以存放在寄存器或内存中。因此,各种不同的操作数的可能性被分为三种类型。
第一种类型是立即数(immediate),用来表示常数值。在 ATT 格式的汇编代码中,立即数的书写方式是 ‘$’ 后面跟一个用标准 C 表示法表示的整数,比如,$-577 或 $0x1F。不同的指令允许的立即数值范围不同,汇编器会自动选择最紧凑的方式进行数值编码。
第二种类型是寄存器(register),它表示某个寄存器的内容,16 个寄存器的低位 1 字节、2 字节、4 字节或 8 字节中的一个作为操作数,这些字节数分别对应于 8 位、16 位、32 位或 64 位。在图 3-3 中,我们用符号 rara 来表示任意寄存器 a,用引用R[ra]R[ra]来表示它的值,这是将寄存器集合看成一个数组 R,用寄存器标识符作为索引。
第三类操作数是内存引用,它会根据计算出来的地址(通常称为有效地址)访问某个内存位置。因为将内存看成一个很大的字节数组,我们用符号Mb[Addr]Mb[Addr]表示对存储在内存中从地址 Addr 开始的 b 个字节值的引用。为了简便,我们通常省去下标 b。
可以观察到程序运行和指令加载有差异,ARM处理器访问内存时,内存只能由特殊的加载指令读取,数据操作只发生在寄存器。如图所示,处理while(counter<21)时,我们是先运行判断,再运行自增。但是指令的加载,是先加载了自增指令,再进行判断的。
ARM架构单片机采用RISC,RISC(Reduced Instruction Set Computer)是精简指令集计算机,它是一种计算机架构,旨在通过减少指令集的复杂性来提高计算机的性能和效率。RISC架构使用一组简单的指令,每条指令完成一个简单的操作,这些指令的执行时间相对较短并且相对统一,这样可以提高指令的执行速度。
与RISC相对的是CISC(Complex Instruction Set Computer),CISC架构使用复杂的指令,每条指令可以完成多个操作,这些指令的执行时间可能不一致。CISC架构可能就不需要取出来放在寄存器中,而是在内存中就可以完成数据操作。
在??main_0指令段,
1.载入counter地址到R0
2.通过地址访问值
3.发生比较,APSR(截图右侧)输出N=1
4.如果是N,则跳转到自增指令段,如果不是,则顺序执行
假如使用的是指针,则减少了指令数,加快了程序运行。因为指针指向了地址,略去了载入地址的步骤