ARM—汇编指令集

一、汇编指令与伪指令
1、伪指令:如.test_start等,本质不是指令,用于指导编译过程,最终不产生机器码。
2、指令:ldr,str等,机器码的助记符,最终生成机器码CPU执行。

二、两种不同风格的ARM
1、官方:LDR R0, [R1] Windows IDE开发环境
2、GNU:ldr r0, [r1] Linux及相关开发环境
主要区别在大小写以及伪指令方面

三、ARM汇编特点
1:ldr/str架构
1)ARM采用RISC架构,CPU通过寄存器处理内存的数据
2)具体的方式就是LDR(内存——>寄存器)和STR(寄存器——>内存)

2、8种寻址方式
寄存器寻址 mov r1, r2 //r1 = r2
立即寻址 mov r0, #0xFF00 //r0 = 0xFF00, #代表数字,因内存中全为0/1数字,
所以在表示真实数字前加#符号。
寄存器移位寻址 mov r0, r1, lsl #3 //r0 = r1 *2^3
寄存器间接寻址 ldr r1, [r2]
基址变址寻址 ldr r1, [r2, #4] //[r2+4]r1
多寄存器寻址 ldmia r1!, {r2-r7, r12} //[r1++] r2-r7, r12
堆栈寻址 stmfd sp!, {r2-r7, lr} //sp++  r2-r7, lr
相对寻址 beq flag //:汇编中代表标号,通过b flag可以跳转:的地方
flag:

3、指令后缀
同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:
B(byte)功能不变,操作长度变为8位
H(half word)功能不变,长度变为16位
S(signed)功能不变,操作数变为有符号,如: ldr ldrb ldrh ldrsb ldrsh
S(S标志)功能不变,影响CPSR寄存器的标志位,如: mov和movs ,movs r0, #0
ARM—汇编指令集_第1张图片
4、条件执行后缀
ARM—汇编指令集_第2张图片
条件执行后缀的指令执行与否,取决于前面的指令结果否满足条件,满足的标志就是CPSR的标志位。

5、多级指令流水线
ARM—汇编指令集_第3张图片
级数越多,CPU速度越快,但最怕跳转,因为跳转意味着当前取址和解码的指令都要重新选取,ARM的解决方案就是通过条件执行后缀来预判是否需要跳转。

四、常用的汇编指令
1、数据处理指令
1)数据传输指令
mov:mov r0, r1 //两个寄存器之间数据传递:r0 = r1
mvn:mov r0, r1// mvn是按位取反后传递:r1 = 0xff,r0 = 0xffffff00
2)算术指令 add sub rsb adc sbc rsc
Sub r0, r1, r2 //r0 = r1 – r2
乘法指令 mvl mla umull umlal smull smlal
算数指令和乘法指令都不重要,基本用不到
3)逻辑指令 and orr eor bic //与 或 异或 位清零
Eor:相同为0,不同为1
Bic r0,r1,#0x1f //将r1的bit[0] – bit[4]位清零后付给r0
4)比较指令 cmp cmn tst teq
cmp r0, r1 等价于 sub r2, r0, r1 (r2 = r0 - r1)
cmn r0, r1 等价于 add r0, r1
tst r0, #0xf @测试r0的bit0~bit3是否全为0
比较指令用来比较2个寄存器中的数,比较指令不用后加s后缀就可以影响cpsr中的 标志位,就是通过标志位来判断
5)前导零计数 clz//判断有多少个0,没有用

2、c/spsr访问指令
mrs & msr
mrs用来读c/spsr,msr用来写c/spsr
C/SPSR寄存器比较特殊,需要专门的指令访问,这就是mrs和msr。

3、常用ARM指令3:跳转(分支)指令
b: b 直接跳转(就没打开算返回)
bl branch and link,跳转前把返回地址放入lr中,以便返回,以便用于函数调用
bx跳转同时切换到ARM模式,一般用于异常处理的跳转。没有用。

4、常用ARM指令4:访存指令
ldr/str:通过加后缀可以访问单个字/半字/字节
ldm/stm:多字批量访问
swp r1, r1, [r0]:[r0]–>r1,r1–>[r0]

5、立即数
ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。
因此有合法立即数与非法立即数之分。
合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数。
如:0x000000ff 0x00ff0000 0xf000000f
非法立即数: 0x000001ff

五、伪指令的介绍
1、伪指令的意义:
伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会生成机器码。伪指令的意义在于指导编译过程,伪指令和具体的编译器相关的,嵌入式学习的是gnu 环境下的汇编伪指令。所有伪指令前面都有.号

2、gnu汇编中的常用名词
1)常用符号
@ 用来做注释,和C语言中//类似;
:以冒号结尾的是标号,可以通过b指令跳转;
. 点号表示当前指令的地址,如右图:表示死循环,也可用b .表示;
数字前面加#或$,表示这是个立即数。
标号及循环的用法
2)常用gnu伪指令
.global _start @ 给_start外部链接属性,当外部需要调用时,就需要此操作
.section .text @ 指定当前段为代码段,暂不用学
.ascii .byte .short .long .word .quad .float .string @ 定义数据,同C语言一样
.align 4 @ 以16字节对齐,4是指2^4个字节对齐
.balignl 16 0xabcdefgh @ 16字节对齐填充 没看懂,待定
3)最重要的伪指令
ldr 大范围的地址加载指令
adr 小范围的地址加载指令
adrl 中等范围的地址加载指令
nop 空操作
ARM中有一个ldr指令,还有一个ldr伪指令,一般都使用ldr伪指令而不用ldr指令
ldr指令: ldr r0, #0xff
伪指令: ldr r0, =0xfffl @涉及到合法/非法立即数
4)区别ldr与adr
1>>adr编译时会被1条sub或add指令替代,而ldr编译时会被一条mov指令替代或者 文字池方式处理;
2>>adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,在运行时确定可 以用来检测程序当前的运行地址在哪里
3>>ldr加载的地址和链接时给定的地址有关,在链接时确定,由链接脚本决定。
所以我们可以通过adr和ldr加载的地址比较来判断当前程序是否在链接时指定的地址运行。

你可能感兴趣的:(单片机开发,stm32,arm开发)