arm汇编指令学习

正式开始学习ARM汇编了,加油~~~!

ARM汇编简单入门

PUSH {R3,LR} 入栈,为了保存寄存器值。
POP {R3,PC} 出栈,恢复寄存器的值。
将LR寄存器的值传递到PC寄存器然后跳到对应的位置.

MOV 数据传送指令。(从右到左)
ADD 数据相加指令。

LDR 从内存到寄存器。<- str="" 从寄存器到内存。-="">

BXL 跳转指令。(B无条件跳转,L是带连接的,X表示状态切换,arm指令跟thumb指令切换)

解释&&备注

汇编处理的是从右到左。
PC寄存器 = R15。
PC是控制程序的走向。(程序的执行流程)

LDR R3,[R3] 意思是把R3寄存器地址对应的值放到R3寄存器中。
ADD R1,R1,PC 意思是R1寄存器的值+PC寄存器的值放到R1寄存器中。
SUB R1,R0,#5 意思是R1寄存器的值等于R0寄存器的值减去5

MOVS R2,#0xB
STR R2,[R3] 意思是将R2寄存器的值放到R3寄存器地址。

ARM微处理器共有37个寄存器,31个通用寄存器,六个状态寄存器。一般使用R0到R15。
R0 - R15
R0到R3四个寄存器是保存参数的。多余的参数保存到栈中。
常用寄存器以及他的别名
R11 fp
R12 ip
R13 sp 堆栈寄存器
R14 lr 连接寄存器
R15 pc 程序计数器

CPSR 标志寄存器
R0到R9为通用寄存器

汇编基本指令格式

{cond}{S}{.W|.N} ,{,operand2}
opcode 指令的助记符
cond 条件
S 是否将运算结果写入到标志寄存器
宽度说明符
.W 32
.N 16

下面正式开始学习ARM汇编

加油!

MOV指令

MOV{cond}{s} ,
{} 表示可选
<> 必选项
Rd 表示目标寄存器
operand 常数/可用寄存器
常数以#开头,默认十进制,十六进制前缀0x
MOV R0,#100 ==> R0 = 100

ADD指令

ADD{cond}{s} ,,
Rn 第一个源寄存器,只要是通用寄存器即可
ADD R0,R1,R2 ==> R0 = R1 + R2

SUB指令

SUB{cond}{s} ,,
SUB R0,R1,R2 ==> R0 = R1 - R2

ARM汇编寻址

立即寻址

立即寻址多于用给寄存器赋值
MOV R0,#100 ==> R0 = 100

寄存器寻址

操作数在寄存器中,指令执行时直接在寄存器中取数据
MOV R0,R1 ==> R0 = R1
MOV R1,R2 ==> R1 = R2

寄存器移位寻址

移位指令:LSL、LSR、ASR、ROR、RRX

LSL 逻辑左移(<<)

一般用法 LSL #2
如果 A=B<<n 则 A=B*2^n

MOV R0,R1,LSL #2 ==> R0 = R1>>2 ==> R0 = R122

寄存器间接寻址

寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。

LDR指令

LDR用于寄存器(内存)加载数据到寄存器中
LDR{type}{cond} Rd,label{!}
LDRDcond{} Rd,Rd2,lable{!}(一次加载双字(64位))
{!}是否将寻址结果写入寄存器中
type 取值:
B 无符号字节
SB 有符号字节
H 无符号半字
SH 有符号半字
label 内存地址

STR指令

将寄存器的值写入到内存
STR R0,[R1]

LDR R0,[R1] ==> R0 = [R1] ==> R0 = *R1

C语言等价汇编语言
*R2 ==> [R2]

基址变址寻址

基址变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而等到一个操作数的有效地址

LDR R0,[R1,#4]; R0 = [R1+4] ==> R0 = *(R1+4)
LDR R0,[R1,#4]!; R0 = [R1+4] && R1 = R1 + 4
LDR R0,[R1],#4;R0 = R[1] && R1 = R1 + 4
LDR R0,[R1,R2]; R0 = [R1+R2]

LDM指令

LDM指令是批量从内存加载数据到寄存器列表
LDM{addr_mode}{cond} Rn{!}reglist
addr_mode的类型。用于数据的存储和读取有以下几种情况:
IA 每次传送后地址加
IB 每次传送前地址加
DA 每次传送后地址减
DB 每次传送前地址减

对于堆栈操作有如下几种情况:
FD 满递减堆栈
ED 空递减堆栈
FA 满递增堆栈
EA 满递增堆栈

寄存器列表

{R0,R5}
{R0-R3,R4}
{R1-R2,LR}
{R0,R1,R2}

STM

STM批量将寄存器列表中的值写入内存
STM{addr_mode}{cond} Rn{!}reglist

两个指令的例子:
STMFD SP!,{FP,LR} (入栈)(写)(函数开头)(将FP寄存器以及LR寄存器压入到堆栈中)(将寄存器列表中的寄存器全部保存到堆栈中)(SP向下的)
LDMFD SP!,{FP,PC} (出栈)(读)(函数结尾)(将保存在堆栈中的寄存器还原到寄存器列表)(SP向上的)

LR 保存上层函数调用子函数的地址。
PC 给PC赋值实现了函数的返回。

LR 赋值给PC实现跳转

多寄存器寻址

采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这寻址指令可以用一条指令完成传送最多16个通用寄存器的值。

LDM指令

LDMIA R0,{R1,R2,R3,R4}

; R1 = [R0]
; R2 = [R0+4]
; R3 = [R0+8]
; R4 = [R0+12]

该指令的后缀IA表示在每次执行完加载/存储操作后,R0按字长度增加,因此该指令可以将连续存储单元的值传送到R1~R4。

堆栈寻址

一般用于保存子程序现场

STM指令

一般STM与LDM成对出现

STMFD SP!,{R1-R7,LR}
LDMFD SP!,{R1-R7,LR}

STMFD SP!,{FP,LR}
LDMFD SP!,{FP,PC}

相对寻址

B指令

跳转指令也称分支指令,它可以改变CPU的执行流程
ARM中有两种方式可实现跳转
1、修改PC寄存器
2、使用跳转指令

B {cond} lable
B NEXT
NEXT

BL指令

带链接跳转,会将下条指令的地址报错到LR寄存器,并跳转到目标地址。
BL{cond}lable
一般用于子程序(函数)调用,在子程序尾部可以用MOV PC,LR来返回上层。

BX指令

带状态切换的跳转指令
BX{cond} Rm
当满足{cond}条件时,处理器会检查Rm[0]是否为1,如果Rm[0]=1,则处理器自动将CPSR的T标>志位置位(将T变为1,T位为状态位),并将目标代码解释位Thumb指令集。
如果Rm[0]=1,处理器将T标志位复位(将T变为0),并将目标代码解释为ARM指令集。

BLX指令

带链接的状态切换跳转。
Z为CPSR寄存器中的标志
BEQ Z=1 相等
BNE Z=0 不相等
BGE N=V 有符号数大于或者等于
BLT N!=V 有符号数小于
BLE Z=1,N!=V 有符号数小于或者等于
BGT Z=0,N!=V 有符号数大于

CMP指令

CMP{cond} Rn,operand2
CMP指令将Rn寄存器的值减operand2的值,并设置标志寄存器。相当于SUBS Rn,operand2(SUBS后缀带S的意思是将运算结果放入标志寄存器中)
CMP R0,0 判断R0的值是否为0
JE R0,0 判断R0的值是否等于0

谢谢,爱你么么哒