常见汇编指令
存储器访问指令
ARM不能直接访问存储器,比如RAM中的数据,一般借助存储器访问指令,通过内核寄存器Rx(x=0~12)完成存储器的读写。常用的存储器访问指令有两种:LDR和STR,用法如下表所示:
| 指令 | 描述 |
| LDR Rd,[Rn, #offset] | 从存储器Rn+offset的位置读取数据放到Rd中 |
| STR Rd,[Rn, #offset] | 将Rd中的数据写入到存储器中的Rn+offset位置 |
1、LDR指令
LDR主要用于从存储加载数据到寄存器 Rx中, LDR也可以将一个立即数加载到寄存器 Rx中, LDR加载立即数的时候要使用“ “=”,而不是 “#”。在嵌入式开发中 LDR最常用的就是读取 CPU的寄存器值,示例代码如下:
LDR R0, =0x0209C004
LDR R1, [R0, #0x00]
2、STR指令
LDR是从存储器读取数据, STR就是将数据写入到存储器中,示例代码如下:
STR R2, [R0, 0x00]
LDR和 STR都是按照字进行读取和写入的,也就是操作的 32位数据,如果要按照字节、
半字进行操作的话可以在指令“ LDR”后面加上 B或 H,比如按字节操作的指令就是 LDRB和
STRB,按半字操作的指令就是 LDRH和 STRH。
压栈和出栈指令
我们通常会在A函数中调用B函数,当B函数执行完以后再回到A函数继续执行。要想再跳回A函数以后代码能够接着正常运行,那就必须在跳到B函数之前将当前处理器状态保存起来 (就是保存 R0~R15这些寄存器值 ),当B函数执行完成以后再用前面保存的寄存器值恢复R0~R15即可。保存 R0~R15寄存器的操作就叫做现场保护,恢复 R0~R15寄存器的操作就叫做恢复现场。在进行现场保护的时候需要进行压栈 (入栈 )操作,恢复现场就要进行出栈操作。压栈的指令为 PUSH,出栈的指令为 POP。PUSH和 POP是一种多存储和多加载指令,即可以一次操作多个寄存器数据,他们利用当前的栈指针SP来生成地址, PUSH和 POP的用法如下表所示:
| 指令 | 描述 |
| PUSH <reg list> | 将寄存器列表存入栈中 |
| POP <reg list> | 从栈中恢复寄存器列表 |
注意:PUSH {R0, R1}和PUSH{R1, R0}效果是一样的,因为按照ARM规范是按照寄存器序列号顺序开始入栈,且从小序列号开始入栈。
算数运算指令
在嵌入式开发中最常会用的就是加减指令,乘除基本用不到。
加法指令如下表所示:
| 指令 | 计算公式 | 备注 |
| ADD Rd, Rn, Rm | Rd = Rn + Rm | 加法指令 |
| ADD Rd, Rn, #immed | Rd = Rn + #immed | |
| ADC Rd, Rn, Rm | Rd = Rn + Rm + 进位 | 带进位的加法指令 |
| ADC Rd, Rn, #immed | Rd = Rn + #immed + 进位 |
示例代码
在单片机中,代码存储在Flash中,数据存储在RAM中。下列代码对应的反汇编如下图所示,指令从Flash中取出,然后对RAM中的数据执行对应的操作。函数传递参数时,第一个参数传递给R0,第二个传递给R1。
void add_val(int *pa, int *pb)
{
volatile int temp;
temp = *pa;
temp += *pb;
*pa = temp;
}

栈的作用
什么是现场?即发生中断或者函数切换时,内核寄存器的值。现场保护即将内核寄存器的值存入栈中,现场恢复即从栈中恢复内核寄存器的值。
栈的作用主要如下:
- 任务切换、函数调用或者中断发生时,现场的保护与恢复;
- 局部变量的存储,下图为局部变量的实例。

本文详细介绍了ARM汇编中的存储器访问指令LDR和STR,以及压栈(PUSH)和出栈(POP)操作。文章还探讨了栈在任务切换、函数调用和中断处理中的作用,以及算数运算指令如加法的使用示例。


被折叠的 条评论
为什么被折叠?



