OC逆向01:初始汇编

张建 lol

前言

在逆向开发中,非常重要的一个环节就是 静态分析,众所周知,手机上安装 APP 其本质是一个 二进制文件,因为iPhone手机本质上执行的指令是二进制,是由手机上的 CPU 执行的;而静态分析是建立在分析二进制上面的。所以在学习逆向之前,需要提前了解相关的汇编知识

汇编语言的发展

机器语言

是由 0和1 组成的机器指令,表示特定的功能,如下所示:

1
2
3
4
加:0100 0000
减:0100 1000
乘:1111 0111 1110 0000
除:1111 0111 1111 0000

汇编语言(assembly language)

由于使用机器语言表示时不方便记忆,于是开始使用 助记符 来代替机器语言,例如下面使用助记符表示的 加减乘除

1
2
3
4
加:INC EAX 通过编译器 0100 0000
减:DEC EAX 通过编译器 0100 1000
乘:MUL EAX 通过编译器 1111 0111 1110 0000
除:DIV EAX 通过编译器 1111 0111 1111 0000

高级语言(High-level programming language)

在后期,为了更加高效的编程,在汇编语言的基础上有了更高级的语言,例如:
C/C++/Java/OC/Swift 等,这些语言更加接近人类的自然语言,例如C语言表示加减乘除

1
2
3
4
加:A+B 通过编译器 0100 0000
减:A-B 通过编译器 0100 1000
乘:A*B 通过编译器 1111 0111 1110 0000
除:A/B 通过编译器 1111 0111 1111 0000

最终的代码在终端设备上显示的过程如下:

【说明】:

  • 汇编语言机器语言--对应 的关系,每一条机器指令都有与之对应的汇编指令

  • 汇编语言 可以通过 编译 得到 机器语言机器语言 可以通过 反编译 得到 汇编语言

  • 高级语言 可以通过 编译 得到 汇编语言/机器语言,但 汇编汇演/机器语言 几乎不可能还原成高级语言

    • 不同的 高级语言 可以得到 同样的 汇编语言,但是同一个 汇编语言 无法推断出用什么高级语言
    • 不同的 CPU架构,而CPU架构对应不同的 指令集

汇编语言的特点

汇编语言主要有以下几个特点:

  • 可以 直接访问、控制 各种硬件设备,比如 存储器、CPU等,能最大限度地发挥硬件的功能
  • 能够不受编译器的限制,对生成的二进制代码进行完全的控制
  • 目标代码简短,占用内存少,执行速度快
  • 汇编指令是机器指令的 助记符,同机器指令一一对应,每一种CPU都有自己的机器指令/汇编指令集
  • 知识点过多,要求过高,需要开发者对CPU等硬件结构有所了解,不易于编写、调式,以及维护
  • 不区分大小写,例如mov和MOV是一样的

汇编语言的用途(哥 我学了能干啥?)

按理说,汇编这么难,为什么还要学呢?以及学了能干什么?

汇编学习的目的

任何高级语言最终都会被编译汇编,学习了汇编的相关知识,可以更好的日常开发,学习探索中帮助我们更好的排查问,理解底层运行的机制,大致分为以下几点:

  • 是理解整个计算机系统的最佳起点和最有效途径

  • 为编写高效代码打下基础

  • 理解代码的本质,例如:

    • 函数的本质是什么?
    • ++a底层是如何执行的?
    • 编译器在底层到底帮我们做了哪些工作?
    • DEBUG模式和RELEASE模式到底有哪些地方是不同的?以及被我们忽略的?

汇编使用的场景

  • 可以 编写驱动程序、操作系统,例如Linux内核的某些关键字

  • 对性能要求极高的程序或代码片段,可 与高级语言混合使用(称为内联汇编)

  • 用于 软件安全方面

    • 病毒的分析与防治
    • 逆向、加壳、脱壳、破解、外挂、免杀、加解密、黑客等

所以综上所述,汇编时所有👨🏻‍💻都需要了解的一门非常重要的语言,这也是为什么大学生中计算机相关专业学生的必修课,就好比修房子,地基稳了,高楼才能平地起

汇编语言的种类

目前讨论比较多的汇编语言有:

  • 8086汇编(8086处理器是16bit的CPU)
  • Win32汇编
  • Win64汇编
  • ARM汇编(嵌入式、Mac、iOS)

我们iPhone里面用到的是 ARM汇编,但是不同的设备也有差异,因CPU的架构不同

必备常识

想要学好汇编,需要有以下几个常识:

  • 1、首先需要了解CPU等硬件的架构

  • 2、APP/程序的执行过程

  • 可执行文件:程序/APP在本地磁盘的文件

  • image(镜像文件):可执行文件被装载到内存的文件(在早起,其本质与可执行文件是一模一样的)

  • 内存中除了 指令,还有 数据,但都是 0和1 组合,CPU是如何区分的?是通过CPU上的部件CPU寄存器来区分

  • 3、硬件相关最为重要的是CPU/内存

  • 4、在汇编中,大部分指令都是和CPU和内存相关的

总线

总线 是CPU和内存之间的桥梁,如下图所示,是iPhoneX上的A11(CPU芯片)

从图中可以看出:每一个CPU芯片都有很多管脚,这些管脚和总线相连,CPU通过总线跟外部件进行交互

总线:是一根根导线的集合

总线的分类

总线主要分为三类,如下图所示:

  • 1、地址总线:CPU是通过地址总线来指定存储单元的
  • 2、数据总线:CPU与内存/其他部件之间的数据传送通道
  • 3、控制总线:CPU通过控制总线对外部器件进行控制

举例:CPU从内存的3号单元读取数据

  • 1、CPU想操作内存中的数据,首先需要找到内存地址:CPU通过地址总线,将3这个地址传递给内存你,即寻址到内存的3号单元

  • 2、需要操作3号单元的数据,还需要确定是读还是写:CPU通过控制总线告诉内存需要进行的操作,假设是读

  • 3、内存知道了CPU想要进行的操作:内存将3号单元的数据通过数据线传递给CPU

地址总线

  • 它的宽度决定了 CPU的寻址能力,即地址总线决定了CPU所能访问的最大内存空间的大小,例如:10根地址线 能访问的最大内存是 2^10 = 1024 位二进制数据(即 1KB

  • 地址总线是地址线数量之和

  • 8086地址总线 宽度是 20,所以寻址能力是 1M(即2^20)

  • 内存地址的单元是 字节byte(简写B),每个字节里面可以放 8位(即bit),以下是内存条的图示:

注意区分 数量单位容量单位

  • 数量单位:1M = 1024K,1K = 1024
  • 容量单位:字节byte(B) 1024B = 1KB,1024KB = 1MB,IBM银行的独立系统是以2字节为一个单位,常用的电脑是以1字节为一个单位
  • 网络宽带 100M=100Mbps(比特位,每秒传输 100/8 = 12.5MB/s

数据总线

  • 它的宽度决定了 CPU的单次数据传送量(即吞吐量),也就是 数据传送速度 即CPU和外界数据的传送速度

  • 每条数据线一次只能传输一位二进制数据,例如:8根 数据线 一次 可传送 一个8位 二进制数据(即一个字节的数据)

  • 数据总线是数据线数量之和

  • 8086数据总线 总宽度是 16,所以单次最大传送 2个字节 的数据

我们常说的32位(4字节)、64位(8字节)CPU,这里的32、64指的就是数据吞吐量

控制总线

  • 它的宽度决定了 CPU对其他器件的控制能力,能有多少中控制,即CPU对外部器件的控制能力

  • 控制总线是控制线数量之和

小练习

  • 一个CPU的寻址能力为8KB,那么它的地址总线的宽度为 2^13

答:我们知道 10根 -> 2^0 -> 1KB,所以,8KB -> 2^3 -> 13根

内存

  • CPU是通过 总线 和硬件设备连接的

  • 内存有RAM主存储器、RAM主存储器(内存条)

  • 下图是按照物理地址划分的内存,有 主存储器、显存地址、显卡地址、网卡地址、系统地址

其中内存中的 低地址 是给 用户用的高地址 是给 系统用的,如下所示:

  • 内存地址空间的大小受CPU地址总线宽度的限制,8086的地址总线宽度为20,可以定位2^20个不同的内存单元(内存地址范围0x00000~0xFFFFF),所以8086的内存空间大小为1MB

  • 0x00000~0x9FFFF:主存储器,可读可写

  • 0xA0000~0xBFFFF:向显存中写入数据,这些数据会被显卡输出到显示器,可读可写

  • 0xC0000~0xFFFFF:存储各种硬件/系统信息,只读

进制

很多人学不好进制,原因是总以十进制为依托去考虑其他进制,需要运算的时候也总是先转换为十进制,在转换为其他进制,其实这种方式是错的

我们为什么一定要转换成十进制呢?仅仅是因为我们对十进制最熟悉,所以才转换

每一种进制都是完美的,想学号进制首先要忘掉十进制,也要忘掉进制间的转换

进制的定义

  • 八进制由8个符号组成:0 1 2 3 4 5 6 7 逢八进一
  • 十进制由10个符号组成:0 1 2 3 4 5 6 7 8 9 逢十进一
  • N进制就是由N个符号组成:逢N进一
1
2
3
4
5
6
7
8
9
<!--练习-->
1+1在___情况下等于3

<!--答案-->
十进制由10个符号组成: 0 1 3 2 8 A B E S 7 逢十进一
如果这样定义十进制:1+1等于3

<!--目的-->
传统定义的十进制和自定义的十进制不一样,如果不告诉别人符号表,别人是无法拿到具体的数据的。这样的应用场景主要是用于加密

进制的运算

八进制

八进制加法表

1
2
3
4
5
6
7
8
9
10
11
12
0  1  2  3  4  5  6  7 
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
...

1+1 = 2
1+2 = 3 2+2 = 4
1+3 = 4 2+3 = 5 3+3 = 6
1+4 = 5 2+4 = 6 3+4 = 7 4+4 = 10
1+5 = 6 2+5 = 7 3+5 = 10 4+5 = 11 5+5 = 12
1+6 = 7 2+6 = 10 3+6 = 11 4+6 = 12 5+6 = 13 6+6 =14
1+7 = 10 2+7 = 11 3+7 = 12 4+7 = 13 5+7 = 14 6+7 =15 7+7 = 16

八进制乘法表

1
2
3
4
5
6
7
8
0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27...
1*1 = 1
1*2 = 2 2*2 = 4
1*3 = 3 2*3 = 6 3*3 = 11
1*4 = 4 2*4 = 10 3*4 = 14 4*4 = 20
1*5 = 5 2*5 = 12 3*5 = 17 4*5 = 24 5*5 = 31
1*6 = 6 2*6 = 14 3*6 = 22 4*6 = 30 5*6 = 36 6*6 = 44
1*7 = 7 2*7 = 16 3*7 = 25 4*7 = 34 5*7 = 43 6*7 = 52 7*7 = 61

做个练习

  • 2 + 3 = ___,2 * 3 = ___,4 + 5 = ___,4 * 5 = ___
  • 277 + 333 = ___,276 * 54 = ___, 237 - 54 = ___ ,234/4 = ___

第一排的计算,我们可以很好的得出结论
但是第二排涉及数据较大,如何计算呢?下面以 277 + 333 为例,计算过程如下:

1
2
3
4
实际上是以加法表为基本的每个位置相加
277 最后一位相加 倒数第二位相加 第一位相加
+ 333 -> 7+3=12 -> 7+3=12 -> 2+3=5 -> 所以最后的结果是632
保留2进1 保留2+1=3,进1 保留5+1=6

二进制

二进制的简写形式

1
2
3
4
5
       二进制: 1 0 1 1 1 0 1 1 1 1 0 0
三个二进制一组: 101 110 111 100
八进制: 5 6 7 4
四个二进制一组: 1011 1011 1100
十六进制: b b c

使用二进制从0到1111:0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

发现这样使用二进制太麻烦,所以将其改为更简单一点的符号

0 1 2 3 4 5 6 7 8 9 A B C D E F 这就是十六进制了

数据的宽度

数学上的数字是没有大小限制的,可以无限大

但是在计算机中,由于硬件的制约,数据都是有长度限制的(称为 数据宽度),超过最多宽度的数据会被丢弃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int test(){
int cTemp = 0x1FFFFFFFF;
return cTemp;
}

int main(int argc, char * argv[]) {
printf("%x\n",test());
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

打断点在 int cTemp 处和 return cTemp 处,调试结果发现 0 溢出了:

也可以此处通过获取的地址,然后在 Debug-Debug Workflow-ViewMemory 中输入地址(0x000000016d82f70c) 查看

计算机中常见的数据宽度

  • 位(bit)1个位 就是 1个二进制,即 0或1
  • 字节(byte)1个字节8个bit 组成,内存中的最小单元byte
  • 字(Word)1个字两个字节 组成(16位),第2个字节分别称为 高字节和低字节
  • 双字(DoubleWork):1个双字由两个字组成(32位)

那么计算机存储数据它分为 有符号数和无符号数,如下图所示:

  • 无符号数,直接换算

  • 有符号数,符号放在第1位,第1位是0即 正数,为1即 负数

    • 正数:0 1 2 3 4 5 6 7
    • 负数:F E D C B A 9 8
      -1 -2 -3 -4 -5 -6 -7 -8

自定义进制符号

【练习1】

现在有10进制数10个符号分别为:2,9,1,7,6,5,4,8,3,A 逢10进1,那么:

123 + 234 = (AA6)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
十进制:    0  1  2  3  4  5  6  7  8  9
自定义: 2 9 1 7 6 5 4 8 3 A
(十进制10)92 99 91 97 96 95 94 98 93 9A
12 19 11 17 16 15 14 18 13 1A
72 79 71 77 76 75 74 78 73 7A
62 69 61 67 66 65 64 68 63 6A
52 59 51 57 56 55 54 58 53 5A
42 49 41 47 46 45 44 48 43 4A
82 89 81 87 86 85 84 88 83 8A
32 39 31 37 36 35 34 38 33 3A
922

(00)2 (01)9 (02)1 (03)7 (04)6 (05)5 (06)4 (07)8 (08)3 (09)A
(10)92 (11)99 (12)91 (13)97 (14)96 (15)95 (16)94 (17)98 (18)93 (19)9A
(20)12 (21)19 (22)11 (23)17 (24)16 (25)15 (26)14 (27)18 (28)13 (29)1A
(30)72 (31)79 (32)71 (33)77 (34)76 (35)75 (36)74 (37)78 (38)73 (39)7A
(40)62 (41)69 (42)61 (43)67 (44)66 (45)65 (46)64 (47)68 (48)63 (49)6A
(50)52 59 51 57 56 55 54 58 53 5A
(60)42 49 41 47 46 45 44 48 43 4A
(70)82 89 81 87 86 85 84 88 83 8A
(80)32 39 31 37 36 35 34 38 33 3A
(90)922

刚才通过10进制运算可以转换,然后查表,但是如果是其他进制,就不能转换,要学会直接查表。

【练习2】

现在有9进制数9个符号,分别是:2,9,1,7,6,5,4,8,3 逢9进1,那么:123 + 234 = (9926)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
十进制:    0  1  2  3  4  5  6  7  8  
自定义: 2 9 1 7 6 5 4 8 3
92 99 91 97 96 95 94 98 93
12 19 11 17 16 15 14 18 13
72 79 71 77 76 75 74 78 73
62 69 61 67 66 65 64 68 63
52 59 51 57 56 55 54 58 53
42 49 41 47 46 45 44 48 43
82 89 81 87 86 85 84 88 83
32 39 31 37 36 35 34 38 33
922

(00)2 (01)9 (02)1 (03)7 (04)6 (05)5 (06)4 (07)8 (08)3
(10)92 (11)99 (12)91 (13)97 (14)96 (15)95 (16)94 (17)98 (18)93
(20)12 19 11 17 16 15 14 18 13
(30)72 79 71 77 76 75 74 78 73
(40)62 69 61 67 66 65 64 68 63
(50)52 59 51 57 56 55 54 58 53
(60)42 49 41 47 46 45 44 48 43
(70)82 89 81 87 86 85 84 88 83
(80)32 39 31 37 36 35 34 38 33
(90)922 ...

CPU和寄存器

内部部件之间是由 总线 连接,如下图所示:

  • CPU除了有 控制器、运算器,还有 寄存器,其中寄存器的作用就是 运行数据的临时存储

  • CPU的运算速度是非常快的,为了性能 CPU 在内部 开辟了一小块临时存储区域,并在进行运算时先将数据从内存中 复制 到这一小块临时区域中,运算就在这一小块临时存储区进行,称这一小块临时存储区域为 寄存器

【针对arm64的CPU来说】

  • 如果寄存器以 x 开头,则表明是一个 64位(84/8=8字节)的寄存器z

  • 如果寄存器以 w 开头,则表明是一个 32位(32/8=4字节) 的寄存器

在系统中没有提供16位和32位的寄存器供访问和使用,其中 32位的寄存器是64位寄存器的低32位的部分,并不是独立存在的

  • 对于程序来说,CPU中最主要的部件是 寄存器,可以通过改变寄存器的内容来实现对CPU的控制

  • 不同CPU,寄存器的个数和结构是不相同的

查看寄存器

默认情况下是不显示的,如下图:

选中后,会出现三种寄存器,如下图:

浮点和向量寄存器

因为浮点数的存储以及其运算的特殊性,CPU中专门提供 浮点寄存器 来处理浮点数

  • 浮点寄存器

    • 64位:D0-D31
    • 32位:S0-S31

现在 CPU支持向量运算(向量运算在图形处理相关的领域用的非常多),为了支持向量计算,系统也提供了众多的向量寄存器

  • 向量寄存器 128 位:V0 - V31

通用寄存器

  • 通用寄存器也称为 数据地址寄存器。通常用来 做数据计算的临时存储、累加、计数、地址保存等功能。定义这些寄存器的作用主要是用于在CPU指令中保存操作数,在CPU中当做一些常规变量来使用

ARM64中

  • 64位:x0-x30,XZR(寄存器)

  • 32位:W0-W30,WZR(零寄存器)

  • arm64拥有 32个64位的通用寄存器X0-X30,以及XZR(零寄存器)。这些通用寄存器有时也有特定用途

    • 那么 w0-w28 这些32位的,因为64位CPU可以兼容32位,所以可以只使用64位寄存器的低32位
    • 例如 w0就是x0的低32位
1
注意:了解过8086汇编的一定知道,还有一种特殊的寄存器段寄存器:CS、DS、SS 、ES。这四个寄存器主要用来保存这些段的基地址,是属于Intel架构的CPU的,在arm中并没有
  • 通常,CPU会先将内存中的数据存储到通用寄存器中,然后再对寄存器中的数据进行运算

例子:假设内存中有块红色内存空间的值是3,现在想把它的值加1,并将结果存储到蓝色内存空间,如何做呢?

  • CPU首先会将红色内存空间的值放到X0寄存器中:mov X0,红色内存空间

  • 然后让X0寄存器与1相加:add X0,1

  • 最后将值赋值给内存空间:mov 蓝色内存空间,X0

PC寄存器

  • 指令指针寄存器,它 指示了CPU当前要读取指令的地址

  • 在内存/磁盘中,指令和数据没有任何区别,都是二进制信息

  • CPU在工作时,将有的信息看做指令,有的信息看做数据,为同样的信息赋予了不同的意义

    • 例如 1110 0000 0000 0011 0000 1000 1010 1010
    • 可以当做数据 0xE003008AA
    • 也可以当做指令 mov x0,x8
  • CPU根据什么将内存中的信息看作指令呢?

    • CPU将pc指向的内存单元的内容看作指令
    • 如果内存中的某段内容曾经被CPU执行过,那么它所在的内存单元必然被pc指向过

寄存器的案例分析

下面通过以下代码的例子来分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int test(){
int cTemp = 0x1FFFFFFFF;
return cTemp;
}

int main(int argc, char * argv[]) {
printf("%x\n",test());
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
  • 以下是demo的汇编图示

pc寄存器调式

  • 打印 pc 寄存器,现在是 d613c

  • 按住 control+Setp into,继续打印

除了读还可以写:

  • register write pc 0x1025d6134
  • register read pc 此时是读不出来的,因为断点断住了,如果step into ,此时断点断在哪里?

高速缓存

iPhoneX上搭载的arm处理器 A11,它的1级缓存的容量是64Kb,2级缓存的容量是8M

CPU每执行一条指令前都需要从内存中将指令读取到CPU内存并执行,而寄存器的运行速度相比内存读写要快很多,为了性能,CPU还集成了一个 高速缓存区域。当程序运行时,先将要执行的指令代码以及数据复制到高速缓存中(由操作系统完成),然后CPU直接从高速缓存依次读取指令来执行

bl指令

  • CPU从何处执行指令,是由pc中的内容决定的,可以 通过改变pc的内容来控制CPU执行目标指令
  • arm64提供了一个 mov指令(传送指令),可以用来改变大部分寄存器的值,例如 mov x0,#10、mov x1,#20
  • 但是,mov指令并不能用于设置pc的值,arm64没有提供这样的功能
  • arm64提供了另外的指令来 修改pc的值,这些指令统一称为 转移指令,其中最简单的是 bl指令

bl指令练习

现在有两段代码,假设程序先执行A,请写出指令执行顺序,最终寄存器x0的值是多少?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
_A:
mov x0,#0xa0
mov x1,#0x00
add x1, x0, #0x14
mov x0,x1
bl _B
mov x0,#0x0
ret

_B:
add x0, x0, #0x10
ret

// 分析流程
流程:
mov x0,#0xa0 -- x0:0xa0
mov x1,#0x00 -- x1:0x00
add x1, x0, #0x14 -- x1:0xa0+0x14=0xb4
mov x0,x1 -- x0:0xb4
bl _B -- 跳转到B
add x0, x0, #0x10 -- x0:0xb4+0x10=0xc4
ret -- 回到bl跳转的下一行
mov x0,#0x0 -- x0:0x00

// 结果
x0的值:0x00

汇编代码验证

下面来写一段汇编代码验证(command + n -> empty -> asm.s)(汇编代码文件,会编译成源码)

如何执行呢?

  • 在VC中定义函数的声明

  • mov x0,#0xa0 执行处加断点,并执行程序,开启汇编调试

  • 按住 control+step into,进入A的具体汇编

  • 继续 control+step into,到 bl _B

  • 按住 control+step into,进入汇编代码B

  • 执行到A的ret

疑问: 发现走到这里死循环了,这是为什么呢?预知后事如何,请看下一篇

总结

  • 1、汇编概述

    • 使用 助记符代替机器指令 的一种编程语言

    • 汇编和机器指令是 一一对应 的关系,拿到二进制就可以反汇编

    • 由于汇编和CPU的指令集是对应的,所以汇编不具备移植性

  • 2、总线:是由一堆导线的集合

    • 地址总线:其宽度决定了寻址能力

    • 数据总线:其宽度决定了CPU数据的吞吐量

    • 控制总线:其宽度决定了CPU对其他器件的控制能力

  • 3、进制

    • 任意进制都是由对应个数的符号组成的,符号可以自定义

    • 2/8/16是相对完美的进制,他们之间的关系

    • 3 个二进制使用一个 8进制 标识

    • 4 个二进制使用一个 16进制 标识

    • 两个16进制可以标识一个字节,即8位

  • 数量单位

    1024 = 1k,1024k = 1M,1024M = 1G

  • 容量单位

    1024 = 1KB,1024KB = 1MB,1024MB = 1GB

  • 数据的宽度

    计算机中的数据是有宽度的,超过了就会溢出

  • 4、寄存器:CPU为了性能,自内部开辟了一小块临时存储区域

    • 浮点向量寄存器:用于浮点数/向量的存储及运算

    • 异常状态寄存器

    • 通用寄存器:除了存放数据有时也有特殊的用途

      • ARM64拥有32个64位的通用寄存器 X0-X30 以及XZR(零寄存器)

      • 为了兼容32位,所以arm64位拥有 W0-W28 以及WZR 30个32位寄存器

      • 32位寄存器并不是独立存在的,例如 W0是X0的低32位

    • PC寄存器:指令指针寄存器

      • PC寄存器里面的值保存的就是CPU接下来需要执行的指令地址

      • 改变PC的值可以改变程序的执行流程

      • mov指令不能更改PC寄存器的值,需要通过bl跳转指令来改变PC寄存器的值

  • Post title:OC逆向01:初始汇编
  • Post author:张建
  • Create time:2022-04-20 15:50:53
  • Post link:https://redefine.ohevan.com/2022/04/20/OC逆向/OC逆向01:初始汇编/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.