目录
一、ARM汇编
1、ARM汇编概述
2、统一的汇编语言:UAL
3、汇编指令格式
4、立即数
5、ARM编译器与GCC编译器语法差异
二、ARM汇编模拟器
1、VisUAL的基本使用
(1)汇编指令集的分类:(常用的,记住这些就够了)
通过上一篇文章的示例,可以知道① ②
(2)指令集的分类
① 怎么修改CPU使用的指令集?
一个芯片既可以用ARM指令集,也可以用Thumb指令集,根据CPU内部的程序状态寄存器里的某一位,来表示运行的指令是ARM还是Thumb指令集,如下图:
ARM公司发布两类指令集:
要节省空间时用Thumb指令,要效率时用ARM指令。
1) ARM指令集,这是32位的,每条指令占据32位,高效,但是太占空间
2) Thumb指令集,这是16位的,每条指令占据16位,节省空间
② Thumb-2指令
当我们同时使用ARM指令集和Thumb指令集时,该怎么办呢?
1)对于以前的ARM7、ARM9和现在的Cortex A7芯片,都是支持这两种指令集。
2)对于现在的Corte-M系列,比如M3和M4,引入了另一种指令集Thumb-2,同时支持16位、32位指令集,可以混合在一起编程。CPU自动识别。
ARM公司推出了: Unified Assembly Language,UAL,统一汇编语言,你不需要去区分这些指令集。
在程序前面用CODE32/CODE16/THUMB,表示指令集:ARM/Thumb/Thumb2
日常工作中,只需要这么几条汇编指令,从名字就可以猜出含义:
MOV LDR/STR LDM/STM AND/OR ADD/SUB B/BL DCD ADR/LDR CMP
如果想要深入学习,可以学习《ARM Cortex-M3与Cortex-M4权威指南.pdf》。
参考《DEN0013D_cortex_a_series_PG.pdf》P70、《ARM Cortex-M3与Cortex-M4权威指南.pdf》第5章
① 汇编指令可以分为几大类:数据处理、内存访问、跳转、饱和运算、其他指令
② 以“数据处理”指令为例,UAL汇编格式为:
Operation表示各类汇编指令,比如ADD、MOV;如下图:
cond有多种取值
(1)立即数
这样一条指令: MOV R0, #VAL ;意图是把VAL这个值存入R0寄存器。
问:VAL可以是任意值吗?
答:不可以,必须是立即数。
问:为什么?
答:假设VAL可以是任意数,”MOV R0, #VAL”本身是16位或32位,哪来的空间保存任意数值的VAL?
所以,VAL必须符合某些规定。
(2)LDR伪指令
去判断一个VAL是否立即数,麻烦!并且我就是想把任意数值赋给R0,怎么办?
可以使用伪指令:
LDR R0, =VAL
LDR R0, =0x12
0x12是立即数,那么替换为:
MOV R0, #0x12
============================================
LDR R0, =0x12345678
0x12345678不是立即数,那么替换为:
LDR R0, [PC, #offset] // 2. 使用Load Register读内存指令读出值,offset是链接程序时确定的
……
Label DCD 0x12345678 // 1. 编译器在程序某个地方保存有这个值
(3)ADR伪指令
ADR的意思是:address,用来读某个标号的地址
示例:
ADR R0, Loop
Loop
ADD R0, R0, #1
它是“伪指令”,会被转换成某条真实的指令,比如:
ADD R0, PC, #val ; val在链接时确定
Loop
ADD R0, R0, #1
GCC编译器使用的是GNU Assembler ,ARM编译器是armasm。
VisUAL是一款ARM汇编模拟器,下载地址:https://salmanarif.bitbucket.io/visual/downloads.html
VisUAL模拟的ARM板子如下图所示,它没有模拟外设,仅仅模拟了CPU、ROM、RAM。
① 直接写汇编代码
代码含义:将R1的值放到R0的数值所指的地址的值。
② 运行:全速运行、单步执行
然后出现错误
③ 修改错误
报错显示:这个值必须是寄存器、寄存器移位、立即数,加上#代表是个立即数。
点击“Reset”后修改为:
④ 单步运行:点击Step Forwards
再点击Step Forwards,报错,0x1234不是立即数,采用伪指令LDR
改为LDR R1, =0x1234。单步运行,结果如下图:
⑤ 内存观察器
1)打开内存观察器
2)查看0x20000这个地址的值
3)点击单步运行
复杂案例:
两个数值的比较结果或存在状态寄存器