- 4arm指令集概述
- .c文件里面包含
- 语句a++;
- 注释//
- 预编译指令(条件编译)#if 1. .... #else .... #endif
- 汇编:
- 汇编中的符号
- 指令:能够编译生成一条32bit机器码,并且能被cpu识别和执行
- 数据处理指令:进行数学运算、逻辑运算、
- 跳转指令:实现程序的跳转,本质就是修改了PC寄存器
- Load/Store指令:访问(读写)内存
- 状态寄存器传送指令:用于访问(读写)CPSR寄存器
- 软中断指令:给CPU发送中断信号,触发软中断
- 协处理器指令:操作协助处理器的指令
- 伪指令:本身不是指令,编译器可以将其替换成若干条指令
- 伪操作:不会生成指令,只是在编译阶段告诉编译器怎么编译
- 指令:能够编译生成一条32bit机器码,并且能被cpu识别和执行
- 汇编中的符号
- 数据处理指令:
- 数据处理指令:数学运算、逻辑运算
- @数据搬移指令R1=1
- MOV R1, #1
- MOV R2, #2
- MOV R3, #3
- MOV PC, #0 @0存的是第一条指令R1,这样就相当于一个小的循环,pc最后两位没有值,但是如果强制写成值,最后两位要改成00,因为他要保持四的整数倍
- MOV R2, R1
- MVN R0, #0xFF. @R0 = ~0xFF 相当于按位取反后再搬移指令
- 立即数@编译不通过就不是立即数,编译通过就是立即数
- 立即数的本质就是包含在指令当中的数,属于指令的一部分
- MOV R0, #0x12 @是立即数
- MOV R0, #0x12345678 @不是立即数,超长了
- 立即数和普通变量区别是变量独占空间,立即数是指令一部分
- 立即数优势是:取指的时候就可以将其读取到CPU,不用单独去内存读取,速度快
- 缺点是:不能是任意的32位的数字,有局限性
- MOV R0, #0xFFFFFFF @不是立即数,但是编译器不报错,类似伪指令,CPU编译成认识的
- @ 加法指令
- MOV R2, #5
- MOV R3, #3
- ADD R1,R2,R3 @R1 = R2+R3
- ADD R1, R2 ,#5
- ADD R1, #5, #5 //这种是错的 ADD R1, #5, R1 //这种也是错的
- @减法指令
- SUB R1, R2, R3
- SUB R1, R2, #3
- sub缺点:只能寄存器-寄存器,寄存器-数,所以设计逆向减法指令
- 逆向减法指令
- RSB R1,R2,#3 @R1 = 3-R2,还是最后写数
- 乘法指令MUL,不能用立即数
- MUL R1, R2,R3 @R1=R2*R3
- 乘法指令只能是两个寄存器相乘
- arm不能直接算除法,通过替换成右移指令
- 按位与指令
- AND R1,R2,R3 @R1=R2&R3
- 按位或指令
- ORR R1,R2,R3 @R1=R2|R3
- 按位异或指令
- EOR R1,R2,R3 @R1=R2^R3
- 左移指令
- MOVR2, #0xF0
- MOV $3, #0x2
- LSL R1,R2,R3 @R1=(R2<<R3)
- 右移指令
- LSR R1,R2,R3 @R1=(R2>>R3)
- 位清零指令
- MOV R2, #0xFF
- BIC R1,R2,#0xF @把R2最后4位清0保存给R1,R2不会变,只是把结果给R1(第二操作数中的哪一位为1,就将第一操作寄存器的中哪一位清零,然后将结果放入目标寄存器)
- 数据运算指令的格式:
- 《操作码》《目标寄存器》 《第一操作寄存器》《第二操作数》
- 操作码:表示执行哪种操作
- 目标寄存器: 用于存储运算的结果
- 第一操作寄存器:存储第一个参与运算的数据(只能是寄存器)
- 第二操作数:第二个参与运算的数据(可以是寄存器,也可以是立即数)
- 数据运算指令的格式扩展
- MOV R1, R2, LSL #1@R1=(R2<<1)
- 《操作码》《目标寄存器》 《第一操作寄存器》《第二操作数》
- @数据搬移指令R1=1
- 数据处理指令:数学运算、逻辑运算
- CPSR寄存器
- 数据运算指令对条件位(N、Z、C、V)的影响
- MOV R1, #3
- SUBS R2, R1, #5
- 默认情况下数据运算不会对条件位产生影响,当在指令后加后缀"S"后可以影响
- 两个64位的数据做加法运算,把高低位拆开分别放在cpu运算,
- 第一个数的低32位放在R1,
- 第一个数的高32位放在R2
- 第二个数的低32位放在R3
- 第四个数的高32位放在R4
- 运算结果低的32位放在R5
- 运算结果高的32位放在R6
- MOV R1, #0x00000001
- MOV R2, #0x00000001
- MOV R3, #0x00000002
- MOV R4, #0x00000002
- ADD R5, R1,R3. @无法解决进位问题
- ADD R6, R2,R4。 @无法解决进位问题
- 解决方案:
- ADDS R5,R1,R3
- ADC R6,R2,R4 @ADC带进位的加法 R6=R2+R4+‘C’位
- 带借位的减法指令SBC
- 第一个数0x00000002 00000001
- 第二个数0x00000001 00000005
- MOV R1,#0x00000001
- MOV R2,#0x00000002
- MOV R3,#0x00000005
- MOV R4,#0x00000001
- SUBS R5, R1, R3
- SBC R6, R2,R4@本质是R6=R2-R4-'!C' (C的取反)
- 跳转指令:实现程序的跳转,本质就是修改了PC寄存器
- 方式一:直接去修改PC寄存器的值
- 方式二:B FUNC:本质也是修改PC,编辑器修改PC的值, LR的值自动改成下一条指令的地址(B不带返回的跳转指令,本质就是将PC寄存器的值改成跳转标号下第一条指令的地址)
- 方式三:BL FUNC带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下的第一条指令的地址,同时将跳转指令下一条指令的地址存储到LR寄存器
- 在FUNC方法里面最后需要:MOV PC,LR
- c里面BX指令跳转,貌似还切换指令集,了解用
- ARM指令的条件码
- CMP R1,R2
- CMP本质就是一条减法指令(SUBS),只是没有将运算的结果存入寄存器
- BEQ == NEQ not equal !=
- cpu本身就是个电路
- ARM指令集中大多数指令都可以带条件码后缀
- 内存访问指令
- Load/Store指令:访问(读写)内存
- 写内存
- STR R1,[R2] @将R1寄存器中的数据存储到R2指向的内存空间
- 调试结果如下:说明是小端对齐,低地址对应低有效位,高地址对应高有效位
- 读内存
- LDR R3,[R2] @将内存中R2指向的内存空间中的数据读取到R3寄存器
- STRB(byte 一个字节只把最低的八位写进去)
- STRH(half word 半个字,两个字节,只把最低的16位写进去)
- c语言不通类型的变量对应不同的指令
- 寻址方式就是CPU去寻找一个操作数的方式
- ARM指令的寻址方式
- 立即寻址
- MOV R1,#1 //参与运算的数来自于立即数
- ADD R1, R2, #1
- 寄存器寻址
- ADD R1,R2,R3
- 寄存器移位寻址
- MOV R1,R2,LSL #1
- 寄存器间接寻址
- STR R1,[R2] // 用寄存器指向内存
- 基址+变址寻址
- 基址+变址寻址的索引方式
- 立即寻址
- 多寄存器内存访问指令
- 多寄存器内存指令的寻址方式
- STMIA(increase after)
- STMIB(increase before)
- STMDA(decrease after)
- STMDB(decrese before)
- 栈的种类和应用
- 栈的概念:
- 栈的本质就是一段内存,程序运行时用于保存一些临时数据,如局部变量、函数的参数、返回值以及程序跳转时需要保护的寄存器
- 栈的种类:压栈,出栈
- STMFD(不是新命令,编译器自动编译成STMDB)
- LDMFD(不是新命令,编译器自动编译成STMIA出栈)
- 栈的应用举例
- 叶子函数的调用过程
- 应用栈后:
- 栈的概念:
-
CPSR寄存器
-
Current Program Status Register,当前程序状态寄存器
-
CPSR寄存器分为四个域,【31:24】为条件域用F表示,【23:16】为状态域用S表示,【15:8】为预留域用X表示,【8:0】为控制域用C表示
-
Bit[4:0]
-
[10000]User
-
[10001]FIQ
-
[10010]IRQ
-
[10011]SVC
-
[10111]Abort
-
[11011]Undef
-
[11111]System
-
[10110]Moniter
-
-
Bit[5]
-
[0]ARM状态
-
[1]Thumb状态
-
-
Bit[6]
-
[0]开启FIQ 硬件中断
-
[1]禁止FIQ
-
-
Bit[7]
-
[0]开启IRQ 硬件中断
-
[1]禁止IRQ
-
-
读CPSR
-
MRS R1, CPSR @ 把cpsr的值读到r1,上电默认svc模式
-
-
写CPSR
-
MSR CPSR, #0x10 @user模式
-
MSR CPSR, #0xD3 @svc模式,在user模式下,不能修改CPSR,非特权模式
-
-
-
软中断指令
-
swi指令在linux内核应用较多
-
-
协处理器指令
-
操控制协处理器的指令
-
协处理器数据运算指令
-
CDP
-
-
协处理器存储访问指令
-
STC将协处理器中的数据存储到存储器中
-
LDC将存储器中的数据读取到协处理器中
-
-
协处理器寄存器传送指令
-
MRC将协处理器中寄存器的数据传送到ARM处理器中的寄存器
-
MCR将ARM处理器寄存器中的数据传送到协处理器中的寄存器
-
-
-
-
伪指令
-
本身不是指令,编译器可以将其替换成若干条指令
-
NOP.空指令
-
MOV R0, R0 这个指令不做任何事情,但是浪费cpu时间
-
-
- .c文件里面包含
-
伪操作和混合编程
-
伪操作:不会生成代码,只是在编译阶段告诉编译器怎么编译
-
.GNU伪操作一般都以"."开头
-
.global symbol
-
将symbol声明成全局
-
.local symbol
-
将symbol声明成局部
-
.equ DATA, oxFF // .equ相当于c语言里面的宏
-
MOV R1, #DATA
-
.maroc .endm 封装代码段
-
#if1 #endif .rept .endr
.weak symbol 弱化符号。 B func
.word 在当前地址申请一个字的空间并将其初始化
.byte在当前地址申请一个字节的空间并将其初始化
.align 2 告诉编译器这一行之后的代码对其,2是2的几次方,align后用2的2次方对其:即4字节对齐
.arm 告诉编译器后面指令都是arm指令
.thumb告诉编译器后面指令都是thumb指令
-
.space 在当前地址申请任意个字节的空间并将其初始化
-
arm汇编指令集
于 2023-05-09 21:06:20 首次发布