首页
视频
资源
登录
原
ARM 常用的指令
493
人阅读
2024/6/19 9:44
总访问:
2971521
评论:
0
收藏:
0
手机
分类:
嵌入式
![](https://img.tnblog.net/arcimg/hb/6930d1439f4b43e785a433685b813262.png) >#ARM 常用的指令 [TOC] 搬移指令 ------------ tn2>`mov`、`msr`和`mrs`指令就不讲了,上一篇写得有。 ### and指令 tn2>将第二个参数和第三个参数进行与运算。 我们先给寄存器`r0`赋值5,在对其中进行后五位清空举例: ```bash .text b main nop nop nop nop nop nop nop main: mov r0,#5 and r0,r0,#0xFFFFFFE0 ``` ![](https://img.tnblog.net/arcimg/hb/f5bdf1f97bb341b9b8b8848a805355c3.png) ![](https://img.tnblog.net/arcimg/hb/b647130acb1c4906aeedc14136b9556b.png) tn2>为什么可以清空? 首先我们要了解与运算。 ```bash 1 AND 1 = 1 1 AND 0 = 0 0 AND 1 = 0 0 AND 0 = 0 ``` tn2>由于`0xFFFFFFE0 = 1111 1111 1111 1111 1111 1111 1110 0000`,而5为`101`所以根据与运算会被清0; ### orr指令 tn2>进行后两位数的或运算。 ```bash 1 OR 1 = 1 1 OR 0 = 1 0 OR 1 = 1 0 OR 0 = 0 ``` tn2>我们将16进制2和7进行或运算。 ```bash .text b main nop nop nop nop nop nop nop main: mov r0,#7 @111 orr r0,r0,#2 @10 ``` ![](https://img.tnblog.net/arcimg/hb/fa6a1847a77d4db69d49082eec043a8d.png) tn2>结果仍然是`111`也就是7. ### mov LSL与LSR tn2>LSL表示向左加0,LSR表示向右加0。 ```bash mov r0,#7 @111 orr r1,r0,LSL#1 @1110 orr r1,r1,LSL#2 @111000 ``` ![](https://img.tnblog.net/arcimg/hb/f6ddffe62ed54e14802ca90d67612933.png) ```bash mov r0,#7 @111 orr r1,r0,LSR#2 @1 ``` ![](https://img.tnblog.net/arcimg/hb/f6bf16e51ec6403299067ae9b91e75a1.png) 判断指令 ------------ ### cmp tn2>判断两个数是否相等。 举例:判断r0等于0时,r1=5,r0大于0时r1再加3给自己。 ```bash .text b main nop nop nop nop nop nop nop main: @ if(r0=0) { r1 = 5 } mov r0,#5 cmp r0,#0 moveq R1,#5 @ if r0 > #0 {r1 += 3} addgt r1,r1,#3 ``` ![](https://img.tnblog.net/arcimg/hb/ef1364f828004c02aa9065f4dc2e5c05.png) tn2>我们调试到这里的是偶发现CPSR的C位变了,这是CPU中AUL计算出的结果。 如果第一个操作数大于第二个操作数,C 位会被设置为 1。 如果第一个操作数小于第二个操作数,C 位会被设置为 0。 如果两个操作数相等,C 位也会被设置为 0。<br/> `moveq`表示如果根据上面的判断相等`r1`会进行赋值`5`。 然而条件不成立,所以没有进行赋值。 ![](https://img.tnblog.net/arcimg/hb/40f8683a4ff04016b23942bddf41b691.png) `addgt`表示如果第一个值比第二个值大就进行相加的操作。 ![](https://img.tnblog.net/arcimg/hb/ece81e24453d4022a84a4dac27bbf9e3.png) tn>指令会被解析成机器码,存储在flush里面。 ARM指令机器码 ------------ ![](https://img.tnblog.net/arcimg/hb/5b31d126443c42d7800e10cbdde22658.png) tn2>机器码是以二进制表示的指令,而汇编指令则是其对应的可读性更高的表示形式。 |机器码 (Hex)| 二进制 (Binary)| 汇编指令| | ------------ | ------------ | |`0x01A03001` |`0000 0001 1010 0000 0011 0000 0000 0001`| `moveq r3, r1`| |`0xE1A03001` |`1110 0001 1010 0000 0011 0000 0000 0001`| `mov r3, r1`| |`0xE0832001` |`1110 0000 1000 0011 0010 0000 0000 0001`| `add r2, r3, r1`| ### ARM指令编码的具体结构 tn2>从右往左数。 31到28位表示条件码(condition codes),如0000表示EQ(等于),0001表示NE(不等于)。 24到21位表示操作码(opcode),如1101表示moveq,1101表示mov,0100表示add。 15到12位表示目标寄存器(Rd), 11到0位表示源寄存器(Rs)或立即数(immediate value)。 ### 条件码的解释 | 条件 | 描述 | | ------------ | ------------ | |`0000` (EQ)|Z = 1,表示等于| |`0001` (NE)|Z = 0,表示不等于| |`0010` (CS/HS)|C = 1,有进位,无符号数大于等于| |`0011` (CC/LO)|C = 0,无进位,无符号数小于| |`0100` (MI)|N = 1,负数| |`0101` (PL)|N = 0,正数或零| |`0110` (VS)|V = 1,溢出| |`0111` (VC)|V = 0,无溢出| |`1000` (HI)|C = 1且Z = 0,无符号数大于| |`1001` (LS)|C = 0或Z = 1,无符号数小于等于| |`1010` (GE)|N = V,带符号数大于等于| |`1011` (LT)|N ≠ V,带符号数小于| |`1100` (GT)|Z = 0且N = V,带符号数大于| |`1101` (LE)|Z = 1或N ≠ V,带符号数小于等于| |`1110` (none)|不启用条件判断|| tn2>我们在表格中的二进制里面找到32-28位也就是从左往右数的前4位。 `moveeq`表示等于所以对应的是`0000` 其他两行都没有判断所以是`1110`。 ### 常规操作码 tn2>接着的24-21为对应的是相关操作码。 | 操作码 | 汇编指令 | 描述 | | ------------ | ------------ |------------ | |`0000`|AND|按位与| |`0001`|EOR|按位异或| |`0010`|SUB|减法| |`0011`|RSB|反向减法(减法的操作数交换)| |`0100`|ADD|加法| |`0101`|ADC|带进位加法| |`0110`|SBC|带进位减法| |`0111`|RSC|反向带进位减法| |`1000`|TST|测试(与操作结果更新标志)| |`1001`|TEQ|测试(异或操作结果更新标志)| |`1010`|CMP|比较(减操作结果更新标志)| |`1011`|CMN|比较(加操作结果更新标志)| |`1100`|ORR|按位或| |`1101`|MOV|传送| |`1110`|BIC|位清零(与非操作)| |`1111`|MVN|按位取反| ### 拆解指令含义 tn2>`moveq r3, r1` |位| 二进制| 含义| | ------------ | ------------ |------------ | |31-28| `0000`| 条件码 EQ (Z=1)| |27-26| `00`| 指令类型| |25|`0`| | |24-21| `1101`| 操作码 MOV| |20|`0` | S位 (更新条件标志)| |19-16| `0000` | 源寄存器 Rn| |15-12| `0011` | 目标寄存器 Rd (r3)| |11-0| `0000 0000 0001`|源寄存器 Rs (r1)| tn>当S位被设置为1时,执行指令后会更新CPSR中的条件标志位。 当S位被设置为0时,执行指令后不会更新CPSR中的条件标志位。 tn2>`mov r3, r1` |位| 二进制 |含义| | ------------ | ------------ |------------ | |31-28| 1110| 条件码 AL (总是)| |27-26| 00| 指令类型| |25| 0| | |24-21| 1101| 操作码 MOV| |20| 0| S位 (更新条件标志)| |19-16| 0000| 源寄存器 Rn| |15-12| 0011| 目标寄存器 Rd (r3)| |11-0| 0000 0000 0001| 源寄存器 Rs (r1)| tn2>`add r2, r3, r1` |位| 二进制 |含义| | ------------ | ------------ |------------ | |31-28| `1110`| 条件码 AL (总是)| |27-26| `00`| 指令类型| |25| `0`| | |24-21 |`0100`| 操作码 ADD| |20|`0`|S位 (更新条件标志)| |19-16 |`0011`| 源寄存器 Rn (r3)| |15-12 |`0010`| 目标寄存器 Rd (r2)| |11-0 |`0000 0000 0001`| 源寄存器 Rs (r1)| tn2>在这当中`mov r3,#0x1101`是不可以的。 因为它对应的二进制是`0001 0001 0000 0001`,在ARM中最高支持8位而转换成二进制已经是16位了所以是不行的。 ![](https://img.tnblog.net/arcimg/hb/231b56bd93c94bb7a28e92a90e6cc716.png) tn2>但是`mov r3,#0x11000000`这样是可以。 在ARM汇编指令集中,立即数(immediate value)有严格的格式限制,不能任意指定。 具体来说,立即数必须能够通过旋转和8位数的组合表示出来。 `#0x11000000`这个数可以通过8位立即数和右移偶数位的方法表示出来。 ![](https://img.tnblog.net/arcimg/hb/9f9568efaa524656b13adac9112abe96.png) tn2>当然可以通过伪指令解决这个问题。`ldr r3,=0x1101`。 ![](https://img.tnblog.net/arcimg/hb/68fff4610df74655b66ea4cab0ac8f11.png) tn2>原因是在汇编程序中,编译器会将这条指令翻译为两步操作: 计算立即数`0x1101`的地址,假设为`0x1000`。 将地址`0x1000`中的值加载到寄存器 `r3` 中。 跳转指令 ------------ | 指令 | 描述 | | ------------ | ------------ | | `b main` | 跳转到符号为main地代码处 | | `bl func` | 跳转函数func,并保存下一条要执行的指令的位置到lr(LR这里是R14),当跳转代码结束后,用`mor pc,lr`指令跳回来 | | `beq addr` | 相等时,跳转到地址addr处。相等(指CPSR寄存器中的条件码置位时)| | `bne addr` | 不等时,跳转到地址addr | ### 用汇编实现C语言功能 ```c void main(void){ int ret=0 ret=func1(2) while(1){} } int func1(int a){ if(a==2) return func2(1) else return func3(2) } int func2(int a){ return a+3; } int func3(int a){ return a-1; } ``` ```bash .text b main nop nop nop nop nop nop nop main: mov r2,#0 bl func1 main_end: b main_end func1: mov r4,lr cmp r2,#2 mov r5,#1 bleq func2 mov r5,#2 blne func3 func1_end: mov pc,r4 func2: add r2,r5,#3 func2_end: mov pc,lr func3: sub r2,r5,#1 func3_end: mov pc,lr .end ``` ![](https://img.tnblog.net/arcimg/hb/bde2af04c8db4b94aff70f3bad329c59.png) 逻辑指令 ------------ tn2>与,指令`and`。 ```bash mov r1,#0x03 @ 0000 0011 mov r2,#0x0e @ 0000 1110 and r0,r1,r2 @ 0000 0010 ``` ![](https://img.tnblog.net/arcimg/hb/134bb9ebde6b4002b55eebed39923bc4.png) tn2>或,指令`orr`。 ```bash mov r1,#0x03 @ 0000 0011 mov r2,#0x0e @ 0000 1110 orr r0,r1,r2 @ 0000 1111 ``` ![](https://img.tnblog.net/arcimg/hb/e243806d0d2b49a4a1fa951bb8f4149b.png) tn2>BIC(Bit Clear)指令用于将一个寄存器的某些位清零。 它执行`r2`按位与操作,然后将结果取反。 ```bash mov r1,#0x03 @ 0000 0011 mov r2,#0x0e @ 0000 1110 bic r0,r1,r2 @ 0000 0001 ``` ![](https://img.tnblog.net/arcimg/hb/b96c27ef0ad142d69217ab9dab539573.png) tn2>TST(Test)指令用于测试两个操作数的按位与结果,并根据结果更新条件标志(条件码寄存器中的标志)。 它类似于 AND 指令,但不会存储结果,只会更新标志位。 Z(零)标志:如果结果为零,则设置为 1;否则设置为 0。 N(负)标志:如果结果的最高有效位(符号位)为 1,则设置为 1;否则设置为 0。 C(进位)标志:保留原值,不受影响。 V(溢出)标志:保留原值,不受影响。 ![](https://img.tnblog.net/arcimg/hb/9fcf34ffdaeb440e83ef84f2a988adb5.png) tn2>CMP(Compare)指令用于比较两个操作数,并根据比较结果更新条件标志(条件码寄存器中的标志)。 它执行减法操作,但不存储结果,只会更新标志位。 ```bash mov r1,#0x03 @ 0000 0011 mov r2,#0x04 @ 0000 0100 cmp r1,r2 @ 0000 0000 Z=1 ``` ![](https://img.tnblog.net/arcimg/hb/940358a1d3d545eda5ee2f3ac370539f.png) 延时1秒 ------------ ```bash .text b main nop nop nop nop nop nop nop main: mov r0,#1 bl delay1s mov r0,#2 delay1s: ldr r4,=0x1fffff delay1s_loop: cmp r4,#0 beq delay1s_end subne r4,#1 b delay1s_loop delay1s_end: mov pc,lr main_end: b main_end .end ``` ![](https://img.tnblog.net/arcimg/hb/5d11bc73137e4e34bfc6a5fc68c75cf9.png)
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
👈{{preArticle.title}}
👉{{nextArticle.title}}
评价
{{titleitem}}
{{titleitem}}
{{item.content}}
{{titleitem}}
{{titleitem}}
{{item.content}}
尘叶心繁
这一世以无限游戏为使命!
博主信息
排名
6
文章
6
粉丝
16
评论
8
文章类别
.net后台框架
177篇
linux
18篇
linux中cve
1篇
windows中cve
0篇
资源分享
10篇
Win32
3篇
前端
28篇
传说中的c
5篇
Xamarin
9篇
docker
15篇
容器编排
101篇
grpc
4篇
Go
15篇
yaml模板
1篇
理论
2篇
更多
Sqlserver
4篇
云产品
39篇
git
3篇
Unity
1篇
考证
2篇
RabbitMq
23篇
Harbor
1篇
Ansible
8篇
Jenkins
17篇
Vue
1篇
Ids4
18篇
istio
1篇
架构
2篇
网络
7篇
windbg
4篇
AI
19篇
threejs
2篇
人物
1篇
嵌入式
20篇
python
20篇
HuggingFace
8篇
pytorch
10篇
opencv
6篇
Halcon
5篇
最新文章
最新评价
{{item.articleTitle}}
{{item.blogName}}
:
{{item.content}}
关于我们
ICP备案 :
渝ICP备18016597号-1
网站信息:
2018-2024
TNBLOG.NET
技术交流:
群号656732739
联系我们:
contact@tnblog.net
欢迎加群
欢迎加群交流技术