以下内容源于网络资源的学习与整理,如有侵权请告知删除。
一、LDR/STR架构
ARM采用RISC架构,CPU本身不能直接读取内存,需要先将内存中的内容加载到CPU的通用寄存器中才能被CPU处理。换言之,寄存器是CPU和内存进行数据交换的中介。
通过ldr与str命令组合,可以实现CPU和内存数据交换。其中ldr(load register)指令将内存的内容加载到通用寄存器,str(store register)指令将寄存器的内容存入内存空间中。比如 ldr r0,[r1] 和 str r0,[r1],注意前者是向左,后者是向右。
注意,寄存器之间数据交换用mov指令,内存和寄存器之间用ldr和str指令。
二、寻址方式
(1)寄存器寻址
mov r1, r2 @把r2中的内容赋给r1
(2)立即数寻址
mov r0, #0xFF00 @#后面直接加数字,#表示后面的是数字,把0xFF00赋值给r0
(3)寄存器移位寻址
mov r0, r1, lsl #3 @把r1左移3位后,赋给r0
(4)寄存器间接寻址
ldr r1, [r2] @ r2寄存器中的内容是一个内存地址,[r2]表示该这个内存地址中的内容。@ 即r2相当指针,[r2]相当指针解引用。
(5)基址变址寻址
ldr r1, [r2, #4] @ r2存的内容是一个地址,该地址加上4,才是真正的地址
(6)多寄存器寻址
ldmia r1!, {r2-r7, r12} @ r1相当于数组名,将以其为开始的内容,分别存入后面的寄存器中。
(7)堆栈寻址
stmfd sp!, {r2-r7, lr} @ 类似于上述
(8)相对寻址
beq flag @ flag表示标号,表示一个入口点。@ 因为用pc和相对偏移量,所以叫相对寻址。
三、指令后缀
同一指令可以附带不同后缀,其基本功能不变,但表示更多含义。
(1)B(byte),功能不变,操作长度变为8位。
(2)H(half word),功能不变,长度变为16位。
(3)S(signed),功能不变,操作数变为有符号。
(4)S(S标志),功能不变,影响CPSR标志位。比如mov和movs:
movs r0, #0 @ 这指令会影响标志位:只要最后运算结果为0,那么z就会为1
四、条件后缀
(1)条件后缀是否成立,取决于该句代码的上一句代码的运行结果。如果成立,本句代码将得以执行,如果不成立,则忽略本句代码而去执行下一句代码。
mov r0,r1 @相当于C语言中的r0=r1
moveq r0,r1 @如果条件后缀eq成立,直接执行mov r0,r1;如果eq不成立则本句代码不执行@这个例子中,如果标志z=1,则该句代码执行
(2)下面是一些条件后缀列表。其中常用的是EQ和NE,如beq就是b和eq的组合。
五、多级指令流水线
为增加处理器指令流的速度,ARM使用多级流水线,下图为3级流水线工作原理示意图。
注意,PC指向正被取址的指令,而非正在执行的指令。这会影响中断返回的地址。
因为ARM模式下,3级流水线差2个周期,每个周期4个字节,所以差8个字节。
六、伪指令与伪操作
1、伪指令
伪指令和汇编指令一样,在汇编的时候都会生成机器码。
它们的不同点在于汇编时,汇编指令只对应着一条机器码,伪指令可以对应着多条机器码,或者说一条伪指令对应着多条汇编指令。
ARM伪指令有LDR、ADR、ADRL和NOP,具体描述见博文ARM官方汇编指令_天糊土的博客。
2、伪操作
伪操作一般用来指导汇编器的汇编工作,本身不对应着任何机器码。
不同的汇编器对应的伪操作是不同的,这里讨论的伪操作是基于GNU汇编器而言的,GNU汇编器下的伪操作一般都用点号“.”作为开头。
3、宏指令
宏指令是由用户按照宏定义格式编写的一段代码,其中的语句可以是指令与伪指令。