目录
5.1ARM指令集导学
汇编
> 每条汇编都会唯一对应一条机器码,且CPU能直接识别和执行,即汇编中所有的指令都是CPU能够识别和执行的。
> 汇编中寄存器的使用、栈的分配与使用、程序的调用、参数的传递等都需要自己维护
C语言
> 每条C语句都要被编译器编译成若干条汇编指令才能被CPU识别和执行,即C语句中的指令CPU不一定能直接识别,需要编译器进行“翻译”
> C中寄存器的使用、栈的分配与使用、程序的调用、参数的传递等,都是编译器来分配和维护
学习汇编目的
底层开发可能会读/写汇编代码
理解CPU是怎样执行程序的
理解C的本质,用汇编的思想写出高效的C代码
5.2keil仿真环境搭建
硬件仿真
通过硬件接口将CPU和内存中实际的信息读出来
软件仿真
通过软件模拟CPU内部运行程序的状态
Keil MDK是用于基于ARM Cortex-M 微控制器的完整软件开发环境。它集成了uVision IDE C/C++编译器、调试器以及其他中间组件,支持众多芯片供应商,易于学习和使用。
环境搭建
1.安装Keil集成开发环境 2.安装gcc交叉编译工具链 3.创建汇编工程,熟悉仿真环境的使用
5.3ARM指令集概述
.c回顾
1.语句
a++;
2.注释
//
3.预编译指令
#if 1
...
#else
...
#endif
@汇编中的符号
@1.指令:能够编译成一条32bit机器码,并且能被CPU识别和执行
@2.伪指令:本身不是指令,编译器可以将其替换成若干条指令
@3.伪操作:不会生成指令,只是在编译阶段告诉编译器怎么编译
@ARM指令集
@1.数据处理指令:进行数学运算、逻辑运算
@2.跳转指令:实现程序的跳转,本质是修改了PC寄存器
@3.Load/Srore指令:访问(读写)内存
@4.状态寄存器传送指令:用于访问(读写)CPSR寄存器
@5.软中端指令:给CPU发送中断信号,触发软中断
@6.协处理器指令:操控协处理器的指令
D6数据处理指令
.text @表示当前为代码段
@.global_start @将start定义成全局符号
_start: @汇编的入口
@1.指令:能够编译成一条32bit机器码,并且能被CPU识别和执行
@1.1数据处理指令: 进行数学运算、逻辑运算
@数据搬移指令
MOV R1,#1 @汇编指令---往R1寄存器放入1
MOV pc,#0 @改变pc值,CPU从0位置取指令
MOV R2,R1 @R2=R1
MVN R0,#0xFF@R0=~0xFF,按位取反搬入
MOV R0,#0
MVN R0,#0
@立即数---本质是包含在指令当中的数,属于指令的一部?
@立即数优点---速度快,取指时可以将其读到CPU,不用单独去内存读取
@立即数缺点---不能是任意的32位数字,有局限性,要遵照指令要求
MOV R0,#0x12345678@数太大,超过32位
MOV R0,#0x12
@伪指令
@MOV R0,#0xFFFFFFFF
@数据运算指令的格式
@操作码/目标寄存器/第一操作寄存器/第二操作数
@操作码:表示执行那种操作
@目标寄存器:用于存储运算的结果
@第一操作寄存器:存储第一个参与运算的数据(只能写寄存器)
@第二操作数:第二个参与运算的数(可以寄存器也可以立即数)
@加法指令
MOV R2,#5
MOV R2,#3
ADD R1,R2,R3 @R1=R2+R3
ADD R1,R2,#5 @R1=R2+5
ADD R1,#5,R3 @非法
@减法指令
SUB R1,R2,R3 @R1=R2-R3
SUB R1,R2,#3 @R1=R2-3
@逆向减法指令
RSB R1,R2,#3 @R1=3-R2
@乘法指令(只能是两个寄存器相乘)
MUL R1,R2,R3 @R1=R2*R3
@按位与指令
AND R1,R2,R3 @R1=R2&R3
@按位或指令
ORR R1,R2,R3 @R1=R2|R3
@按位异或指令
EOR R1,R2,R3 @R1=R2^R3
@左移指令
LSL R1,R2,R3 @R1=(R2<<R3)
@右移指令
LSR R1,R2,R3 @R1=(R2>>R3)
@位清零指令
BIC R1,R2,0xF @第二操作数中的哪一位为1,就将第一操作寄存器中的哪一位清零,将结果放入目标寄存器
@数据运算指令的格式扩展
MOV R1,R2,LSL #1 @R1=(R2<<1)
@数据运算指令对条件位(N/Z/C/V)的影响---CPSR
@默认情况下数据运算不会对条件为产生影响,当在指令后加后缀"s"后可以影响
MOV R1,#0xFFFFFFFF
ADDS R2,R1,#3
@带进位的加法指令
@两个64位的数据做加法运算
@第一个数的低32位放在R1
@第一个数的高32位放在R2
@第二个数的低32位放在R3
@第二个数的高32位放在R4
@运算结果低32位放在R5
@运算结果高32位放在R6
@第一个数
@0x00000001 00000001
@第二个数
@0x00000002 00000002
MOV R1,#0x00000001
MOV R2,#0x00000001
MOV R3,#0x00000002
MOV R4,#0x00000002
ADD R5,R1,R3 @需进位会报错
ADC R6,R2,R4 @带进位的加法,考虑了APRS的C位,R6=R2+R4+'C'
@带借位的减法指令
SBC R6,R2,R4 @本质R6=R2-R4-'C'
stop: @死循环,防止程序跑飞
B stop
.end @汇编的结束
一条C语言对应一条甚至好几条汇编语言,使用的C语言越简单,对应的汇编语言越少,CPU 运算速度越快,
作业D5
1.简述C语言和汇编语言的本质区别是什么
答:
每条汇编都会唯一对应一条机器码,且CPU能直接识别和执行,即汇编中所有的指令都是CPU能够识别和执行的。汇编中寄存器的使用、栈的分配与使用、程序的调用、参数的传递等都需要自己维护。
C语言是高级语言,每条C语句都要被编译器编译成若干条汇编指令才能被CPU识别和执行,即C语句中的指令CPU不一定能直接识别,需要编译器进行“翻译” ,C中寄存器的使用、栈的分配与使用、程序的调用、参数的传递等,都是编译器来分配和维护。
作业D6
1.编程实现使用32bit的ARM处理器实现两个128位的数据的加法运算。
注:
第一个数的bit[31:0]、bit[63:32]、bit[95:64]、bit[127:96]分别存储在R1、R2、R3、R4寄存器
第二个数的bit[31:0]、bit[63:32]、bit[95:64]、bit[127:96]分别存储在R5、R6、R7、R8寄存器
运算结果的bit[31:0]、bit[63:32]、bit[95:64]、bit[127:96]分别存储在R9、R10、R11、R12寄存器
答:
.text @ 表示当前为代码段
.global _start @ 将_start定义为全局符号
_start: @ 汇编的入口
@ 带进位的加法运算(两个128位数据)
@ 第一个数 0xFFFFFFFF 00000001 00000001 00000001
@ 第二个数 0x00000002 00000002 00000002 00000002
MOV R1, #0xFFFFFFFF
MOV R2, #0x00000001
MOV R3, #0x00000001
MOV R4, #0x00000001
MOV R5, #0x00000002
MOV R6, #0x00000002
MOV R7, #0x00000002
MOV R8, #0x00000002
ADDS R9, R1, R5
ADCS R10, R2, R6
ADCS R11, R3, R7
ADC R12, R4, R8 @带进位的加法,考虑了APRS的C位,R12=R4+R8+'C',
@ADD不关心之前是否有进位,也不关心加了后是否有进位
@ADDS不关心之前是否有进位,但关心加了后是否有进位
@ADC只关心之前是否有进位,不关心加了后是否有进位
@ADCS关心之前是否有进位,关心加了后是否有进位
stop: @死循环,防止程序跑飞
B stop
.end @ 汇编的结束