arm汇编指令汇总

一、读内存:从内存读取数据到寄存器

  1. src:从哪里读?
  2. len:读多长?(ldr四字节,ldrb一字节,ldrh两字节)
  3. dst:读到哪里去?

(1)指令格式和作用:

LDR{条件} 目的寄存器,<内存地址>:从内存中将一个32位的字数据传送到目的寄存器中。该指令通常用于从内存中读取32位的字数据到通用寄存器,然后对数据进行处理。

LDR{条件}B 目的寄存器,<内存地址>:从内存中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零

LDR{条件}H 目的寄存器,<内存地址>:从内存中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零

特别说明:当程序计数器PC作为目的寄存器时,从内存中读取的字数据将被当作目的地址,从而实现程序流程的跳转。

(2)代码示例:

LDR  R0,[R1]       ;将内存地址为R1的字数据读入寄存器R0。
LDR  R0,[R1,R2]    ;将内存地址为R1+R2的字数据读入寄存器R0。
LDR  R0,[R1,#8]   ;将内存地址为R1+8的字数据读入寄存器R0。
LDR  R0,[R1,R2]!   ;将内存地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR  R0,[R1,#8]!  ;将内存地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
LDR  R0,[R1],R2         ;将内存地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR  R0,[R1,R2,LSL#2]! ;将内存地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
LDR  R0,[R1],R2,LSL#2  ;将内存地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。

(3)LDR伪指令

LDR Rn,=expr 

COUNT EQU 0x40003100 ;COUNT是我们定义的一个变量,地址为0x40003100。
LDR R1,=COUNT        ;将COUNT这个变量的地址,也就是0x40003100放到R1中。
MOV R0,#0            ;将立即数0放到R0中。
STR R0,[R1]          ;将R0中的值放到以R1中的值为地址的存储单元去。
                     ;实际就是将0放到地址为0x40003100的存储单元中去。
//这三条指令是为了完成对变量COUNT赋值。
//用三条指令来完成对一个变量的赋值,跟ARM的采用RISC有关。
//注意,变量、变量的地址、变量的值
//  COUNT  0x40003100  0

二、写内存:

(1)指令格式和作用:

STR{条件} 源寄存器,<内存地址>:从源寄存器中将一个32位的字数据传送到内存中。

STR {条件}B源寄存器,<内存地址>:从源寄存器中将一个8位的字节数据传送到内存中。该字节数据为源寄存器中的低8位。

STR {条件}H源寄存器,<内存地址>:从源寄存器中将一个16位的字节数据传送到内存中。该字节数据为源寄存器中的低16位。

(2)代码示例:

STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中。
STR R1,[R0]     ;将R1寄存器的值,传送到以r0为地址的存储器中。

     

三、算数运算指令

(1)指令格式和作用:

ADD{条件}{S} 目的寄存器,操作数1,操作数2:把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器、被移位的寄存器,或者一个立即数

SUB{条件}{S} 目的寄存器,操作数1,操作数2:把操作数1减去操作数2,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器、被移位的寄存器,或者一个立即数。该指令可用于有符号数或无符号数的减法运算。

(2)代码示例:

ADD  R0,R1,R2           ; R0 = R1 + R2
ADD  R0,R1,#256         ; R0 = R1 + 256
ADD  R0,R2,R3,LSL#1     ; R0 = R2 + (R3 << 1)

SUB  R0,R1,R2         ;R0 = R1 - R2
SUB  R0,R1,#256       ;R0 = R1 - 256
SUB  R0,R2,R3,LSL#1   ;R0 = R2 - (R3 << 1)

四、比较指令

(1)指令格式和作用:

CMP{条件} 操作数1,操作数2:将一个寄存器的内容和另一个寄存器的内容或立即数进行比较,比较结果放在CPSR中条件标志位的值。

(2)代码示例:

CMP R1,R0     ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100  ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位

五、跳转指令

在ARM程序中有两种方法可以实现程序流程的跳转:

(1)使用跳转指令实现程序流程的跳转

跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令:

指令

功能描述

应用场景

对寄存器的影响

示例

B

实现无条件跳转,跳转值为相对当前 PC 的偏移量(24 位有符号数扩展为 32 位)

短距离跳转、循环或条件跳转

仅改变程序计数器(PC)

B Label;

CMP R1, #0;

BEQ Label;

BL

跳转前将下一条指令地址存入链接寄存器 LR(R14),便于子程序返回

子程序调用

改变 PC,将返回地址存入 LR

BL my_subroutine

BX

跳转到指定地址,根据目标地址寄存器最低位 / 两位切换处理器状态(1 为 Thumb,0 为 ARM)

ARM 与 Thumb 指令集间切换跳转

改变 PC,切换处理器状态

BX R0

BLX

结合 BL 和 BX 功能,跳转前存返回地址到 LR,并切换处理器状态

调用 Thumb 指令集子程序(调用者为 ARM 指令集)

改变 PC,将返回地址存入 LR,切换处理器状态

BLX R0

(2)直接向程序计数器PC写入跳转地址值

通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中任意跳转,在跳转之前结合使用MOV LR,PC等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。

(2)代码示例:

B  Label    ;程序无条件跳转到标号Label处执行
CMP R1,#0  ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行
BEQ Label  


BL Label  ;程序无条件跳转到标号Label处,同时将当前的PC值保存到R14中

六、数据传送指令

(1)指令格式和作用:

压栈的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令,即可以一次操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址,PUSH 和 POP 的用法如下表所示:

指令 描述
PUSH <reg list>将寄存器列表存入栈中
POP <reg list> 从栈中恢复寄存器列表

(2)代码示例:

假如当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,压栈汇编代码如下:

PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈
PUSH {LR} @将 LR 进行压栈

对 LR 进行压栈完成以后的堆栈模型如下图所示:

如果我们要出栈的话就是使用如下代码:

POP {LR} @先恢复 LR
POP {R0~R3,R12} @在恢复 R0~R3,R12


出栈的就是从栈顶,也就是 SP 当前执行的位置开始,地址依次减小来提取堆栈中的数据到要恢复的寄存器列表中。

ref:ARM官方汇编指令_arm汇编指令-优快云博客

常用的ARM汇编指令_ldr指令-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值