文章目录
- 前言
- 一、MOV指令
- 二、内存访问指令
- 1.LDR指令
- 2.STR指令
- 三、数据处理指令
- 1.ADD指令
- 2.SUB指令
- 3.位操作指令
- 4.CMP指令
- 四、跳转指令
- 总结
前言
本篇文章带大家来学习ARM汇编的一些常用的指令,这里指令都是非常基础的指令。
一、MOV指令
MOV(Move)指令是在ARM架构中用于将数据从一个位置或寄存器复制到另一个位置或寄存器的指令。
在ARM汇编语言中,MOV指令的基本语法格式如下:
MOV{cond}{S} Rd, Operand2
其中:
{cond}是条件码,可选项。用于指定条件执行MOV指令的条件。
{S}是标志位,可选项。用于指定是否更新标志寄存器。
Rd是目标寄存器,用于存储要加载的数据。
Operand2是操作数,即要移动到目标寄存器的值。它可以是另一个寄存器、立即数或寄存器的移位操作。
下面是一些MOV指令的示例:
1.将立即数移动到寄存器:
MOV R0, #42 ; 将立即数42移动到寄存器R0
2.MOV R0, #42 ; 将立即数42移动到寄存器R0
MOV R1, R0 ; 将寄存器R0的值复制到寄存器R1
3.将一个寄存器的值与立即数进行逻辑或运算后,将结果存储到另一个寄存器:
MOV R2, R0 OR #0x18 ; 将寄存器R0的值与立即数0x18进行逻辑或运算后,将结果存储到寄存器R2
4.将一个寄存器的值进行左移,并将结果存储到另一个寄存器:
MOV R3, R0, LSL #4 ; 将寄存器R0的值左移4位,并将结果存储到寄存器R3
MOV指令可以在不同的操作数之间进行数据传输和操作。它在程序中经常用于加载常数、复制寄存器值、进行逻辑运算等操作。
需要注意的是,ARM架构中的一些条件码(cond)和标志位(S)可以用于指定MOV指令的执行条件和是否更新标志寄存器。条件执行可根据先前的条件(例如,相等、大于等于等)决定是否执行指令,而更新标志位可将结果写入条件寄存器,以便进一步的条件执行。
总结起来,MOV指令是在ARM汇编语言中用于将数据从一个位置或寄存器复制到另一个位置或寄存器的指令。它可以用于加载立即数、复制寄存器值、进行逻辑运算等操作。指令的使用可以通过条件码和标志位进行条件执行和标志位更新。
在模拟器中运行:
二、内存访问指令
1.LDR指令
LDR指令:
LDR指令用于从内存中加载数据到寄存器。它的基本语法为:
LDR{cond}{B}{T} Rd, [Rn{, #offset}]
其中:
{cond}是条件码,可选项。用于指定条件执行LDR指令的条件。
{B}是字节访问标志,可选项。用于指定是否进行字节级别的加载。
{T}是类型标志,可选项。用于指定加载的数据类型,例如字、半字或字节。
Rd是目标寄存器,用于存储从内存中加载的数据。
Rn是基地址寄存器,其中存储了要加载数据的内存地址。
#offset是可选的偏移量,用于指定基地址寄存器Rn与实际数据的偏移量。
LDR指令可以加载整数、浮点数、字符等类型的数据。
2.STR指令
STR指令:
STR指令用于将数据从寄存器存储到内存。它的基本语法为:
STR{cond}{B}{T} Rd, [Rn{, #offset}]
其中:
{cond}是条件码,可选项。用于指定条件执行STR指令的条件。
{B}是字节访问标志,可选项。用于指定是否进行字节级别的存储。
{T}是类型标志,可选项。用于指定存储的数据类型。
Rd是源寄存器,其中存储了要存储到内存的数据。
Rn是基地址寄存器,其中存储了要存储数据的内存地址。
#offset是可选的偏移量,用于指定基地址寄存器Rn与实际数据的偏移量。
STR指令将寄存器中的数据存储到内存中的指定位置。
示例用法:
1.使用LDR指令加载一个字(4个字节)到寄存器R1中:
LDR R1, [R0] ; 将内存地址存储在R0中的字加载到寄存器R1
2.使用STR指令将寄存器R2中的值存储为一个字(4个字节)到内存地址存储在R0中的位置:
STR R2, [R0] ; 将寄存器R2的值存储为一个字到内存地址存储在R0中的位置
除了基本格式之外,LDR和STR指令还可通过偏移量和寄存器间接寻址来加载和存储数据。此外,有许多变体指令可用于处理特定类型和大小的数据。
总结:LDR指令用于从内存中加载数据到寄存器,而STR指令用于将数据从寄存器存储到内存。它们可以加载和存储不同类型和大小的数据,并支持偏移量和寄存器间接寻址。这些指令在ARM汇编语言中被广泛使用,用于处理数据的读取和写入操作。
演示:
三、数据处理指令
1.ADD指令
ADD指令是一种在计算机指令集中常见的算术指令,用于执行两个操作数的相加操作。它可以用于整数、浮点数等各种数据类型的加法运算。
在典型的计算机体系结构中,ADD指令通常有以下格式:
ADD 目标操作数,源操作数
其中,目标操作数是要进行相加运算并将结果存储的位置,源操作数是要相加的值。具体的操作数可以是寄存器、内存地址或立即数。
执行ADD指令时,计算机会将源操作数中的值(或者是地址对应的值)与目标操作数中的值相加,并将结果存储到目标操作数的位置。这个过程可以描述为:目标操作数 = 目标操作数 + 源操作数。
下面是一个示例,展示了使用ADD指令进行加法运算的过程:
MOV R1, 5 ; 将寄存器R1设置为5
MOV R2, 3 ; 将寄存器R2设置为3
ADD R1, R2 ; R1 = R1 + R2
; 在执行完ADD指令后,寄存器R1的值变为8
在这个例子中,我们首先将寄存器R1设置为5,寄存器R2设置为3。然后使用ADD指令将寄存器R1和寄存器R2的值相加,并将结果存储回寄存器R1。最终,寄存器R1的值变为8,即5 + 3的结果。
2.SUB指令
UB指令是计算机指令集中的一种算术指令,用于执行两个操作数的减法操作。它可以用于整数、浮点数等各种数据类型的减法运算。
在典型的计算机体系结构中,SUB指令通常具有以下格式:
SUB 目标操作数,源操作数
其中,目标操作数是要进行减法运算并将结果存储的位置,源操作数是要减去的值。具体的操作数可以是寄存器、内存地址或立即数。
执行SUB指令时,计算机会将源操作数中的值(或者是地址对应的值)从目标操作数中的值中减去,并将结果存储到目标操作数的位置。这个过程可以描述为:目标操作数 = 目标操作数 - 源操作数。
以下是一个示例,展示了使用SUB指令进行减法运算的过程:
MOV R1, 10 ; 将寄存器R1设置为10
MOV R2, 5 ; 将寄存器R2设置为5
SUB R1, R2 ; R1 = R1 - R2
; 在执行完SUB指令后,寄存器R1的值变为5
在这个例子中,我们首先将寄存器R1设置为10,寄存器R2设置为5。然后使用SUB指令,将寄存器R2的值从寄存器R1的值中减去,并将结果存储回寄存器R1。最终,寄存器R1的值变为5,即10 - 5的结果。
3.位操作指令
位操作指令是计算机指令集中用于对数据进行逐位操作的指令。其中,AND(与)、ORR(或)和BIC(位清除)是常见的位操作指令,用于实现逻辑操作和修改特定位的功能。
AND指令(与指令)用于执行逻辑与操作。它按位比较两个操作数,并在结果中设置对应位置的位,如果两个操作数的对应位都为1。具体操作可以表示为:目标操作数 = 操作数1 AND 操作数2。这个指令可以用于清除某些位上的值或进行位屏蔽操作。
例如,对于以下示例:
MOV R1, 0x0F ; 将寄存器R1设置为0x0F,二进制为 00001111
MOV R2, 0x03 ; 将寄存器R2设置为0x03,二进制为 00000011
AND R3, R1, R2 ; R3 = R1 AND R2
; 执行完AND指令后,寄存器R3的值为0x03,二进制为 00000011
在这个示例中,AND指令将寄存器R1和R2的值逐位进行与操作,并将结果存储在寄存器R3中。结果为0x03,即二进制的 00000011,对应于两个操作数的共同为1的位。
ORR指令(或指令)用于执行逻辑或操作。它按位比较两个操作数,并在结果中设置对应位置的位,如果两个操作数的对应位中至少有一个为1。具体操作可以表示为:目标操作数 = 操作数1 ORR 操作数2。这个指令可用于设置特定位的值或进行位屏蔽操作。
例如,对于以下示例:
MOV R1, 0x0A ; 将寄存器R1设置为0x0A,二进制为 00001010
MOV R2, 0x03 ; 将寄存器R2设置为0x03,二进制为 00000011
ORR R3, R1, R2 ; R3 = R1 ORR R2
; 执行完ORR指令后,寄存器R3的值为0x0B,二进制为 00001011
在这个示例中,ORR指令将寄存器R1和R2的值逐位进行或操作,并将结果存储在寄存器R3中。结果为0x0B,即二进制的 00001011,对应于两个操作数中至少有一个为1的位。
BIC指令(位清除指令)用于修改目标操作数中特定位的值。它按位比较目标操作数和指定操作数,并将目标操作数的对应位清除(置为0)。具体操作可以表示为:目标操作数 = 目标操作数 BIC 指定操作数。
例如,对于以下示例:
MOV R1, 0x0F ; 将寄存器R1设置为0x0F,二进制为 00001111
MOV R2, 0x0C ; 将寄存器R2设置为0x0C,二进制为 00001100
BIC R3, R1, R2 ; R3 = R1 BIC R2
; 执行完BIC指令后,寄存器R3的值为0x03,二进制为 00000011
在这个示例中,BIC指令将寄存器R1和R2的值逐位进行位清除操作,并将结果存储在寄存器R3中。结果为0x03,即二进制的 00000011,对应于目标操作数中通过指定操作数清除的位。
总结来说,AND、ORR和BIC指令是常用的位操作指令,用于执行逻辑与、逻辑或和位清除操作。它们可以用于逐位处理数据,并在逻辑运算和位操作中发挥重要作用。
4.CMP指令
CMP指令是计算机指令集中的一种比较指令,用于比较两个操作数的大小关系或相等性,并根据比较结果设置或更新条件码寄存器(或程序状态字)的标志位。
在典型的计算机体系结构中,CMP指令通常有以下格式:
CMP 操作数1,操作数2
其中,操作数1和操作数2是要进行比较的值,可以是寄存器、内存地址或立即数。
执行CMP指令时,计算机会计算操作数1与操作数2之间的差值,并更新条件码寄存器中的标志位。常见的标志位包括零标志位(Z),负标志位(N),进位标志位(C)和溢出标志位(V)。
常见的比较结果及标志位设置如下:
如果操作数1等于操作数2,则设置零标志位(Z)为1,表示两个操作数相等。
如果操作数1小于操作数2,则设置负标志位(N)为1,表示操作数1为负值。
如果操作数1大于操作数2,则清除负标志位(N)为0,表示操作数1为正值。
如果操作数1小于操作数2,则设置进位标志位(C)为1。
CMP指令经常与条件跳转指令(例如BEQ、BNE、BLT等)配合使用,用于根据比较结果决定程序的执行路径。
以下是一个示例,展示了使用CMP指令进行比较的过程:
MOV R1, 5 ; 将寄存器R1设置为5
MOV R2, 3 ; 将寄存器R2设置为3
CMP R1, R2 ; 比较 R1 和 R2
; 在执行完CMP指令后,根据比较结果,条件码寄存器的标志位可能会更新
在这个示例中,我们首先将寄存器R1设置为5,寄存器R2设置为3。然后使用CMP指令进行比较,比较R1和R2的值。根据比较结果,条件码寄存器的标志位可能会被更新。
需要注意的是,CMP指令只用于比较操作,它不会修改任何操作数的值,只更新标志位。程序可以根据标志位的值执行条件分支或其他操作。
四、跳转指令
1.B(Branch)指令:
B指令是一种无条件跳转指令。它允许程序直接跳转到指定的目标地址执行代码。B指令使用的目标地址可以是一个立即数(即直接指定的跳转地址)或者一个寄存器中存储的地址。B指令不会将任何返回地址保存在寄存器中,因此它是一种非长跳转的指令。
loop:
... ; 一些代码
B loop ; 无条件跳转到loop标签处
2.BL(Branch with Link)指令:
BL指令也是一种跳转指令,但它在跳转之前会将当前的返回地址保存在链接寄存器(通常是LR)中。这使得BL指令可以用于实现函数调用或子程序的跳转。在跳转执行完后,在返回到调用者时,可以使用之前保存的返回地址来继续执行。
function:
... ; 函数的代码
BX LR ; 返回到调用函数的地址
main:
BL function ; 调用function函数
... ; 继续执行其他代码
3.BLX(Branch with Link and Exchange)指令:
BLX指令是一种特殊的跳转指令,它可以在跳转过程中切换处理器的执行状态。它可以从ARM指令集(32位)切换到Thumb指令集(16位),或者从Thumb切换回ARM。BLX指令一般用于访问和执行不同指令集下的库函数或子程序。
thumb_function:
... ; Thumb指令集下的函数代码
BX LR ; 返回到调用函数的地址
arm_function:
... ; ARM指令集下的函数代码
BX LR ; 返回到调用函数的地址
main:
BLX thumb_function ; 使用BLX指令调用Thumb指令集下的函数
... ; 继续执行其他代码
BLX arm_function ; 使用BLX指令调用ARM指令集下的函数
4.BX(Branch and Exchange)指令:
BX指令用于无条件跳转,并且允许在跳转过程中切换处理器执行状态。类似于BLX指令,BX指令可以从ARM指令集(32位)切换到Thumb指令集(16位),或者从Thumb切换回ARM。与BLX指令不同的是,BX指令不会将返回地址保存在链接寄存器中。
thumb_function:
... ; Thumb指令集下的函数代码
BX LR ; 返回到调用函数的地址
main:
BX thumb_function ; 使用BX指令跳转到Thumb指令集下的函数
... ; 继续执行其他代码
总结
本篇文章讲解了一些基础的汇编指令,掌握了这些基础的汇编指令后我们就有能力去看懂一些汇编代码了,这对于我们了解ARM架构有非常重要的作用。