ARM汇编常用指令

本节来学习ARM汇编的常用指令,并结合在uboot中看到的汇编指令进行分析。

目录

一 数据处理指令

(1) MOV  数据传送指令:

(2)MVN  数据取反传送指令

(3)CMP  比较指令

(4)CMN  反值比较指令

(5)TST  位测试指令

(6)TEQ  相等测试指令

(7)ADD  加法指令

(8)ADC  带进位加法指令

(9)SUB  减法指令

(10)SBC  带借位减法指令

(11)RSB  逆向减法指令

(12)RSC  带借位的逆向减法指令

(13) AND  按位与指令

(14)ORR 按位或指令

(15)EOR  按位异或指令

(16)BIC  位清除指令

(17)移位指令

(18)数据交换指令

(19)乘法与乘加指令

二 加载存储指令

(1)LDR  字数据加载指令  

(2)STR  字数据存储指令

(3)批量数据加载/存储指令

1)—LDM

2)—STM

三 跳转指令

1. B指令

2. BL指令

3. BLX指令

4. BX指令

四 程序状态寄存器访问指令

(1)MRS指令

(2)MSR指令

五 协处理器指令

(1)CDP指令

(2)LDC指令

(3)STC指令

(4)MCR指令

(5)MRC指令

六 异常产生指令

(1)SWI指令

(2)BKPT指令

 

一 数据处理指令

(1) MOV  数据传送指令:

mov r0 , #0x04        @r0 = 0x04

mov r0, r1                @r0 = r1

mov r0, r1, lsl#3       @r0 = r1<<3

(2)MVN  数据取反传送指令

mvn r0, #1             @r0 = ~1

mvn r0, r1              @r0 = ~r1

(3)CMP  比较指令

cmp r0, r1       等价于 sub r2, r0, r1 (r2 = r0 - r1), 并根据结果设置CPSR的标志位

常常跟以下指令一起使用:

bne a1      @r0 != r1(即Z位为0时),跳转到a1
beq a2      @r0 == r1(即Z位为1时),跳转到a2

(4)CMN  反值比较指令

cmn r0, r1     等价于 add r0, r1,并根据结果设置CPSR的标志位

(5)TST  位测试指令

用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。当前运算结果为1,则Z=0;当前运算结果为0,则Z=1

bne: 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处  

beq: 数据跳转指令,标志寄存器中Z标志位等于零时, 跳转到BEQ后标签处

tst r0, #1      @测试r0中的bit_0位是否为1, 即进行逻辑与运算 r0&1  

beq  a1        @如果bit_0位为1,则执行a1标签的代码

(6)TEQ  相等测试指令

teq r0, r1

(7)ADD  加法指令

ADD R0, R1, R2 ; R0 = R1 + R2

ADD R0, R1, #256 ; R0 = R1 + 256

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

ADDS 是32位数的加法运算, 影响进位标志位C而不影响运算结果的值

(8)ADC  带进位加法指令

用adc指令实现64位的加法运算

基本思路:

r0和r2 分别代表高位

r1和r3分别代表低位

即高位与高位运算r0 = r0 + r2

即低位与低位运算r1 = r1 + r3

实现代码:

mov r0, #1

mov r1, #0xffffffff

mov r2, #1

mov r3, #0x2 

adds r1, r1, r3    ;r1+r3溢出 adds进位 c标志位置1

adc r0, r0, r2     ;高位相加,因为adc是带进位的加 所以高位r0 = r0 + r2 运算结果再加 1(进位的1),即r0 = r0 + r2 + 1

(9)SUB  减法指令

SUB R0, R1, R2                    ; R0 = R1 - R2  

SUB R0, R1, #256                 ; R0 = R1 - 256  

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

SUB R1, R0                           ;R1 -= R0

(10)SBC  带借位减法指令

 SBC带进位减法指令,即除了加两个数以外,还要把CPSR的C值也要带进来,类似ADC

 以下是做64Bit的减法

SUBS R0, R1, R2                  ;R0=R1-R2,SUBS中S表示把进位结果写入CPSR

SBC  R5, R3, R4                    ;R5=R3-R4-C

(11)RSB  逆向减法指令

RSB{条件}{S} 目的寄存器,操作数1,操作数2

RSB指令称为逆向减法指令,用于把操作数2减去操作数1,并将结果存放到目的寄存器中。

rsb r0, r1, r2                       ;r0 = r2 - r1

rsb r0, r1, #123                  ;r0 = 123 - r1

(12)RSC  带借位的逆向减法指令

和SBC类似

(13) AND  按位与指令

 AND{条件}{S} 目的寄存器,操作数1,操作数2

and r0, r0, #3                      ;r0 = r0&0x3

(14)ORR 按位或指令

ORR{条件}{S} 目的寄存器,操作数1,操作数2

orr r0, r0, #3                       ;r0 = r0|0x3

(15)EOR  按位异或指令

EOR{条件}{S} 目的寄存器,操作数1,操作数2

eor r0, r0, #3                     ;r0 = r0^0x3

(16)BIC  位清除指令

BIC 是 逻辑”与非” 指令, 实现的 Bit Clear的功能

BIC     R0,   R0  , #0xF0000000 @将 R0  高4位清零

(17)移位指令

操作数可以是通用寄 存器,也可以是立即数(0~31)。

   —  LSL  逻辑左移

          通用寄存器,LSL  操作数  

          LSL可完成对通用寄存器中的内容进行左移的操作,按操作数所指定的数量向左移位,右端用零来填充。

          MOV   R0,  R1,  LSL#2             @ R0 = R1<<2  

   —  ASL  算术左移

          同LSL

   —  LSR  逻辑右移

         通用寄存器,LSR  操作数

          LSR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用零来填充。

          MOV   R0,  R1,  LSR#2             @ R0 = R1>>2  

   —  ASR  算术右移  

        通用寄存器,ASR 操作数 

        ASR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用第31位的值来填充

         MOV   R0,  R1,  ASR#2

   —  ROR  循环右移

        通用寄存器,ROR 操作数 

        ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充

        MOV   R0,  R1,  ROR#2

   —  RRX  带扩展的循环右移

        通用寄存器,RRX 操作数 

        RRX可完成对通用寄存器中的内容进行带扩展的循环右移的操作,按操作数所指定的数量向右循环移位,左端用进位标志位         C来填充。

(18)数据交换指令

——SWP指令

        SWP{条件} 目的寄存器,源寄存器1,[源寄存器2]

SWP指令用于将源寄存器2所指向的存储器中的字数据传送到目的寄存器中,同时将源寄存器1中的字数据传送到源寄存器2所指向的存储器中。显然,当源寄存 器1和目的寄存器为同一个寄存器时,指令交换该寄存器和存储器的内容。

SWP R0, R1, [R2]          @将R2所指向的存储器中的数据传送给R0, 同时将R1寄存器中的字数据传送给R2指向的存储单元

SWP R0, R0, [R2]          @R0与R2的数据交换

——SWPB指令

  SWP{条件}B 目的寄存器,源寄存器1,[源寄存器2]

SWPB指令用于将源寄存器2所指向的存储器中的字节数据传送到目的寄存器中,目的寄存器的高24清零,

同时将源寄存 器1中的字节数据传送到源寄存器2所指向的存储器中。显然,当源寄存器1和目的寄存器为同一个寄存器时,

指令交换该寄存器和存储器的内容。

(19)乘法与乘加指令

      ARM 微处理器支持的乘法指令与乘加指令共有6条,可分为运算结果为32位和运算结果为64位两类。与前面的数据处理指令不同,指令中的所有操作数、目的寄存器 必须为通用寄存器,不能对操作数使用立即数或被移位的寄存器,同时,目的寄存器和操作数1必须是不同的寄存器。

——MUL相乘

       MUL{条件}{S} 目的寄存器,操作数1,操作数2

MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,

同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操 作数2均为32位的有符号数或无符号数。

MUL R0, R1, R2                    @R0 = R1 * R2

MULS R0, R1, R2                  @R0 = R1 * R2   同时设置CPSR中的相关标志位

——MLA带累加的相乘 

       MLA{条件}{S} 目的寄存器,操作数1,操作数2,操作数3

MLA指令完成将操作数1与操作数2的乘法运算,再将乘积加上操作数3,并把结果放置到目的寄存器中,

同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数或无符号数

MLA  R0, R1, R2, R3              @R0 = R1*R2+R3

MLAS R0, R1, R2, R3             @R0=R1*R2+R3  同时设置CPSR中的相关标志位

——SMULL指令

      SMULL{条件}{S}   目的寄存器Low,目的寄存器High,操作数1,操作数2

SMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,

结果的高32位放置到目的寄存器High中,同时可以 根据运算结果设置CPSR中相应的条件标志位。

其中,操作数1和操作数2均为32位的有符号数

SMULL R0, R1, R2, R3             @R0 等于 R2*R3底32位值,  R1等于R2*R3高32位值,  

——SMLAL指令

       SMLAL{条件}{S}   目的寄存器Low,目的寄存器High,操作数1,操作数2

SMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位同目的寄存器Low中的值相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。

其中,操作数1和操作数2均为32位的有符号数

对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位;

对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。

SMLAL R0, R1, R2, R3        @R0 = R2*R3的低32位数 + R0,   R1 = R2*R3的高32位数 + R1

——UMULL指令

         UMULL{条件}{S}   目的寄存器Low,目的寄存器High,操作数1,操作数2

UMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,

结果的高32位放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。

其中,操作数1和操作数2均为32位的无符号数

UMULL R0, R1, R2, R3             @R0 等于 R2*R3底32位值,  R1等于R2*R3高32位值,  

——UMLAL指令

        UMLAL{条件}{S}   目的寄存器Low,目的寄存器High,操作数1,操作数2

UMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位同目的寄存器Low中的值相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的无符号数

对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位;

对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。

SMLAL R0, R1, R2, R3        @R0 = R2*R3的低32位数 + R0,   R1 = R2*R3的高32位数 + R1

二 加载存储指令

   —  LDR  字数据加载指令  

   —  LDRB  字节数据加载指令  

   —  LDRH  半字数据加载指令  

   —  STR  字数据存储指令  

   —  STRB  字节数据存储指令  

   —  STRH  半字数据存储指令

(1)LDR  字数据加载指令  

(注意:加一个[]表示一个内存地址)

ldr r0, =0x12345678            @把0x12345678这个地址写到r0中

ldr r0, [r1]                             @把r1这个地址数据写到r0中,[ ]代表这是一个内存的地址

ldr r0, [r1, #8]                       @将地址r1 + 8的字数据读入以r0存储器中

ldr r0, [r1], #8                       @将r1的数据读入到r0,并将r1 + 8的值存入r1

(2)STR  字数据存储指令

str r0, [r1, #8]                       @将r1中的字数据读入以r1 + 8为地址的存储器中

str r0, [r1], #8                       @ 将r0的字数据读入r1,并将r1 + 8的值存入r1

(3)批量数据加载/存储指令

1)—LDM

2)—STM

LDM批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,STM批量数据存储指令则完成相反的操作。

LDM(或 STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈(STM)或出栈(LDM)

指令格式为: LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}

{类型} 为 以下几种情况:

IA    每次传送后地址加1;

IB      每次传送前地址加1;

DA   每次传送后地址减1;

DB   每次传送前地址减1;

FD   满递减堆栈;

ED   空递减堆栈;

FA   满递增堆栈;

EA   空递增堆栈;

{!}为可选后缀,若选用该后缀,则当数据 传送完毕之后,将最后的地址写入基址寄存器,

否则基址寄存器的内容不改变。基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。

{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,

还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。

uboot中重定位代码的实例:

relocate_to_text:
	/*
	 * relocate u-boot code on memory to text base
	 * for nexell arm core (add by jhkim)
	 */
	adr	r0, _stext				/* r0 <- current position of code   */
	ldr	r1, TEXT_BASE			/* test if we run from flash or RAM */
	cmp r0, r1              	/* don't reloc during debug         */
	beq clear_bss

	ldr	r2, _bss_start_ofs
	add	r2, r0, r2				/* r2 <- source end address         */

copy_loop_text:
	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */
	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
	cmp	r0, r2					/* until source end addreee [r2]    */
	ble	copy_loop_text         //若r0 <= r2  则执行

三 跳转指令

实现指令跳转的方式有两种

  使用专门的跳转指令跳转

          分支指令 B

          带链接的分支指令: BL

          带状态切换的分支指令 BX

 使用程序计数器PC

           直接向程序计数器PC写入跳转地址值,通过向程序计数器PC写入跳转地址值

    可以实现在程序地址空间中的任意跳转,在跳转之前结合使用MOV LR,PC等类似指令

    可以保存将来的返回地址值,从而实现在连续的线性地址空间的子程序调用

1. B指令

     B{条件} 目标地址

B  label           @跳转到label标签后面的代码执行

CMP R0, R1   

BEQ  label      @当R0=R1时,程序跳转到label处执行

2. BL指令

    BL{条件} 目标地址

BL是另一个跳转指令,但跳转之前,会在寄存器R14(LR)中保存PC的当前内容,

因此,可以通过将R14的内容重新加载到PC中,来返回到跳转指令之后的那个 指令处执行。

该指令是实现子程序调用的一个基本但常用的手段

            BEQ    相等
            BNE    不等
            BPL    非负
            BMI    负
            BCC    无进位
            BCS    有进位
            BLO    小于(无符号数)
            BHS    大于等于(无符号数)
            BHI    大于(无符号数)
            BLS    小于等于(无符号数)
            BVC    无溢出(有符号数)
            BVS    有溢出(有符号数)
            BGT    大于(有符号数)
            BGE    大于等于(有符号数)
            BLT    小于(有符号数)
            BLE    小于等于(有符号数)


3. BLX指令

    BLX 目标地址

BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM状态切换到Thumb状态,

该指令同时将PC的当前内容保存到寄存器R14中。因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,

可以通过BLX指令实现子程序的调用和处理器工作状态的切换。同时,子程序的返回可以通过将寄存器R14值复制到PC中来完成

4. BX指令

    BX{条件} 目标地址

BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。

四 程序状态寄存器访问指令

(1)MRS指令

   MRS{条件}    通用寄存器   程序状态寄存器(CPSR或SPSR)

MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以下两种情况:

Ⅰ.当需要改变程序状态寄存器的内容时,可用MRS将程序状态寄存器的内容读入通用寄存器,修改后再写回程序状态寄存器。

Ⅱ.当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存

MRS R0, CPSR             @将CPSR的内容读到R0

MRS R0, SPSR             @将SPSR的内容读到R0 

(2)MSR指令

      MSR{条件}    程序状态寄存器(CPSR或SPSR)_<域>,操作数

MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。

<域>用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器可分为4个域:

位[31:24]为条件位域,用f表示;

位[23:16]为状态位域,用s表示;

位[15:8] 为扩展位域,用x表示;

位[7:0]    为控制位域,用c表示;

该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将要操作的域。

     MSR CPSR, R0         @将R0的内容读到CPSR

     MSR SPSR, R0          @将R0的内容读到SPSR

     MSR CPSR_C, R0      @讲R0的内容读到CPSR,但仅仅修改CPSR中的控制位域

五 协处理器指令

(1)CDP指令

      CDP{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2

CDP指令用于ARM处理器通知ARM协处理器执行特定的操作,若协处理器不能成功完成特定的操作,

则产生未定义指令异常。其中协处理器操作码1和协处理 器操作码2为协处理器将要执行的操作,

目的寄存器和源寄存器均为协处理器的寄存器,指令不涉及ARM处理器的寄存器和存储器。

CDP P3, 2, C12, C10, C3, 4          @该指令完成协处理器P3的初始化

(2)LDC指令

      LDC{条件}{L} 协处理器编码,目的寄存器,[源寄存器]

LDC指令用于将源寄存器所指向的存储器中的字数据传送到目的寄存器中,若协处理器不能成功完成传送操作,

则产生未定义指令异常。其中,{L}选项表示指 令为长读取操作,如用于双精度数据的传输

LDC  P3, C4, [R0]        @将ARM处理器的寄存器R0所指向的存储器中的字数据传送到协处理器P3的寄存器C4中

(3)STC指令

      STC{条件}{L} 协处理器编码,源寄存器,[目的寄存器]

STC指令用于将源寄存器中的字数据传送到目的寄存器所指向的存储器中,若协处理器不能成功完成传送操作,则产生未定义指令异常。

其中,{L}选项表示指 令为长读取操作,如用于双精度数据的传输

    STC P3, C4, [R0]         @将协处理器P3的寄存器C4中的字 数据传送到ARM处理器的寄存器R0所指向的存储器中

(4)MCR指令

    MCR{条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2

MCR指令用于将ARM处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,

则产生未定义指令异常。其中协处理器操作码1和协处理 器操作码2为协处理器将要执行的操作,

源寄存器为ARM处理器的寄存器,目的寄存器1和目的寄存器2均为协处理器的寄 存器

    MCR P3, 3, R0, C4, C5, 6      @将ARM处理器寄存器R0中的数据传送到协处理器P3的寄存器C4和C5中

(5)MRC指令

     MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2

MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,

则产生未定义指令异常。其中协处理器操作码1和协处理 器操作码2为协处理器将要执行的操作,

目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。

MRC P3, 3, R0, C4, C5, 6              @将协处理器P3的寄存器中的数据传送到ARM处理器寄存器中

六 异常产生指令

(1)SWI指令

       SWI{条件} 24位的立即数

SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在SWI的异常处理程序中提供相应的系统服务,

指令中24位的立即数指定用 户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中24位的立即数被忽略时,

用户程序调用系统例程的类型由通用寄存器R0的内容决定,同 时,参数通过其他通用寄存器传递

      SWI  0x02        @调用操作系统编号位02的系统例程

(2)BKPT指令

     BKPT   16位的立即数

 BKPT指令产生软件断点中断,可用于程序的调试

 

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值