ARM汇编

一、ARM编程-工作模式

ARM Cortex-A系列处理器支持如下八种工作模式:

  1. 用户模式(usr):User模式

    操作系统之上应用程序代码运行本模式

  2. 系统模式(sys):System模式

    操作系统内核源码里各个系统调用函数体内代码所处的工作模式

  3. 管理模式(svc):Supervisor模式

    开机或复位 运行的代码

    软中断异常的处理代码

  4. 中断模式(irq):Interrupt模式

    中断是一种硬件通知机制

    中断异常的处理代码所处的工作模式

  5. 快速中断模式(fiq):Fast-interrupt模式

    快中断也是一种硬件通知机制,但对它的响应速度,要比中断异常更快

    快中断异常的处理代码所处工作模式

  6. 未定义模式(und):undefine模式

    当CPU无法正确执行某条指令,会产生未定义指令异常

    未定义指令异常的处理代码所处的工作模式

  7. 中止模式(abt):abort模式

    当CPU访问内存时如果出错,会产生数据中止异常或指令预取异常

    数据中止异常或指令预取异常的处理代码所处工作模式

  8. 监控模式(mon):monitor模式

    执行安全监控性质代码时所处的工作模式

用户模式:非特权模式

其他7种:特权模式

svc、irq、fiq、und、abt这五种模式专门用于对应的异常处理,因此又将他们统一称为:异常模式

二、ARM编程-寄存器组织

不同工作模式决定CPU内部寄存器的使用方式:

Cortex-A系列之前,ARM SOC处理器内部含编程可用寄存器37个

Cortex-A系列之后,ARM SOC处理器内部含编程可用寄存器40个

  • R0~R12:通用寄存器:寄存器中存放的内容由程序员自行决定–
  • R13:又叫做SP Stack Pointer 栈顶指针
  • R14:又叫做LR LInk Register 链接寄存器
  • R15:又叫做PC Program Counter 程序计数器
  • CPSR:Current Program Status Register 当前程序状态寄存器
  • SPSR:Saved Program Status Register 备份用程序状态寄存器,专门用于对CPSR进行备份

在这里插入图片描述
在这里插入图片描述

三、ARM指令一般形式

在这里插入图片描述

典型的ARM指令二进制编码格式:

在这里插入图片描述

  • opcode:操作码

  • cond:条件码

  • S:(S标记)决定指令的操作是否影响CPSR的值

  • Rd:目标寄存器

  • Rn:包含第1个操作数的寄存器编码

  • shifter_operand:表示第2个操作数

    • 第25位为0时:寄存器或者寄存器加移位 5位移位数+3位移位方式+4位寄存器编号
    • 第25位为1时:立即数 4位循环右移数+8位数值

每条ARM指令根据指定的条件码来决定是否会被执行

在这里插入图片描述

四、汇编程序中的语句

  1. 指令:有对应机器码的指令,需要CPU执行的各种运算
  2. 伪指令:形式类似于指令,但会被汇编器替换成同功能指令序列的语句
  3. 伪操作:没有对应机器码的操作,它是用于告诉汇编程序如何进行汇编的操作语句,在汇编过程中起作用,运行中不起作用
  4. #开头的整行注释,只能注释一整行
  5. @开头的行尾注释,即从@开始到行尾的内容被注释
  6. /* */包裹的多行注释

五、ARM指令分类

  1. 数据处理指令(重点)
    • 数据传送指令:MOV MVN
    • 算术运算指令:ADD ADC SUB SBC RSB RSC
    • 逻辑运算指令:AND ORR EOR BIC
    • 比较指令:CMP CMN TST TEQ
  2. 跳转指令:B(重点) BL(重点) BX(重点) BLX
  3. 乘法运算指令:MUL MLA SMULL SMLAL UMULL UMLAL
  4. PSR传输指令(重点):MRS MSR
  5. 访存指令(重点):LDR STR LDM STM SWP
  6. 异常产生指令:SWI(重点) BKPT
  7. 协处理器指令:CDP LDC STC MCR MRC

一般情况下,相同类的指令,具有同样寻址方式

寻址方式:操作数的来源方式

六、数据处理指令

6.1 数据传送指令

MOV指令:MOV{cond}{S} <Rd>, <shifter_operand>

功能:将shifter_operand表示的数据传送到目标寄存器中

程序中的作用:

  1. 将数据从一个寄存器传送到另一个寄存器中
  2. 将一个立即数传送到一个寄存器中
  3. 实现单纯的移位操作。左移可以实现操作数乘以2^n
  4. 当R15(PC)作为目标寄存器时,可以实现程序跳转
  5. 当R15(PC)作为目标寄存器且有S标志,除了跳转外,还会将对应的SPSR还原到CPSR

MVN指令:MVN{cond}{S} <Rd>, <shifter_operand>

功能:将shifter_operand表示的数据的反码传送到目标寄存器中

6.2 算术运算指令

ADD指令:ADD{cond}{S} <Rd>, <Rn>, <shifter_operand>

Rd = Rn + shifter_operand

ADC指令:ADC{cond}{S} <Rd>, <Rn>, <shifter_operand>

带进位的加法 Rd = Rn + shifter_operand+C

示例:64位的加法

.text	   @abcd
.globl _start
_start:
	MOV R0,#0xff000000		@Low 32bits
	MOV R1,#0x10000000		@High 32 bits

	MOV R2,#0xff000000      @Low 32bits
	MOV R3,#0x20000000      @High 32bits

	ADDS R4,R0,R2
	ADC R5,R1,R3
	B .
.end

SUB指令:SUB{cond}{S} <Rd>, <Rn>, <shifter_operand>

Rd = Rn - shifter_operand

SBC指令:SBC{cond}{S} <Rd>, <Rn>, <shifter_operand>

带借位的减法 Rd = Rn - shifter_operand - (~C)

作业:实现64位的减法

提交方式:sub64_姓名.S

上交日期:明日10:00前

SUBS R4,R0,R2
SBC R5,R1,R3

RSB指令:RSB{cond}{S} <Rd>, <Rn>, <shifter_operand>

逆向减 Rd = shifter_operand - Rn

简化立即数做为被减数的情况

@5-r2
mov R1,#5
sub R0,R1,R2

rsb R0,R2,#5

RSC指令:RSC{cond}{S} <Rd>, <Rn>, <shifter_operand>

带借位的逆向减法 Rd = shifter_operand - Rn - (~C)

@常用技巧
/*Rd = Rx *(2^n+1)*/
ADD R0,R1,R1,LSL #n

/*Rd = Rx *(2^n-1)*/
RSB R0,R1,R1,LSL #n

/*求64位的相反数,R0、R1放置一个64位数,R2,R3放置其相反数,R0、R2放置64位数低32位*/
RSBS R2,R0,#0
RSC R3,R1,#0

/*利用左移n位相当于乘以2的n次方,可以优化乘法*/
/*将R2中的值乘以4*/
MOV R2,R2,LSL #2

/*将R2中的值乘以5*/
ADD R2,R2,R2,LSL #2

6.3 逻辑运算指令:按位的位运算(两个操作数的所有位按位做运算)

AND指令:AND{cond}{S} <Rd>, <Rn>, <shifter_operand>

Rd = Rn & shifter_operand

  1. 程序中主要来将指定位 置0 (不太方便)

构造一个辅助数(掩码)来完成将指定位置0

AND R1,R1,#0xFFFFF7F3 不正确

  1. 判断指定位是1还是0

    判断R0的第6位是0还是1

    AND R1,R0,#0x40

ORR指令:ORR{cond}{S} <Rd>, <Rn>, <shifter_operand>

Rd = Rn | shifter_operand

  1. 程序中主要来将指定位 置1

将R0的第5位 置1,其它位不变:ORR R0,R0,#0x20

  1. 和BIC指令配合来给某寄存器的指定位范围赋值

    @将R0的低4位赋值为0b0101,其它位不变
    MOV R0,#0xAB
    BIC R0,R0,#0xF
    ORR R0,R0,#0b0101
    

EOR指令:EOR{cond}{S} <Rd>, <Rn>, <shifter_operand>

Rd = Rn ^ shifter_operand 相同为零,不同为1

程序中主要来将指定位 取反:构造掩码,掩码中所谓为1的位,与第一个操作数对应做异或,会将这些位取反

BIC指令:BIC{cond}{S} <Rd>, <Rn>, <shifter_operand>

位清除:将指定位置0

Rd = Rn & (~shifter_operand)

BIC R1,R1,#0x800

BIC R1,R1,#0xC

@常用技巧
/*判断R0的第2位为0还是1*/
AND R1,R0,#4

/*将r3寄存器中的第3、5位置0*/
BIC R3,R3,#0x28
AND R3,R3,#FFFFFFD7   @非法立即数

/*将r3寄存器中的第3、5位置1*/
ORR R3,R3,#0x28

/*将r3寄存器中的第3、5位取反*/
EOR R3,R3,#0x28

/*将r3寄存器中的低四位设置成0101,其它位不变*/
BIC R3,R3,#0xF
ORR R3,R3,#0b0101

/*将R2的高八位放置到R3的低八位,R3的其它位不变*/
MOV R0,R2,LSR #24
BIC R3,R3,#0xFF
ORR R3,R3,R0
@测验
@1. 写一条 ARM 指令,分别完成下列操作:
@a) r0 = 16    
	MOV R0,#16
@b) r0 = r1 / 16 (带符号的数字)
	MOV R0,R1,ASR #4
@c) r1 = r2 * 3    
	ADD R1,R2,R2,LSL #1
@d) r0 = -r0   
	RSB R0,R0,0
	
@2. 下面哪些立即数是数据处理指令中有效的数据?
@a) 0x00AB0000 合法
@b) 0x0000FFFF 非法 
@c) 0xF000000F 合法
@d) 0x08000012 非法
@e) 0x00001f80 合法
@f) 0xFFFFFFFF 非法

@3. BIC指令做什么用?

@4. 为什么ARM 处理器增加了一条RSB 指令?

6.4 比较指令

没有S标志,这些指令只是为了设置CPSR高4位

这些指令不要计算结果,只要计算后CPSR高4位的状态

比较指令一般不会单独使用,往往是配合一些指令的条件助记符来实现选择执行

CMP指令:CMP{cond} <Rn>, <shifter_operand>

Rn - shifter_operand

SUBS

CMN指令:CMN{cond} <Rn>, <shifter_operand>

Rn + shifter_operand

ADDS

TST指令:TST{cond} <Rn>, <shifter_operand>

位测试 Rn & shifter_operand

ANDS

TEQ指令:TEQ{cond} <Rn>, <shifter_operand>

相等测试 Rn ^ shifter_operand

EORS

七、跳转指令

这些指令只能实现短跳转,要实现任意范围的跳转用MOV PC,<shifter_operand>

B指令:B{cond} <target_address>

跳转到指定位置,target_address在二进制编码中占24位,一般用于局部范围内跳转,跳转范围-32M~32M

一般用来局部代码的循环实现

BL指令:BL{cond} <target_address>

带链接的跳转:保存PC到LR,跳转到指定位置,一般用于子程序调用

BX指令:BX{cond} <Rm>

带状态转换的跳转:跳转到指定位置,Rm的bits[0]为1切换为Thumb状态、bits[0]为0切换为ARM状态,一般用于子程序返回

BLX指令1:BLX <target_address>

保存PC到LR,跳转到指定位置,并切换为Thumb状态

BLX指令2:BLX{cond} <Rm>

保存PC到LR,跳转到指定位置,Rm的bits[0]为1切换为Thumb状态、bits[0]为0切换为ARM状态

八、LDR伪指令装载任意数

LDR R0,=const :可以装载任意的32位常数

  1. 这种形式LDR是伪指令
  2. 汇编器遇到该行,发现如果mov可以的话,就改为使用mov指令来完成,如果mov不行的话,就借用内存来实现该数的装载
  3. MOV与LDR伪指令的比较
    用mov来实现,占用空间小,速度快,但是对立即数有限制
    如果数比较大,用ldr r0,=const会多占空间,降低效率

在实际编程中,如果只是将一个常数赋值给一个寄存器,建议写成:LDR Rn,=常数

聪明的汇编器:

LDR R0,=0x1F ----> MOV R0,#0x1F

LDR R1,=0xABCD1234 ----> 将0xABCD1234放到内存,然后读内存数据到寄存器

MOV R2,#0xFFFFFFFF

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值