目录
汇编指令代码框架
汇编指令语法格式
数据处理指令
数据搬移指令 mov
示例
立即数的本质
立即数的特点
立即数的使用
算术运算指令
指令格式
add 普通的加法指令
adc 带进位的加法指令
跳转指令
Load/Store指令
状态寄存器指令
基础概念
C 语言与汇编指令的关系
;) 的 C 语言语句可以被编译成汇编指令。#) 开头的行称为预处理指令,它们告诉编译器如何处理源代码。汇编语言的整体分类
(相当于c中的’#‘的内容)告诉编译器怎么编译)
(如:cpu中没有乘法器,对应没有乘法指令,3*3 ---》用加法器实现3+3+3,替换实现)
注释
@ 符号开始。/**/ 包围。指令分类
.text .global _start _start: ; 汇编代码段 .end {s} Rd, Rn, operand2 mov{s} Rd, operand2mov{}{s} Rd, #immediate在这个示例中,我们首先声明了一个 .text 段,然后定义了一个全局符号 _start,这是程序的入口点。接下来我们初始化寄存器 R0 为 0x1234,然后将 R0 的值复制给 R1。最后,通过 bx lr 返回到调用者
.text .global _start _start: ; 初始化寄存器 R0 为 0x1234 mov r0, #0x1234 ; 将 R0 的值移动到 R1 mov r1, r0 ; 结束程序 bx lr .end {s} Rd, oprand2
PC寄存器详细讲解:


指令的执行三步:取指,译码,执行(PC永远指向当前正在取指指令的地址)。
立即数在 ARM 汇编语言中是一个重要的概念。立即数是直接编码在指令中的数值,它与普通变量不同,后者通常存储在内存中。下面是关于立即数的一些详细说明和优化后的格式:
立即数是直接嵌入在指令中的数据,作为指令的一部分。这意味着当指令被加载到处理器中时,立即数也会同时被加载。
在 ARM 汇编语言中,立即数通常用于简单的数值操作,例如赋值或者与寄存器进行逻辑运算。立即数只能是某些特定的值,并且这些值通常被限制为可以由指令直接处理的形式。
如:MOV ,#0x12345678 @报错,不合法
对于 mov 指令而言,立即数必须是一个可以通过位移得到的 8 位值。这意味着立即数必须是 2 的幂次方的倍数,并且最大不超过 255。例如,0x1234 是一个有效的立即数,因为它可以通过位移得到。但是 0x12345678 则不是一个有效的立即数,因为它超过了 8 位的限制,并且不能通过简单的位移得到。 

注:使用mov 给寄存器里面存放值的时候,#号后面需是有效数(1:立即数,2:取反之后是立即数),如果不是立即数需要用ldr指令进行存放。

常见的算术运算指令包括:
算术运算指令的一般格式如下:
{}{s} Rd, Rn, operand2 其中:
是指令名称。 是条件码,可选。{s} 表示是否更新 CPSR 的标志位。Rd 是目标寄存器。Rn 是第一个操作寄存器。operand2 是第二个操作数,可以是寄存器或立即数。
假设2个64位的数相加
add和ADC的区别,例如是64位的字符,如果低位大小满足进1的话用ADD只会显示在C进1,但是存储的地址并不进1,ADC的话则会将存储的地址进1

注意:mul r2, r0, #0x4 @ 错误
乘法指令的第二个操作数只能是一个寄存器
mul r2, r1,r0

1》修改PC,不建议使用,因为需要查询指令的地址

2》 b bl :指令跳转
不保存返回地址的跳转(返回地址不保存到lr中)


补充了解:
RM指令条件码表:可跟的判断条件成立跳转(NZCV在用于判断两者之间关系使用比较多)

如:c代码如下:
练习: 实现以下逻辑 unsigned int r1 = 9; unsigned int r2 = 15; while(1) { if(r1 == r2) goto stop; if(r1 > r2) r1 = r1 - r2; if(r1 < r2) r2 = r2 - r1; } stop: while(1); 汇编指令练习答案如下: mov r1,#9 mov r2,#15 loop: cmp r1,r2 @cmp 比较指令 beq stop subhi r1,r1,r2 subcc r2,r2,r1 b loop stop: b stop 对内存的读写操作//如 a++ 读a的值,将运算结果从cpu写道内存
可用地址查找:(我们不用查找,脚本文件中配置了内存空间的分配)
查看内存中内容:

1>单寄存器操作指令 ldr/str
Rn:存储的数据,地址
将CPU中r1寄存器中的数据存储到内存中r0地址的空间中









栈指针指向的地址是空的,在栈中存储数据时,可以直接存储,存储完成之后需要将栈指针再次指向空的位置。
栈指针指向的地址有数据,在栈中存储数据时,需要先将栈指针,指向一个空的位置,然后在存储数据。

栈指针向高地址方向移动
栈指针向低地址方向移动
操作栈的方式有四种

sp!, {寄存器列表}
更新栈指针指向的地址空间

特殊:
stmfd sp!, {r1-r5,lr}(写) (压栈)
ldmfd sp!, {r6-r10,pc}(读) (出栈) //r1-r5出栈给r6-r10, 将lr的值出栈给pc
对CPSR进行读写操作//其他都不能动CPSR (SWI 指令是linux内核有,所以arm为了匹配才有的指令)(CPSR保存cpu的状态、模式、中断中断开关、运算状态,非常重要,不能任意更改,只有一类指令能操作这个寄存器)
1》读cpsr 指令mrs 
2》写cpsr 指令 msr :一般情况不能修改cpsr,只能用msr命令修改,user模式下不能切换到其他模式。


注:修改CPSR的控制域(bit[7:0]),修改CPSR时必须指定修改哪个区域
USER模式下不能修改CPSR的值,防止应用程序修改CPU状态,保护操作系统
CPSR_C修改的是CPSR的低八位ctrl(控制)域,一般都只修改C域
OK,就分享到这,如果帮到你那就点个关注吧~
上一篇:RabbitMQ的安装
下一篇:jupyter下载