当前位置:   article > 正文

Arm汇编指令学习

push{r4-r7}

ARM指令格式

ARM指令格式解析

opcode: 指令助记符,例如,MOV ,ADD,SUB等等

cond:指令条件码表.下面附一张图

{S}:是否影响CPSR的值.

{.W .N}:指令宽度说明符,无论是ARM代码还是Thumb(armv6t2或更高版本)代码都可以在其中使用.W宽度说明符,但它对32位的代码没有影响。如果要将指令汇编为16位编码,则可以为指令加上.N宽度说明符。

Rd:目的寄存器.

Rn:第一个操作数寄存器.

operand2:第二个操作数,第二个操作数可以是寄存器,立即数,或者是寄存器移位操作.

跳转指令

B指令

B {cond} lable

B指令执行时,如果条件满足,就直接跳转到label指定的地址继续执行.

例如:BNE 就是not equal z=0时候,跳转到label执行

BL指令

B {cond} lable

BL是指带链接的跳转指令,如果条件cond满足,会将当前指令的下一条指令的地址copy到R14(LR)寄存器中,然后跳转到lable指定的地址继续执行,这条指令通常作用于子程序,在子程序的尾部 执行MOV PC,LR 就可以返回到主程序中,继续执行下一条指令。

BX指令

BX{cond}Rm

就是跳转时候判断是用arm代码还是Thumb代码执行

存储器访问指令

存储器访问操作包括从存储器中加载数据、或者存数据到存储器、再或者是存储器与寄存器之间的数据交换.

LDR指令

LDR用于从存储器中加载数据到寄存器中格式

LDR{type}{cond}Rd,lable

LDRD{cond}Rd,Rd2,lable

type指明了操作数据的大小,他的取值

cond:仍为执行条件和上面的一样

Rd:是要加载的寄存器

lable:Lable 为要读取的内存地址 有三种表示方法

直接偏移量

如: LDR R8, [R9, #04] 、LDR R8, [R9], #04

寄存器偏移

如: 直 接 偏 移 量。 如: LDR R8, [R9, #04] 、LDR R8, [R9], #04

相对PC偏移

如: LDR R8, label1

STR指令

STR用于存储内容到指定的内存地址中

STR{ type}{ cond} Rd, label

STRD{ cond} Rd, Rd2, label

指令格式基本和LDR相同,只是type中的SB与SH对STR无效。

指令举例:STR R0,[R2,#04] 将R0寄存器的数据,存储到R2+4所指向的存储单元中去

LDM指令

LDM可以从指定的存储单元加载多个数据到一个寄存器列表,他的格式如下:

LDM{ addr_mode}{ cond} Rn{!} reglist

addr_mode的取值

Rn:基地址寄存器,用于存储初始地址

!:为可选后缀.如果有! 那么最终地址将写回到Rn寄存器

reglist:寄存器列表,用大括号括起来,多个连续的寄存器使用'-'连接,如{R0-R3}如果寄存器不是连续的,则使用逗号将他们分隔开来,如{R0,R1,R7}

指令举例:LDM R0! {R1-R3} 依次加载R0指向的存储单元的数据,到R1,R2,R3寄存器中

STM指令

STM指令将一个寄存器列表的数据存储到指定的存储单元。它的格式如下:

STM{addr_mode}{cond}Rn{!} reglist

STM与LDM的格式是一样的,STM指令:

STM R1!,{R3-R6,R11} 将R3-R6 R11 寄存器存储的内容存到R1所指向的存储单元中

STM SP!,{R3-R7}

PUSH指令

PUSH将寄存器推入满递减堆栈,它的格式如下

PUSH{cond} reglist

指令举例:PUSH {r0,r4-r7} 将R0,R4-R7寄存器内容压入堆栈

POP指令

POP从满递减堆栈中弹出数据到寄存器

POP{cond} reglist

POP {r0,r4-r7} 将R0,R4,R5,R6,R7从堆栈中弹出

SWP指令

SWP用于寄存器与存储器之间的数据交换,他的格式如下

SWP {B}{cond}Rd,Rm,[Rn]

B:是可选的字节,若有B,则交换字节,否则交换32位的字。

cond:和前面一样是条件

Rd:为要从存储器中加载数据的寄存器 存储器->寄存器

Rm:为要从寄存器加载数据到存储器的寄存器 寄存器->存储器

Rn:为需要进行数据交换的存储器地址。Rn不能与Rd和Rm相同

如果Rd与Rm相同,可实现单个寄存器与存储器的数据交换。例如:

SWP R1,R1,[R0] 将R1寄存器与R0寄存器指向的存储单元中的内容进行交换

SWP R1,R2,[R0] 将R0寄存器指向的存储单元的内容取出,存入R1寄存器,再将R2寄存器存储的内容存储到R0寄存器所指向的内存单元

数据处理指令

数据指令主要用于寄存器之间的数据传送

MOV指令

MOV的功能是将8位立即数或者寄存器的内容传送到目标寄存器,指令格式如下

MOV{cond}{S}Rd,operand2

MOV指令举例

MOV,RO,#8 == R0 = 8

MOV,RO,R1 == R0 = R1

MVN指令

MVN为数据非传送指令,它的功能是将8位的立即数或寄存器按位取反后,传送到目标寄存器中。指令格式如下:

MVN{cond}{S}Rd,operand2

MVN R0,#0xFF == R0=0xFFFFFF00

算数运算指令

ADD指令

ADD为加法指令

指令格式: ADD{cond}{S}Rd,Rn,operand2

指令举例:

ADD R0,R1,#2 R0 = R1+@

ADDS R0,R1,R2 R0 = R1+R2 影响标志位

ADD R0,R1,LSL #3 R0 = R1 * 8

ADC指令

指令格式: ADC{cond}{S}Rd,Rn,operand2

ADC为带进位的加法指令,他的功能是将Rn,operand2的值相加,然后再加上CPSR寄存器的C条件标志位的值,最后将结果保存到Rd寄存器.

指令举例: ADD R0,R0,R2 ADC R1,R1,R3

SUB指令

指令格式: SUB{cond}{S}Rd,rn,operand2

SUB为减法指令,他的功能是将Rn与operand2的值

指令举例:

SUB RO,R1,#4 R0 = R1-4

同理带S的影响标志位

RSB

指令格式:RSB{cond}{S}Rd,Rn,operand2

RSB是逆向减法指令,就是说用operand2 - Rn 然后赋值给Rd

指令举例

RSB R0,R1 #0X1234

逻辑运算

逻辑运算指令主要完成与、或、异或、移位等逻辑运算操作

AND指令

逻辑 "与" 指令

指令格式:AND{cond}{S}Rd,Rn,operand2

指令举例:AND RO,R0,#1 用来测试R0的最低位

ORR指令

逻辑 "或" 指令

指令格式: ORR{cond}{S}Rd,Rn,operand2

指令举例:ORR R0,RO,#0X0F 指令执行后保留R0的低四位,其余位清0.

EOR指令

逻辑 "异或" 指令

指令格式:EOR{cond}{S}Rd,Rn,operand2

指令举例:EOR R0,R0,R0 执行后R0 为 0

ORN指令

逻辑“或非”指令 先将操作数取反,再与目标寄存器进行或操作

指令格式:ORN指令{cond}{S}Rd,Rn,operand2 指令举例:EOR R0,R0,#0x0F

BIC指令

位清除指令

指令格式:BIC{cond}{S}Rd,Rn,operand2

功能是将operand2的值取反,然后将结果与Rn寄存器的值相 "与" 并保存到Rd寄存器中

指令举例:BIC R0,R0,#0X0F 将R0第四位清0,其余位保持不变

比较指令

CMP指令

指令格式: CMP{cond}Rn,operand2

CMP指令使用Rn寄存器减去operand2的值,这与SUBS指令功能相同,但CMP指令不保存计算结果,仅仅根据比较重置标志位.

4月8日更新:它影响的标志位包括CF,SF,ZF,OF,AF,PF

CF : 进位标志

PF : 奇偶标志

AF : 辅助进位标识

ZF : 0标识

SF : 符号标识

OF : 溢出标识

指令举例:CMP R0,#0 判断R0寄存器的值是否为0

CMN指令

指令格式: CMN{cond}Rn,operand2

CMN指令将operand2的值加到Rn寄存器上,这与ADDS的指令功能相同,不过CMN指令不保存计算结果

CMN指令举例如下:

CMN RO,R1

TST指令

指令格式: TST{cond}Rn,operand2

TST为测试指令,它的功能是将Rn寄存器中的内容与operand2的值进行 “与” 运算,这与ANDS指令功能相同,但TST指令不保存计算结果,仅仅根据计算结果设置标志位。

指令举例:

TEQ R0,#1 判断R0寄存器最低位是否为1

TEQ指令

指令格式: TEQ {cond}Rn,operand2

TEQ的功能是将Rn寄存器的值和operand2的值进行 “异或” 运算,但是TEQ指令不保存计算结果,仅根据计算结果设置标志位.

指令举例: 判断R0寄存器与R1寄存器的值是否相等

移位指令

LSL

逻辑左移,将整个操作数向左移动两位,右边补0,最终操作也就是 * 2^n(移位)

指令举例: LSL R1,R0,#2 将R0向左移动两位,结果保存到R1中. 也就是 R0 * 2^2

LSR

逻辑右移,基本和左移操作差不多,就是整体向右移,左边补0,最终操作也就是 / 2 ^ n(移位)

指令举例: LSR R1,R0,#2 将R0向右移动两位,结果保存到R1中. 也就是 R0 / 2^2

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号