嵌入式硬件-ARM芯片的启动

目录

一.基本指令

1.mov指令

2.add指令

3.sub指令

4.ldr与str指令

5.bic与orr指令

6.CMP与b指令:

7.stmfd与ldmfd指令

8.常用条件码

二.程序状态寄存器cpsr

三.内存布局

四.栈的分类

五.汇编和C语言混合编程

六.切换处理器工作模式为USER模式

七.立即数


一.基本指令

1.mov指令

cpp 复制代码
//加载12位立即数到寄存器或转移一个寄存器的值到另外一个寄存器;
MOV{S}<c> <Rd>, #<const>
mov r0, #1 ;加载立即数1到寄存器r0
MOV{S}<c> <Rd>, <Rm>
mov r1, r0 ;将r0寄存器的值加载到r1

2.add指令

cpp 复制代码
ADD{S}<c> <Rd>, <Rn>, #<const>

ADD R0, R1, #1 ; R0 = R1 + 1,不更新标志
ADDS R0, R1, #0xFF ; R0 = R1 + 0xFF,更新N/Z/C/V

ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}    //shift 指的是"移位操作"

ADD R0, R1, R2 ; R0 = R1 + R2
ADD R0, R1, R2, LSL #2 ; R0 = R1 + (R2 << 2)

3.sub指令

cpp 复制代码
SUB{S}<c> <Rd>, <Rn>, #<const>

SUB R0, R1, #5 ; R0 = R1 − 5,不更新标志
SUBS R0, R1, #0x10 ; R0 = R1 − 0x10,更新N/Z/C/V

SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}

SUB R0, R1, R2 ; R0 = R1 − R2
SUB R0, R1, R2, LSL #1 ; R0 = R1 − (R2 << 1)

4.ldr与str指令

ldr:

cpp 复制代码
功能1:将非立即数加载到通用寄存器
LDR{<c>}{<q>} <Rt>, <label>

例:如ldr r0, =0x2FAB4

功能2:将RAM中的数据加载到通用寄存器
LDR<c> <Rt>, [<Rn>{, #+/-<imm12>}]

例:ldr r0,[r1,#4];将内存地址为R1+4的字数据读入寄存器R0

LDR<c> <Rt>, [<Rn>], #+/-<imm12>

例:ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r1+8

LDR<c> <Rt>, [<Rn>, #+/-<imm12>]!

例:LDR R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。

str:

cpp 复制代码
与ldr作用相反,将通用寄存器中的值写入到RAM中
str r1, [r0]         ;*r0 = r1
str r1, [r0, #4]     ;*(r0 + 1) = r1
str r1, [r0], #4     ;*r0++ = r1
str r1, [r0, #4]!     ;*++r0 = r1

ldr与str结合使用

cpp 复制代码
LDR R0, =0x40000000   ; R0 = 目标内存地址(伪指令)
LDR R1, [R0]          ; R1 = 从 R0 指向的地址读取一个字(32位)
ADD R1, R1, #1        ; R1 = R1 + 1
STR R1, [R0]          ; 把 R1 写回 R0 指向的地址

5.bic与orr指令

bic:

cpp 复制代码
将某个通用寄存器清零(操作数中为bit1的位清0),清0结果写回到通用寄存器。
BIC{S}<c> <Rd>, <Rn>, #<const>;
将rn中的字数据const为1的比特清零,把结果放入rd。

例:
MOV r0, 0x11
BIC r1, r0, #1   ; 把 r0 的第 0 位清零,结果为0x10,存到 r1,r0 不变

orr:

cpp 复制代码
将某个通用寄存器置1(操作数中为bit1的位置1),置1结果写回到通用寄存器

例:
ORR r1, r0, #(1 << 3) ; r1 = r0 | 0x08,r0 原值不变

bic与orr结合使用:

cpp 复制代码
BIC r0, r0, #(0x7 << 4)  ; 先把第4~6位清零(避免脏数据)
ORR r0, r0, #(0x3 << 4)  ; 再把新值 0b011 写入第4~6位

6.CMP与b指令:

cmp:

cpp 复制代码
比较两个寄存器的值或者比较一个寄存器和立即数的值,其原理是对待比较的两个数求差,看结果是否为0,这个指令会无条件修改N,V,C,Z位。

例:
mov r0, #100
cmp r0, #100
会导致Z置位,从条件码表可知,只要Z置位就是两数相等。

b:

cpp 复制代码
实现无条件跳转;
b指令条件分支
b指令循环
b函数调用
bl指令:函数跳转前,会将函数返回地址保存到lr寄存器;
bx指令:bx lr 等价于mov pc, lr

7.stmfd与ldmfd指令

stmfd:

cpp 复制代码
stmfd:入栈保护
STMFD<c> <Rn>(!}, <registers>

例:stmfd sp!, <r0,r1,lr>    //通过入栈保存r0,r1,lr寄存器的值

ldmfd:

cpp 复制代码
ldmfd:出栈恢复
LDMFD<c> <Rn>{!), <registers>

例:ldmfd sp!, <r0, r1, lr>

8.常用条件码

对{S}与<c>解释如下

{S} ------ 可选后缀,决定是否更新状态标志

  • 有 S :指令执行后,会更新 CPSR(当前程序状态寄存器)中的条件标志位(N、Z、C、V)。

  • 没有 S:不更新任何标志位,只完成数据传送。

<c> ------ 条件码(Condition Code),决定指令在什么条件下执行

  • ARM 指令可以条件执行:只有当前 CPSR 中的标志位满足指定条件时,指令才会真正执行,否则被当作 NOP(空操作)。

  • <c> 是条件码的占位符,可以是 EQ、NE、CS、CC、MI、PL、VS、VC、HI、LS、GE、LT、GT、LE、AL 等。

  • 如果省略 <c> ,默认是 AL(Always,无条件执行)。

其中常用条件码如下:

二.程序状态寄存器cpsr

三.内存布局

四.栈的分类

满栈/空栈(是一种结构,不是传统字面意思的满空):根据栈顶所在位置是否存有元素确定。

栈顶所在位置一直存有元素称为满栈,先移动栈顶再存入数据;

栈顶所在位置一直没有元素称为空栈,先存入数据再移动栈顶。

增栈/减栈:根据栈的生长方向确定。

入栈数据时,栈顶向内存高地址移动,称为增栈;

入栈数据时,栈顶向内存低地址移动,称为减栈,

注意:ARM中的栈结构为:满减栈。

五.汇编和C语言混合编程

1.汇编调用C函数

汇编和C语言混合编程(汇编调用C函数C调用汇编函数)

汇编如何向c语言传参:

C语言将函数运行结果返回给R0寄存器

当参数小于等于4个时,通过通用寄存器进行传参(R0-R3)

当参数超过4个时,必须通过栈进行传参(入栈保护出栈恢复)

2.C调用汇编函数

C语言向汇编函数传参,参数会被保存到通用寄存器汇编函数的结果,通过R0寄存器返回给C语言

六.切换处理器工作模式为USER模式

1.将cpsr寄存器中的值读到R0寄存器

2.将R0寄存器中的值修改为10000

3.将R0寄存器中的值写回到cpsr寄存器

mrs指令:读取某个特殊寄存器(cpsr)的值到通用寄存器

msr指令:将通用寄存器中的值写入到特殊寄存器(cpsr)

例:

MRS , <spec_reg>

mrs r0, cpsr

MSR<spec_reg>,

msr cpsr, r0

七.立即数

立即数的判断:

  1. 如果某个数的数值范围是 0~0xFF 之间,那么这个数一定是立即数;
  2. 把某个数展开成 2 进制,这个数的最高位 1 至最低位 1 之间的二进制数序列的位
    数不能超过 8 位;
  3. 这个数的二进制序列凑够 8 位之后的的右边必须为偶数个连续的 0**(2条不够8位时右对齐,在末尾补0)**

例:

0x234 = 0000 0000 0000 0000 0000 0010 0011 0100

最高位1至最低位1之间的二进制数序列:1000 1101没有超过8位

末尾1的右边有2个0,所以0x234是立即数

0x3f4 = 0000 0000 0000 0000 0000 0011 1111 0100

最高位1至最低位1之间的二进制数序列:1111 1101 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有2个0,所以0x3f4是立即数

0x132 = 0000 0000 0000 0000 0000 0001 0011 0010

最高位1至最低位1之间的二进制数序列:1001 1001 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有1个0,不满足第二条,所以0x132不是立即数

0x7f8 = 0000 0000 0000 0000 0000 0111 1111 1000

最高位1至最低位1之间的二进制数序列:1111 1111从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有3个0,不满足第二条,所以0x7f8不是立即数

0xfab4 = 0000 0000 0000 0000 1111 1010 1011 0100

最高位1至最低位1之间的二进制数序列:0011 1110 1010 1101 从第一个1开始到最后一个1之间超过8位,不满足条件1,所以这个数不是立即数

ARM 指令机器码只有12bit 用来存立即数,放不下完整 32 位数字,拆成两部分:

高 4 位:rotate(旋转位)

低 8 位:imm8(8 位基础立即数)

4位旋转位若直接表示位移0-15位,则立即数最大只能位移15位,无法覆盖32位寄存器的所有角落,故×2,最终 32 位立即数 = imm8 循环右移 2×rotate 位(移位步数永远是偶数:0、2、4 ... 30 位,硬件无法实现移位奇数位,易知,能表示的最大立即数为0xFF00 0000,即0xFF循环右移8位,rotate=4,12位则为0x4FF)

相关推荐
芯岭技术郦1 小时前
32 位 ARM® Cortex®-M0+ 内核MCU普冉MS32C001-C
单片机·嵌入式硬件
骑着毛驴数星星2 小时前
STM32 CAN波特率与采样点计算,基于HAL库
stm32·单片机·嵌入式硬件
dozenyaoyida2 小时前
Zephyr静态注册机制详解:SYS_INIT和BT_CONN_CB_DEFINE为什么没人调用也执行
嵌入式·nordic·链接器·zephyr·蓝牙开发
zhangrelay3 小时前
Arduino-MEGA-ESP单片机理论课笔记02-硬件-2026
笔记·单片机·嵌入式硬件
艾芯微科技3 小时前
钰泰 ETA5055V330DD1E|SOT-223 3.3V LDO,低压差、大电流线性稳压选型分享
网络·单片机·嵌入式硬件·集成测试·51单片机
威嵌神州4 小时前
恩智浦 T1022 性能怎么样?QorIQ 架构中端工业嵌入式优势解析
嵌入式硬件
weixin_690654744 小时前
龙迅#LT9611EX 现MIPI转HDMI1.4功能主推型号,分辨率高达4K30HZ,IC内置I2C无需外部12C控制。
嵌入式硬件·音视频·信号处理
qq_401700415 小时前
STM32 GPIO 精讲|推挽 / 开漏 / 上拉浮空,工程选型避坑
stm32·单片机·嵌入式硬件
创界工坊工作室5 小时前
19-基于单片机的宠物喂养控制系统设计
stm32·单片机·嵌入式硬件·proteus·宠物
深圳市恒锐丰科技杨生6 小时前
EG3116D 600V 单路半桥栅极驱动芯片|屹晶 EGmicro
嵌入式硬件·硬件工程