汇编指令分为指令和伪指令
指令:针对于CPU设计的指令。作用在CPU上。
伪指令:针对于编译器设计的指令。作用在编译器上,用来知道编译过程,经过编译后伪指令最终不会生成机器码。要知道,汇编指令是机器指令的助记符,最终要通过编译器翻译成CPU能直接识别的由01组成的代码(机器码)。
LDR/STR架构:
ARM采用RISC架构,CPU不能直接操作内存中的内容,而需要先将内存中的内容加载到CPU中的通用寄存器中才能被CPU处理。
LDR(load register)指令将内存中的内容加载的通用寄存器中。
STR(store register)指令与LDR指令相反,将寄存器中的内容存入到内存中。
CPU通过LDR指令和STR指令实现内存与寄存器之间的数据交换。
ARM的八种寻址方式:
1、寄存器寻址 直接用寄存器名称操作数据,与内存地址无关。如:MOV r1,r2 相当于mysql 的set r1=r2,即把r2寄存器的内容赋值给r1寄存器。
2、立即寻址 数据与寄存器之间内容传送。如MOV r0,#0xFF00 ,把16进制的数据0xFF00赋值给r0寄存器,相当于mysql的set r1=0xFF00,加#表示0xFF00是一个数字,不是地址。
3、寄存器移位寻址 数据在寄存器之间赋值的过程中还带有移位运算。如MOV r0,r1 lsl#3,把r1寄存器里的内容左移三位后再赋值给r0寄存器,lsl是左移指令。
4、寄存器间接寻址 寄存器与内存之间的数据操作。如MOV r1,[r2],将r2寄存器里所存地址的里的内容赋值给r1寄存器,r2寄存器类似于与c语言里的指针,存放的是内存的地址。中括号[]相当于c语言指针的取值运算。
5、基址变址寻址 在通过寄存器访问内存地址的时候还带有地址的移位。如ldr r1,[r2,#4] ,将r2寄存器里存放的地址+4后再取其内容赋值只给r1寄存器,是基于上一种寻址方式演变而来。
6、多寄存器寻址 从内存往寄存器加载内容。如ldmia r1!,{r2-r7,r12},将起始地址为r1寄存器所存的地址的后n个地址的内容对应的赋值给{}里对应的寄存器,n的大小取决于{}里寄存器数量。
7、堆栈寻址 从堆栈往寄存器加载内容。如stmfd sp!,{r2-r7,lr},跟上一种寻址非常类似,只不过这种的起始地址不是普通的寄存器里存放的地址,而是堆栈指针sp里存放的地址。stmfd 进栈,sdmfd 出栈。
8、相对寻址 与基址变址方式相类似。相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。如BL haha,BL是跳转指令,haha是程序中的一个标记点,相当于javaScipt中锚点跳转的锚点。
指令后缀:同一指令加上不同的后缀,变成了不同的指令。常用的后缀有:
B后缀(byte) 功能不变,操作长度变成8位。ARM默认处理的32位。
H后缀(half word)功能不变,操作长度变为16位。
S后缀 (signed)功能不变,操作数变为有符号。
如ldr指令,加载指令。从内存的加载四个字节到寄存器。衍生出来的指令有 ldrb(加载一个字节)、ldrh(加载两个字节)、ldrsb(加载一个有符号字节),ldrsh(加载两个有符号字节)。
S后缀(S标志)功能不变,影响CPSR标志位,一般用在数据传输指令,如MOV,MOV r1,#0 ,将数字0赋值给r1寄存器,不会影响CPSR里的零标志位,如果写成MOVS r1,#0,将会影响。
条件执行后缀:
先介绍一下CPRS程序状态寄存器的条件位:
N (negative)运算结果负标志位。Z(zero)运算结果是零。C(carried out)运算中有进位。V(verflowed)运算中有溢出,当条件成立时为1。
如MOV r1,r0,写成条件执行指令为 MOVEQ r1,r0,表示如果上一条指令的执行结果使得CPSP(程序状态)寄存器的条件位Z(运算结果是零)的零标志位为1,则执行这条条件指令,否则不执行。
特点:条件后缀是否成立,取决于上一条语句或语句块所执行的结果。条件后缀只决定本句语句是否执行。