首页
社区
课程
招聘
[原创]Arm指令介绍
发表于: 2021-9-10 14:25 17812

[原创]Arm指令介绍

2021-9-10 14:25
17812

与高级语言相似,ARM支持操作不同类型的数据类型。我们可以load(or stroe)的数据类型有signed and unsigned words、halfwords、or bytes. 这些数据类型的extensions分别是:halfwords是-h or -sh,bytes是-b or -sb,word没有extension. signed and unsinged 数据的区别:
1.signed data type 能储存正数和负数
2.unsigned data type 可以保存大的正值(包括“零”),但不能保存负值。

以下是一些load和store指令的操作指令的一些例子:

查看内存中的字节有两种基本方式:Little-Endian (LE) 或 Big-Endian (BE)。 区别在于对象的每个字节存储在内存中的字节顺序。 在像 Intel x86 这样的小端机器上,最低有效字节存储在最低地址(最接近零的地址)。 在 big-endian 机器上,最高有效字节存储在最低地址。 ARM 体系结构在第 3 版之前是小端的,从那时起它是双端的,这意味着它具有允许可切换的端的设置。 例如,在 ARMv6 上,指令是固定的 little-endian,数据访问可以是 little-endian 或 big-endian,由程序状态寄存器 (CPSR) 的第 9 位(E 位)控制。

寄存器的数量是依赖于ARM的版本的,通过查询ARM Reference Manual,除了基于 ARMv6-M 和 ARMv7-M 的处理器外,都有 30 个通用 32 位寄存器,前 16 个寄存器(r1-r15)可在用户级模式下访问,其他寄存器可在特权软件执行中使用(ARMv6-M 和 ARMv7-M 除外)。

下表只是快速了解 ARM 寄存器如何与 Intel 处理器中的寄存器相关联。

R0-R12:在普通的操作中可以被用作储存临时数据、指针等等。例如,R0 可在算术运算期间称为累加器或用于存储先前调用函数的结果。 R7 在处理系统调用时变得有用,因为它存储系统调用编号,而 R11 帮助我们跟踪用作帧指针的堆栈边界。 此外,ARM 上的函数调用约定指定函数的前四个参数存储在寄存器 r0-r3 中。

R13:SP(Stack Pointer). 这个栈指针指向栈顶,栈是用于特定于函数的存储的内存区域,在函数返回时被回收。 因此,栈指针用于在栈上分配空间,方法是从栈指针中减去我们想要分配的值(以字节为单位)。 换句话说,如果我们想分配一个 32 位的值,我们从栈指针中减去 4。

R14:LR(Link Register). 当一个函数调用被执行了,链接寄存器就会更新为下一条指令的内存地址。止痒允许程序在子函数完成后返回到父函数中接着执行。

R15:PC(Program Counter).程序计数器根据所执行指令的大小自动递增。 此大小在 ARM 状态下始终为 4 个字节,在 THUMB 模式下始终为 2 个字节。 当执行分支指令时,PC 持有目的地址。 在执行过程中,PC 在 ARM 状态下存储当前指令加 8(两条 ARM 指令)的地址,在 Thumb(v1) 状态下存储当前指令加 4(两条 Thumb 指令)的地址。 这与 x86 不同,在 x86 中 PC 总是指向要执行的下一条指令。

源程序如下:

在GDB中我们设置断点_start然后运行

断点的现场状态如下:

单步运行后:

奇妙的事情发生了,查看R0中的地址。 虽然我们希望 R0 包含先前读取的 PC 值 (0x10054),但它保存的是我们先前读取的 PC (0x1005c) 前两条指令的值。 从这个例子可以看出,当我们直接读取PC时,它遵循PC指向下一条指令的定义; 但在调试时,PC 指向当前 PC 值(0x10054 + 8 = 0x1005C)之前的两条指令。 这是因为较旧的 ARM 处理器总是在当前执行的指令之前获取两条指令。 ARM 保留此定义的原因是为了确保与早期处理器的兼容性。

寄存器 $CPSR 显示当前程序状态寄存器 (CPSR) 的值,在其下方您可以看到标志拇指、快速中断、溢出、进位、零和负数。 这些标志代表 CPSR 寄存器中的某些位,根据 CPSR 的值设置,激活时变为1。 N、Z、C 和 V 位与 x86 上 EFLAG 寄存器中的 SF、ZF、CF 和 OF 位相同。 这些位用于在程序集级别支持条件和循环中的条件执行

Negative|Zero|Carry|Overflow|underflow| |Jazelle| |Greater than or Equal for SIMD| |Endianness| Abort disable| IRQ disable | FIQ disable | Thumb| Processor mode(Privilege mode)|

APSR包含下列ALU的状态标志:

N-当操作结果为负数时设置;

Z-当操作结果为0时设置;

C-当操作导致进位时设置;

V-当操作造成溢出时设置。

在下列情况下,进位发生:

如果加法、减法或比较的结果大于或等于 2^31,或小于 –2^31,溢出发生。

ARM 处理器有两个主要的状态可以运行(这里不计算 Jazelle),ARM 和 Thumb。 这些状态与特权级别无关。 例如,在 SVC 模式下运行的代码可以是 ARM 或 Thumb。 这两种状态的主要区别在于指令集,其中ARM状态的指令总是32位的,Thumb状态的指令是16位的(但也可以是32位的)。 了解何时以及如何使用 Thumb 对于我们的 ARM 漏洞利用开发目的尤其重要。 在编写 ARM shellcode 时,我们需要去掉 NULL 字节,使用 16 位 Thumb 指令而不是 32 位 ARM 指令减少了拥有它们的机会。

这里有不同的Thumb版本:

ARM和Thumb之间的差别:

要切换处理器执行的状态,必须满足以下两个条件之一:

汇编语言由作为主要构建块的指令组成。 ARM 指令通常后跟一两个操作数,一般使用以下模板:

由于 ARM 指令集的灵活性,并非所有指令都使用模板中提供的所有字段。模板中字段的用途描述如下:

MNEMONIC、S、Rd 和 Operand1 字段是比较直观的,但条件和 Operand2 字段需要更多说明。 条件字段与 CPSR 寄存器的值密切相关,或者准确地说,是寄存器中特定位的值。 Operand2 被称为灵活操作数,因为我们可以以各种形式使用它——作为立即数(具有有限的值集)、寄存器或带有移位的寄存器。 例如,我们可以将这些表达式用作 Operand2:

不同种类的指令的例子如下所示:

总结下:

ARM使用load-store模式进行内存的访问,这意味着只能使用load/store(LDR and LDR)指令能访问内存。而x86允许直接在内存上操作数据,在arm上数据在操作前必须被move到寄存器中。这意味着在 ARM 上的特定内存地址处递增 32 位值将需要三种类型的指令(load, increment, and store) 来首先将特定地址处的值加载到寄存器中,在寄存器中递增它,然后将它从寄存器存储回内存。为了解释 ARM 上加载和存储操作的基本原理,我们从一个基本示例开始,然后继续介绍三种基本偏移量形式,每种偏移量形式具有三种不同的地址模式。 对于每个示例,我们将使用具有不同 LDR/STR 偏移形式的同一段汇编代码,以保持简单。

立即数作为偏移:
地址模式: 偏移
地址模式: 预先索引
地址模式: 后索引
寄存器作为偏移:
地址模式: 偏移
地址模式: 预先索引
地址模式: 后索引
Scaled register作为偏移
地址模式: 偏移
地址模式: 预先索引
地址模式: 后索引

通常,LDR用于将内存中的某些内容加载到寄存器中,STR用于将存储器中的某些内容存储到内存地址。

LDR操作:将R0中找到的地址上的值加载到目标寄存器R2。

STR操作:将R2中找到的值存储到R1中找到的内存地址。

在底部,我们有我们的 Literal Pool(同一代码段中的一个内存区域,用于存储其他人可以以与位置无关的方式引用的常量、字符串或偏移量),其中存储了 var1 和 var2 的内存地址(在顶部的数据部分)使用标签 adr_var1 和 adr_var2。第一个 LDR 将 var1 的地址加载到寄存器 R0 中。第二个 LDR 对 var2 执行相同的操作并将其加载到 R1。然后我们将存储在 R0 中找到的内存地址的值加载到 R2,并将 R2 中找到的值存储到 R1 中找到的内存地址。

当我们将某些内容加载到寄存器中时,方括号 ([ ]) 表示:在这些方括号之间的寄存器中找到的值是我们要从中加载某些内容的内存地址。

当我们将内容存储到内存位置时,方括号 ([]) 表示:在这些方括号之间的寄存器中找到的值是我们想要存储内容的内存地址。

调试器中的代码片段:

我们在前两个 LDR 操作中指定的标签更改为 [pc, #12]。这称为 PC 相对寻址。因为我们使用了标签,所以编译器计算了我们在文字池 (PC+12) 中指定的值的位置。您可以使用这种精确方法自己计算位置,也可以像我们之前所做的那样使用标签。唯一的区别是,您需要计算您的值在 Literal Pool 中的确切位置,而不是使用标签。在这种情况下,它距离有效 PC 位置 3 跳(4+4+4=12)。

这里我们使用立即数(整数)作为偏移量。 该值与基址寄存器(下例中的 R1)相加或相减,以在编译时已知的偏移量处访问数据。

将在偏移地址模式下执行 STR 操作的下一条指令。 它会将 R2 (0x00000003) 中的值存储到 R1 (0x0001009c) 中指定的内存地址 + 偏移量 (#2) = 0x1009e。

这种偏移形式使用寄存器作为偏移。 这种偏移形式的一个示例用法是当您的代码想要访问在运行时计算索引的数组时。

在偏移地址模式下执行第一个STR操作后,R2的值(0x00000003)将存储在内存地址0x0001009c + 0x00000003 = 0x0001009F。

第三种偏移形式有一个缩放寄存器作为偏移。 在这种情况下,Rb 是基址寄存器,Rc 是立即偏移量(或包含立即值的寄存器)左/右移位 (\<shifter\>) 以缩放立即数。 这意味着桶形移位器用于缩放偏移。 这种偏移形式的一个示例用法是循环遍历数组。

第一个 STR 操作使用偏移地址模式,并将在 R2 中找到的值存储在从 [r1, r2, LSL#2] 计算出的内存位置,这意味着它以 R1 中的值为基数(在这种情况下,R1 包含 var2 的内存地址),然后取 R2 (0x3) 中的值,并将其左移 2。下图是尝试可视化如何使用 [r1, r2, LSL#2] 计算内存位置 .

在 ARM 上的寄存器中加载立即值并不像在 x86 上那样简单。您可以使用哪些直接值是有限制的。可以使用一些技巧来绕过这些限制(提示:LDR)。

我们知道每条 ARM 指令都是 32bit 长的,所有指令都是有条件的。我们可以使用16个条件码,一个条件码占指令的4位。然后我们需要 2 位作为目标寄存器。 2 位用于第一个操作数寄存器,1 位用于设置状态标志,以及用于其他事项(如实际操作码)的各种位。这里的重点是,在为指令类型、寄存器和其他字段分配位后,立即数只剩下 12 位,这将只允许 4096 个不同的值。

这意味着 ARM 指令只能直接在 MOV 中使用有限范围的立即数。如果一个数字不能直接使用,就必须把它分成几部分,由多个较小的数字拼凑起来。

但还有更多。不是将 12 位用于单个整数,而是将这 12 位拆分为一个 8 位数字 (n),能够加载 0-255 范围内的任何 8 位值,以及一个 4 位旋转字段 (r) 作为一个在 0 到 30 之间以 2 为步长向右循环。这意味着完整的立即数 v 由以下公式给出:v = n ror 2*r。换句话说,唯一有效的立即数是循环字节(可以减少到循环一个偶数的字节的值)。

以下是一些有效和无效的立即数的例子:

这导致无法一次性加载完整的 32 位地址。 我们可以使用以下两个选项之一绕过此限制:

如果你试图加载一个无效的立即数,汇编器会产生一个错误,"Error: invalid constant.",
如果您需要弄清楚某个数字是否可以用作有效的立即数,则无需自己计算。 您可以使用我的名为 rotator.py 的小 Python 脚本,它将您的号码作为输入并告诉您它是否可以用作有效的立即数。

rotator.py

有时一次加载(或存储)多个值更有效。为此,我们使用LDM(负载倍数)和STM(存储倍数)。这些指令的变体基本上只因访问初始地址的方式而异。这是我们本节将使用的代码。我们将一步一步地完成每项指令。

在开始之前,请记住,.word 指的是 32 位 = 4 BYTES 的数据(内存)块。 这对于理解偏移很重要。 因此该程序由 .data 部分组成,我们在其中分配了一个具有 5 个元素的空数组 (array_buff)。 我们将使用它作为存储数据的可写内存位置。 .text 部分包含我们的代码以及内存操作指令和一个包含两个标签的只读数据池:一个用于具有 7 个元素的数组,另一个用于“桥接” .text 和 .data 部分,以便我们可以访问驻留的 array_buff 在 .data 部分。

我们使用 ADR 指令将第 4 个元素(words[3])的地址放入 R0。 我们指向 words 数组的中间,因为我们将从那里向前和向后操作。

我们用 array_buff 数组的第一个 (array_buff[0]) 和第三个 (array_buff[2]) 元素的地址准备 R1 和 R2。 一旦获得地址,我们就可以开始对其进行操作。

下一条指令使用 LDM 从 R0 指向的内存中加载两个字值。 因此,因为我们之前让 R0 指向 words[3] 元素,所以 words[3] 值转到 R4,words[4] 值转到 R5。

下一条指令让我们执行 STM 指令将多个值存储到内存中。 我们代码中的 STM 指令从寄存器 R4 和 R5 获取值(0x3 和 0x4),并将这些值存储到 R1 指定的内存位置。

变体的类型由指令的后缀定义。 示例中使用的后缀是:-IA(之后增加)、-IB(之前增加)、-DA(之后减少)、-DB(之前减少)。 这些变体的不同之处在于它们如何访问由第一个操作数(存储源地址或目标地址的寄存器)指定的内存。 实际上,LDM 与 LDMIA 相同,这意味着每次加载后都会增加下一个要加载的元素的地址。 通过这种方式,我们从第一个操作数(存储源地址的寄存器)指定的内存地址中获得顺序(前向)数据加载。

执行上述两条指令后,寄存器 R4-R6 和内存地址 0x000100D0、0x000100D4 和 0x000100D8 包含值 0x3、0x4 和 0x5。

LDMIB 指令首先将源地址增加 4 个字节(一个字值),然后执行第一次加载。 通过这种方式,我们仍然可以顺序(向前)加载数据,但第一个元素与源地址有 4 个字节的偏移量。 这就是为什么在我们的示例中,通过 LDMIB 指令从内存加载到 R4 的第一个元素是 0x00000004(word[4])而不是 R0 指向的 0x00000003(word[3])。

执行上述两条指令后,寄存器 R4-R6 和内存地址 0x100D4、0x100D8 和 0x100DC 包含值 0x4、0x5 和 0x6。

当我们使用 LDMDA 指令时,一切都开始向后运行。 R0 指向word[3]。 当加载开始时,我们向后移动并将word[3]、word[2]和word[1]加载到R6、R5、R4中。 是的,寄存器也是反向加载的。 所以在指令完成后 R6 = 0x00000003,R5 = 0x00000002,R4 = 0x00000001。

加载多个,递减后:

store多个,递减后:

PUSH:

POP:

上面代码中的第一条 CMP 指令触发负位被置位 (2 – 3 = -1) 表示 r0 中的值低于数字 3。随后执行 ADDLT 指令,因为当 V 时 LT 条件已满! = N(CPSR 中溢出位和负位的值不同)。 在我们执行第二个 CMP 之前,我们的 r0 = 3。这就是为什么第二个 CMP 清除负位(因为 3 – 3 = 0,不需要设置负标志)并设置零标志(Z = 1)。 现在我们有 V = 0 和 N = 0 这导致 LT 条件失败。 因此,不会执行第二个 ADDLT,并且 r0 保持不变。 程序退出,结果为 3。

在允许条件执行的 Thumb 版本 (Thumb-2)中。 某些 ARM 处理器版本支持“IT”指令,该指令允许在 Thumb 状态下有条件地执行最多 4 条指令。

语法:IT{x{y{z}}} cond

IT 指令的结构是“IF-Then-(Else)”,语法是两个字母 T 和 E 的结构:

IT 块内的每条指令都必须指定一个条件后缀,该后缀相同或逻辑相反。 这意味着,如果您使用 ITE,则第一条和第二条指令 (If-Then) 必须具有相同的条件后缀,而第三条 (Else) 必须具有前两条的逻辑逆。

以下是条件代码及其对立的条件:

.code 32

此示例代码以ARM状态开始。第一条指令将 PC 加 1 指定的地址添加到 R3,然后分支到 R3 中的地址。这将导致切换到拇指状态,因为LSB(最不重要的位)是1,因此不是4字节对齐的。为此使用bx(分支+交换)很重要。在分支之后设置T(拇指)标志,我们处于拇指状态。

.code 16

在拇指状态下,我们首先将R0与#10进行比较,这将设置负标志(0–10 = – 10)。然后我们使用If-Then-Else块。此块将跳过ADDEQ指令,因为没有设置Z(零)标志,并将执行ADDNE指令,因为结果为NE(不等于)为10。

存在三种类型的分支指令:

Branch (B)

Branch link (BL)

Branch exchange (BX) and Branch link exchange (BLX)

◎ Full descending 满递减堆栈
堆栈首部是高地址,堆栈向低地址增长。栈指针总是指向堆栈最后一个元素(最后一个元素是最后压入的数据)。
ARM-Thumb过程调用标准和ARM、Thumb C/C++ 编译器总是使用Full descending 类型堆栈。

◎ Full ascending 满递增堆栈
堆栈首部是低地址,堆栈向高地址增长。栈指针总是指向堆栈最后一个元素(最后一个元素是最后压入的数据)。

◎ Empty descending 空递减堆栈
堆栈首部是低地址,堆栈向高地址增长。栈指针总是指向下一个将要放入数据的空位置。

◎ Empty ascending 空递增堆栈
堆栈首部是高地址,堆栈向低地址增长。栈指针总是指向下一个将要放入数据的空位置。

 
ldr = Load Word
ldrh = Load unsigned Half Word
ldrsh = Load signed Half Word
ldrb = Load unsigned Byte
ldrsb = Load signed Bytes
 
str = Store Word
strh = Store unsigned Half Word
strsh = Store signed Half Word
strb = Store unsigned Byte
strsb = Store signed Byte
ldr = Load Word
ldrh = Load unsigned Half Word
ldrsh = Load signed Half Word
ldrb = Load unsigned Byte
ldrsb = Load signed Bytes
 
str = Store Word
strh = Store unsigned Half Word
strsh = Store signed Half Word
strb = Store unsigned Byte
strsb = Store signed Byte
 
# Alias Purpose
R0 - General purppose
R1 - General purppose
R2 - General purppose
R3 - General purppose
R4 - General purppose
R5 - General purppose
R6 - General purppose
R7 - General purppose
R8 - General purppose
R9 - General purppose
R10 - General purppose
R11 FP Frame Pointer
R12 IP Instra Procedural Call
R13 SP Stack Pointer
R14 LR Link Register
R15 PC Program Counter
CPSR - Current Program Status Register
 
ARM Description x86
R0 General Purpose EAX
R1-R5 General Purpose EBX, ECX, EDX, ESI, EDI
R6-R10 General Purpose
R11 (FP) Frame Pointer EBP
R12 Intra Procedural Call
R13 (SP) Stack Pointer ESP
R14 (LR) Link Register
R15 (PC) <- Program Counter / Instruction Pointer -> EIP
CPSR Current Program State Register/Flags EFLAGS
 
 
 
 
.section .text
.global _start
 
_start:
 mov r0, pc
 mov r1, #2
 add r2, r1, r1
 bkpt
.section .text
.global _start
 
_start:
 mov r0, pc
 mov r1, #2
 add r2, r1, r1
 bkpt
gef> b _start
Breakpoint 1 at 0x10054
gef> r
gef> b _start
Breakpoint 1 at 0x10054
gef> r
Breakpoint 1, 0x00010054 in _start ()
---------------------------------------------------------------[ registers ]----
$r0   : 0x00000000
$r1   : 0x00000000
$r2   : 0x00000000
$r3   : 0x00000000
$r4   : 0x00000000
$r5   : 0x00000000
$r6   : 0x00000000
$r7   : 0x00000000
$r8   : 0x00000000
$r9   : 0x00000000
$r10  : 0x00000000
$r11  : 0x00000000
$r12  : 0x00000000
$sp   : 0xbefff3b0 -> 0x00000001
$lr   : 0x00000000
$pc   : 0x00010054 -> <_start+0> mov r0,  pc
$cpsr : [thumb fast interrupt overflow carry zero negative]
-------------------------------------------------------------------[ stack ]----
0xbefff3b0|+0x00: 0x00000001    <-$sp
0xbefff3b4|+0x04: 0xbefff51c -> "/home/pi/asm/test_pc"
0xbefff3b8|+0x08: 0x00000000
0xbefff3bc|+0x0c: 0xbefff531 -> 0x49464e49
0xbefff3c0|+0x10: 0xbefff56b -> "XDG_SESSION_ID=c2"
0xbefff3c4|+0x14: 0xbefff57d -> "SHELL=/bin/bash"
0xbefff3c8|+0x18: 0xbefff58d -> "TERM=xterm"
0xbefff3cc|+0x1c: 0xbefff598 -> 0x49464e49
-------------------------------------------------------------[ code:armv5t ]----
      0x1003c                  andeq  r0,  r1,  r0
      0x10040                  andeq  r0,  r1,  r0
      0x10044                  andeq  r0,  r0,  r4,  rrx
      0x10048                  andeq  r0,  r0,  r4,  rrx
      0x1004c                  andeq  r0,  r0,  r5
      0x10050                  andeq  r0,  r1,  r0
->   0x10054 <_start+0>       mov    r0,  pc
      0x10058 <_start+4>       mov    r1,  #2
      0x1005c <_start+8>       add    r2,  r1,  r1
      0x10060 <_start+12>      bkpt   0x0000
      0x10064                  andeq  r1,  r0,  r1,  asr #6
      0x10068                  cmnvs  r5,  r0,  lsl #2
-----------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: BREAKPOINT
-------------------------------------------------------------------[ trace ]----
[#0] 0x10054->Name: _start()
--------------------------------------------------------------------------------
Breakpoint 1, 0x00010054 in _start ()
---------------------------------------------------------------[ registers ]----
$r0   : 0x00000000
$r1   : 0x00000000
$r2   : 0x00000000
$r3   : 0x00000000
$r4   : 0x00000000
$r5   : 0x00000000
$r6   : 0x00000000
$r7   : 0x00000000
$r8   : 0x00000000
$r9   : 0x00000000
$r10  : 0x00000000
$r11  : 0x00000000
$r12  : 0x00000000
$sp   : 0xbefff3b0 -> 0x00000001
$lr   : 0x00000000
$pc   : 0x00010054 -> <_start+0> mov r0,  pc
$cpsr : [thumb fast interrupt overflow carry zero negative]
-------------------------------------------------------------------[ stack ]----
0xbefff3b0|+0x00: 0x00000001    <-$sp
0xbefff3b4|+0x04: 0xbefff51c -> "/home/pi/asm/test_pc"
0xbefff3b8|+0x08: 0x00000000
0xbefff3bc|+0x0c: 0xbefff531 -> 0x49464e49
0xbefff3c0|+0x10: 0xbefff56b -> "XDG_SESSION_ID=c2"
0xbefff3c4|+0x14: 0xbefff57d -> "SHELL=/bin/bash"
0xbefff3c8|+0x18: 0xbefff58d -> "TERM=xterm"
0xbefff3cc|+0x1c: 0xbefff598 -> 0x49464e49
-------------------------------------------------------------[ code:armv5t ]----
      0x1003c                  andeq  r0,  r1,  r0
      0x10040                  andeq  r0,  r1,  r0
      0x10044                  andeq  r0,  r0,  r4,  rrx
      0x10048                  andeq  r0,  r0,  r4,  rrx
      0x1004c                  andeq  r0,  r0,  r5
      0x10050                  andeq  r0,  r1,  r0
->   0x10054 <_start+0>       mov    r0,  pc
      0x10058 <_start+4>       mov    r1,  #2
      0x1005c <_start+8>       add    r2,  r1,  r1
      0x10060 <_start+12>      bkpt   0x0000
      0x10064                  andeq  r1,  r0,  r1,  asr #6
      0x10068                  cmnvs  r5,  r0,  lsl #2
-----------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: BREAKPOINT
-------------------------------------------------------------------[ trace ]----
[#0] 0x10054->Name: _start()
--------------------------------------------------------------------------------
0x00010058 in _start ()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------[ registers ]----
$r0   : 0x0001005c -> <_start+8> add r2,  r1,  r1
$r1   : 0x00000000
$r2   : 0x00000000
$r3   : 0x00000000
$r4   : 0x00000000
$r5   : 0x00000000
$r6   : 0x00000000
$r7   : 0x00000000
$r8   : 0x00000000
$r9   : 0x00000000
$r10  : 0x00000000
$r11  : 0x00000000
$r12  : 0x00000000
$sp   : 0xbefff3b0 -> 0x00000001
$lr   : 0x00000000
$pc   : 0x00010058 -> <_start+4> mov r1,  #2
$cpsr : [thumb fast interrupt overflow carry zero negative]
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ stack ]----
0xbefff3b0|+0x00: 0x00000001    <-$sp
0xbefff3b4|+0x04: 0xbefff51c -> "/home/pi/asm/test_pc"
0xbefff3b8|+0x08: 0x00000000
0xbefff3bc|+0x0c: 0xbefff531 -> 0x49464e49
0xbefff3c0|+0x10: 0xbefff56b -> "XDG_SESSION_ID=c2"
0xbefff3c4|+0x14: 0xbefff57d -> "SHELL=/bin/bash"
0xbefff3c8|+0x18: 0xbefff58d -> "TERM=xterm"
0xbefff3cc|+0x1c: 0xbefff598 -> 0x49464e49
------------------------------------------------------------------------------------------------------------------------------------------------------------------[ code:armv5t ]----
      0x10040                  andeq  r0,  r1,  r0
      0x10044                  andeq  r0,  r0,  r4,  rrx
      0x10048                  andeq  r0,  r0,  r4,  rrx
      0x1004c                  andeq  r0,  r0,  r5
      0x10050                  andeq  r0,  r1,  r0
      0x10054 <_start+0>       mov    r0,  pc
->   0x10058 <_start+4>       mov    r1,  #2
      0x1005c <_start+8>       add    r2,  r1,  r1
      0x10060 <_start+12>      bkpt   0x0000
      0x10064                  andeq  r1,  r0,  r1,  asr #6
      0x10068                  cmnvs  r5,  r0,  lsl #2
      0x1006c                  tsteq  r0,  r2,  ror #18
----------------------------------------------------------------------------------------------------------------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: SINGLE STEP
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ trace ]----
[#0] 0x10058->Name: _start()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x00010058 in _start ()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------[ registers ]----
$r0   : 0x0001005c -> <_start+8> add r2,  r1,  r1
$r1   : 0x00000000
$r2   : 0x00000000
$r3   : 0x00000000
$r4   : 0x00000000
$r5   : 0x00000000
$r6   : 0x00000000
$r7   : 0x00000000
$r8   : 0x00000000
$r9   : 0x00000000
$r10  : 0x00000000
$r11  : 0x00000000
$r12  : 0x00000000
$sp   : 0xbefff3b0 -> 0x00000001
$lr   : 0x00000000
$pc   : 0x00010058 -> <_start+4> mov r1,  #2
$cpsr : [thumb fast interrupt overflow carry zero negative]
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ stack ]----
0xbefff3b0|+0x00: 0x00000001    <-$sp
0xbefff3b4|+0x04: 0xbefff51c -> "/home/pi/asm/test_pc"
0xbefff3b8|+0x08: 0x00000000
0xbefff3bc|+0x0c: 0xbefff531 -> 0x49464e49
0xbefff3c0|+0x10: 0xbefff56b -> "XDG_SESSION_ID=c2"
0xbefff3c4|+0x14: 0xbefff57d -> "SHELL=/bin/bash"
0xbefff3c8|+0x18: 0xbefff58d -> "TERM=xterm"
0xbefff3cc|+0x1c: 0xbefff598 -> 0x49464e49
------------------------------------------------------------------------------------------------------------------------------------------------------------------[ code:armv5t ]----
      0x10040                  andeq  r0,  r1,  r0
      0x10044                  andeq  r0,  r0,  r4,  rrx
      0x10048                  andeq  r0,  r0,  r4,  rrx
      0x1004c                  andeq  r0,  r0,  r5
      0x10050                  andeq  r0,  r1,  r0
      0x10054 <_start+0>       mov    r0,  pc
->   0x10058 <_start+4>       mov    r1,  #2
      0x1005c <_start+8>       add    r2,  r1,  r1
      0x10060 <_start+12>      bkpt   0x0000
      0x10064                  andeq  r1,  r0,  r1,  asr #6
      0x10068                  cmnvs  r5,  r0,  lsl #2
      0x1006c                  tsteq  r0,  r2,  ror #18
----------------------------------------------------------------------------------------------------------------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: SINGLE STEP
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ trace ]----
[#0] 0x10058->Name: _start()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
N Z C V Q - J - GE - E A I F T M
 
Flag Description
N(Negative) 如果指令结果是负数则置1.
Z(Zero) 如果指令结果产生零值则置1.
C(Carry) 如果指令的结果产生一个需要第 33 位才能完全表示的值,则置1.
V(Overflow) 如果该指令的结果产生不能在32位二进制补码表示的值.
E(Endian-bit) ARM 可以以小端或大端方式运行。 对于小端模式,该位设置为 0,对于大端模式设置为 1.
T(Thumb-bit) 如果是Thumb模式置1,如果是ARM模式置0.
M(Mode-bits) 这些位指定当前特权模式(USR、SVC 等).
J(Jazelle) 允许某些 ARM 处理器在硬件中执行 Java 字节码的第三种执行状态.
 
 
 
 
 
 
 
MNEMONIC{S}{condition} {Rd}, Operand1, Operand2
MNEMONIC{S}{condition} {Rd}, Operand1, Operand2
MNEMONIC     - Short name (mnemonic) of the instruction
{S}          - An optional suffix. If S is specified, the condition flags are updated on the result of the operation
{condition}  - Condition that is needed to be met in order for the instruction to be executed
{Rd}         - Register (destination) for storing the result of the instruction
Operand1     - First operand. Either a register or an immediate value
Operand2     - Second (flexible) operand. Can be an immediate value (number) or a register with an optional shift
MNEMONIC     - Short name (mnemonic) of the instruction
{S}          - An optional suffix. If S is specified, the condition flags are updated on the result of the operation
{condition}  - Condition that is needed to be met in order for the instruction to be executed
{Rd}         - Register (destination) for storing the result of the instruction
Operand1     - First operand. Either a register or an immediate value
Operand2     - Second (flexible) operand. Can be an immediate value (number) or a register with an optional shift
#123                    - Immediate value (with limited set of values).
Rx                      - Register x (like R1, R2, R3 ...)
Rx, ASR n               - Register x with arithmetic shift right by n bits (1 = n = 32)
Rx, LSL n               - Register x with logical shift left by n bits (0 = n = 31)
Rx, LSR n               - Register x with logical shift right by n bits (1 = n = 32)
Rx, ROR n               - Register x with rotate right by n bits (1 = n = 31)
Rx, RRX                 - Register x with rotate right by one bit, with extend
#123                    - Immediate value (with limited set of values).
Rx                      - Register x (like R1, R2, R3 ...)
Rx, ASR n               - Register x with arithmetic shift right by n bits (1 = n = 32)
Rx, LSL n               - Register x with logical shift left by n bits (0 = n = 31)
Rx, LSR n               - Register x with logical shift right by n bits (1 = n = 32)
Rx, ROR n               - Register x with rotate right by n bits (1 = n = 31)
Rx, RRX                 - Register x with rotate right by one bit, with extend
ADD   R0, R1, R2         - Adds contents of R1 (Operand1) and R2 (Operand2 in a form of register) and stores the result into R0 (Rd)
ADD   R0, R1, #2         - Adds contents of R1 (Operand1) and the value 2 (Operand2 in a form of an immediate value) and stores the result into R0 (Rd)
MOVLE R0, #5             - Moves number 5 (Operand2, because the compiler treats it as MOVLE R0, R0, #5) to R0 (Rd) ONLY if the condition LE (Less Than or Equal) is satisfied
MOV   R0, R1, LSL #1     - Moves the contents of R1 (Operand2 in a form of register with logical shift left) shifted left by one bit to R0 (Rd). So if R1 had value 2, it gets shifted left by one bit and becomes 4. 4 is then moved to R0.
ADD   R0, R1, R2         - Adds contents of R1 (Operand1) and R2 (Operand2 in a form of register) and stores the result into R0 (Rd)
ADD   R0, R1, #2         - Adds contents of R1 (Operand1) and the value 2 (Operand2 in a form of an immediate value) and stores the result into R0 (Rd)
MOVLE R0, #5             - Moves number 5 (Operand2, because the compiler treats it as MOVLE R0, R0, #5) to R0 (Rd) ONLY if the condition LE (Less Than or Equal) is satisfied
MOV   R0, R1, LSL #1     - Moves the contents of R1 (Operand2 in a form of register with logical shift left) shifted left by one bit to R0 (Rd). So if R1 had value 2, it gets shifted left by one bit and becomes 4. 4 is then moved to R0.
Instruction Description Instruction Description
MOV Move data EOR Bitwise XOR
MVN Move and negate LDR Load
ADD Addition STR Store
SUB Subtraction LDM Load Multiple
MUL Multiplication STM Store Multiple
LSL Logical Shift Left PUSH Push on Stack
LSR Logical Shift Right POP Pop off Stack
ASR Arithmetic Shift Right B Branch
ROR Rotate Right BL Branch with Link
CMP Compare BX Branch and eXchange
AND Bitwise AND BLX Branch with Link and eXchange
ORR Bitwise OR SWI/SVC System Call
 
 
LDR R2, [R0]   @ [R0] - origin address is the value found in R0.
STR R2, [R1]   @ [R1] - destination address is the value found in R1.
LDR R2, [R0]   @ [R0] - origin address is the value found in R0.
STR R2, [R1]   @ [R1] - destination address is the value found in R1.
 
.data          /* the .data section is dynamically created and its addresses cannot be easily predicted */
var1: .word 3  /* variable 1 in memory */
var2: .word 4  /* variable 2 in memory */
 
.text          /* start of the text (code) section */
.global _start
 
_start:
    ldr r0, adr_var1  @ load the memory address of var1 via label adr_var1 into R0
    ldr r1, adr_var2  @ load the memory address of var2 via label adr_var2 into R1
    ldr r2, [r0]      @ load the value (0x03) at memory address found in R0 to register R2 
    str r2, [r1]      @ store the value found in R2 (0x03) to the memory address found in R1
    bkpt            
 
adr_var1: .word var1  /* address to var1 stored here */
adr_var2: .word var2  /* address to var2 stored here */
.data          /* the .data section is dynamically created and its addresses cannot be easily predicted */
var1: .word 3  /* variable 1 in memory */
var2: .word 4  /* variable 2 in memory */
 
.text          /* start of the text (code) section */
.global _start
 
_start:
    ldr r0, adr_var1  @ load the memory address of var1 via label adr_var1 into R0
    ldr r1, adr_var2  @ load the memory address of var2 via label adr_var2 into R1
    ldr r2, [r0]      @ load the value (0x03) at memory address found in R0 to register R2 
    str r2, [r1]      @ store the value found in R2 (0x03) to the memory address found in R1
    bkpt            
 
adr_var1: .word var1  /* address to var1 stored here */
adr_var2: .word var2  /* address to var2 stored here */
 
 
 
->   0x10074 <_start+0>       ldr    r0,  [pc,  #12]    ; 0x10088 <adr_var1>
      0x10078 <_start+4>       ldr    r1,  [pc,  #12]     0x1008c <adr_var2>
      0x1007c <_start+8>       ldr    r2,  [r0]
      0x10080 <_start+12>      str    r2,  [r1]
      0x10084 <_start+16>      bkpt   0x0000
      0x10088 <adr_var1+0>     muleq  r2,  r0,  r0
----------------------------------------------------------------------------------------------------------------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: BREAKPOINT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ trace ]----
[#0] 0x10074->Name: _start()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gef>
->   0x10074 <_start+0>       ldr    r0,  [pc,  #12]    ; 0x10088 <adr_var1>
      0x10078 <_start+4>       ldr    r1,  [pc,  #12]     0x1008c <adr_var2>
      0x1007c <_start+8>       ldr    r2,  [r0]
      0x10080 <_start+12>      str    r2,  [r1]
      0x10084 <_start+16>      bkpt   0x0000
      0x10088 <adr_var1+0>     muleq  r2,  r0,  r0
----------------------------------------------------------------------------------------------------------------------------------------------------------------------[ threads ]----
[#0] Id 1, Name: "test_pc", stopped, reason: BREAKPOINT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------[ trace ]----
[#0] 0x10074->Name: _start()
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gef>
STR    Ra, [Rb, imm]
LDR    Ra, [Rc, imm]
STR    Ra, [Rb, imm]
LDR    Ra, [Rc, imm]
.data
var1: .word 3
var2: .word 4
 
.text
.global _start
 
_start:
    ldr r0, adr_var1  @ load the memory address of var1 via label adr_var1 into R0
    ldr r1, adr_var2  @ load the memory address of var2 via label adr_var2 into R1
    ldr r2, [r0]      @ load the value (0x03) at memory address found in R0 to register R2
    str r2, [r1, #2]  @ address mode: offset. Store the value found in R2 (0x03) to the memory address found in R1 plus 2. Base register (R1) unmodified.
    str r2, [r1, #4]! @ address mode: pre-indexed. Store the value found in R2 (0x03) to the memory address found in R1 plus 4. Base register (R1) modified: R1 = R1+4
    ldr r3, [r1], #4  @ address mode: post-indexed. Load the value at memory address found in R1 to register R3. Base register (R1) modified: R1 = R1+4
    bkpt
 
adr_var1: .word var1
adr_var2: .word var2
.data
var1: .word 3
var2: .word 4
 
.text
.global _start

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-11-5 17:49 被dig_grave编辑 ,原因: 表格没设置好
收藏
免费 6
支持
分享
最新回复 (3)
雪    币: 767
活跃值: (3415)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
2
请教一下,word、halfword、byte 长度分别是多少?我刚接触arm,这些还不太懂,x86上word是2字节,byte是1字节,halfword没见过。
2021-9-10 15:27
0
雪    币: 8203
活跃值: (2738)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
3
字(Word):在ARM体系结构(32位机)中,字的长度为32位,
半字(Half-Word):在ARM体系结构(32位机)中,半字的长度为16位。
2021-9-10 15:37
1
雪    币: 767
活跃值: (3415)
能力值: ( LV7,RANK:140 )
在线值:
发帖
回帖
粉丝
4
谢谢解答
2021-9-10 20:14
0
游客
登录 | 注册 方可回帖
返回
//