嵌入式 - ARM2

发布于:2025-09-09 ⋅ 阅读:(24) ⋅ 点赞:(0)

一、ARM汇编

        学习arm汇编的主要目的是为了编写arm启动代码,引导程序到c语言环境下运行。
        启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。

启动代码的主要任务:
1、初始化异常向量表;
2、初始化各工作模式的栈指针寄存器;
3、开启arm内核中断允许;
4、将工作模式设置为user模式;
5、引导程序进入c语言主函数执行;

二、格式

伪操作
        不是 ARM 处理器实际的指令(如 MOV, ADD 等),而是汇编器的命令,用于指导汇编器如何工作

area reset, code, readonly
code32
entry

end

area:用于定义一个段。程序、数据、堆栈等都需要被组织在不同的段中。
reset: 段的名字。名字 reset 具有很强的暗示性,通常用于表示复位向量段,即CPU上电或复位后首先执行的第一段代码所在的位置。
code: 指定该段的属性为代码,意味着这个段包含可执行的指令。
readonly: 指定该段的属性为只读。对于代码段来说,通常是默认且必须的。

code32: 表示后续指令使用 32位的 ARM 指令集。
thumb: 表示后续指令使用 16位的 Thumb 指令集。

三、指令

手册目录:指令(目的操作数,第一操作数,第二操作数)

immediate:立即数

register:寄存器

SP plus:栈指针

立即数:12位立即数imm12的条件是:
        把某个数展开成2进制,该数必须存在一种循环右移(偶数位),使得移位后高24位全0,低8位即为有效imm8;
eg:0xA0 00 00 00 0A是立即数
        0xFFFF FFFF     不是立即数

1. mov

手册484

基本格式:
        MOV{S}<c> <Rd>, #<const>
        MOV{S}<c> <Rd>, <Rm>

MOV与位移指令的结合:

注意:
        (1)与C语言中的赋值运算对比(左值/右值),利于加深理解
        (2)#<n>/<Rs> 取值范围 (0 - 31)
        (3)RRX{S}:扩展右移 (不需要移位量)
        (4)在计算机中只识别二进制数据,计算机没有有无符号,浮动点等概念

2. add

手册306

立即数作为第二操作数: ADD{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: ADD{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>

注意
       (1){, <shift>} 其中{}代表可选择,“,”表示在使用时需要在Rm后添加“,” shift 移位量(立即数)
        (2) add r0, #3, #2 :没有这种形式,C语言int a = 1 + 2; 编译阶段计算, 不需要在机器指令中体现

3. sub

手册708

立即数作为第二操作数: SUB{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: SUB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>

4. ldr(加载指令)

手册406

LDR<c> <Rt>, <label>

5. sdr(存放指令)

6. mvn

手册504

MVN{S}<c> <Rd>, #<const>
MVN{S}<c> <Rd>, <Rm>{, <shift>}
MVN{S}<c> <Rd>, <Rm>, <type> <Rs>

7. bic

手册340

BIC{S}<c> <Rd>, <Rn>, #<const>
BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
BIC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>

8. orr

手册516

ORR{S}<c> <Rd>, <Rn>, #<const>
ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ORR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>

9. 标志位

CPSR寄存器中条件判断标志位
N: 符号标志位:
        
上条指令执行结果最高位bit31为1,则 N = 1, 当结果作为有符号解释时为负值;
Z: 零值标志位:
        
上条指令执行结果为0(即bit0 - bit31 均为0),则 Z = 1;
C: 进位标志位:
        
进行无符号解读,如果在加法过程中进位或者减法时没有借位,则为 C = 1,否则 C = 0
V: 溢出标志位:
        
进行有符号解读,是否发生溢出 -2^31 - 2^31-1(两个正数加得负数,两个负数加得正数)


条件码:  eq(相等)                ne(不相等)
                ge(大于等于)         gt(大于)         le(小于等于)         lt(小于)
                al(无条件执行)
 

10. cmp

手册370

CMP<c> <Rn>, #<const>
CMP<c> <Rn>, <Rm>{, <shift>}
CMP<c> <Rn>, <Rm>, <type> <Rs>

比较并获取三个数中的最大值

11. b bl bx

手册334

B<c> <label>
b fun <==> ldr pc, =fun
直接跳转到目标地址,不保存返回地址

BL<c> <label>
bl fun
跳转前将返回地址存入LR寄存器

BX<c> <Rm>
bx lr <==> mov pc, lr
跳转到寄存器指定的地址,并可切换指令集,不保存返回地址

12. while / do while

循环三要素
        循环结束条件
        推动循环趋向终结的语句
        循环的循环体

while实现0 -100 求和

do while 实现0 -100 求和

13. function

四、ARM栈

​FD (满减栈)​
        栈指针(SP)指向最后压入的元素,即栈顶元素
        操作方式:PUSH:SP先减少再存数据
                          POP:   先取数据再增加SP

FA(满增栈)
        栈指针(SP)指向最后压入的元素,即栈顶元素
        操作方式:PUSH:SP先增加再存数据
                          POP:   先取数据再减少SP

​EA (空增栈)​
        栈指针(SP)指向下一个空闲位置
        操作方式:PUSH:现存数据再增加SP
                          POP:  SP先减少再取数据

​ED (空减栈)​
        栈指针(SP)指向下一个空闲位置
        操作方式:PUSH:现存数据再减少SP
                          POP:  SP先增加再取数据


网站公告

今日签到

点亮在社区的每一天
去签到