Emiter0 2019-12-28
今天进入逆向开发的另一个部分--汇编知识的讲解,分为上下篇,希望通过两篇博客的讲解让大家对汇编知识有个大致的了解!!!
机器语言:有0和1共同组成的机器语言
汇编语言:使用助记符来代替机器语言
高级语言:比如Java,Objective-C
iPhone使用的是ARM汇编,但是不同的手机设备以及架构是不同的
APP/程序执行过程
如果想深入了解汇编,下面将讲解几个插曲。
硬件最重要就是CPU和内存
总线是一根根导线的集合
总线分为地址总线、数据总线、控制总线三种
地址总线宽度决定了CPU的寻址能力
8086地址总线是20,其寻址能力是2^20 = 1M
数据总线宽度决定了CPU单次传递的数据量,换句话说也是数据的传送速度
8086的数据宽度为16,单次最大传送数据量为2个字节
控制总线宽度决定了CPU对其他控件的控制能力
在存储数据时,分为有符号和无符号数
内部部件之间是由总线来相连
CPU最重要的部件是寄存器,日常工作中,通过改变寄存器的值来实现对CPU的值。
ARM64有31个64位通用寄存器X0-X30,通常用来存储一般性的数据,有时候也会有特定用途,称之为通用寄存器。
W0-W28是32位,是X0-X32的低28位,而64位CPU是兼容32位的CPU,所以使用64位的低32位。W0就是X0。
CPU一般先将内存的数据存储到通用寄存器中,然后再对此进行运算。
CPU由计算器,控制器以及寄存器组成,其中,寄存器的作用将数据进行临行存储起来.
CPU的运行速度非常快, 为了性能的提高, CPU会在内部开辟小块的临时存储区域, 并在运算时先将数据从内存复制到这小块临时存储区域中, 在这小块区域进行运算,这小块临时区域就称作寄存器.
对于ARM64架构的CPU, 以 X 开头的就是64位的寄存器, 以 W 开头的就是32位的寄存器, 其中32位寄存器就是64位寄存器的低32位部分
系统中没有提供16位 和 8位的寄存器供以访问(注意: 查看时要使用真机调试, 模拟器使用的X86的架构)
iPhoneX搭载的ARM64处理器A11, 它的一级缓存容量是64KB, 二级缓存容量是8M (现在普遍也只有二级缓存)
注意: 8086汇编中有一种寄存器, 段寄存器: CS, ES, DS, SS四个寄存器用来保存段的基地址, 这属于Intel CPU中, 在ARM中没有.
现在CPU支持向量运算(向量运算在图形处理中使用比较广泛), 为支持向量运算, 故提供了更多向量寄存器.
因为浮点数以及其运算的特殊性, CPU专门提供浮点寄存器来计算浮点数
注意: ARM64开始取消32位的LDM, STM, PUSH, POP指令. 与之替代的是 ldr/ ldp, str/ stp
ARM64里面 对栈的操作都是16进制对齐的!!!
内存的读写指令
str(store register)写入指令
将数据从寄存器中读出来, 写入到内存中
ldr(load register)读取指令
将数据从内存中读取出来, 存到寄存器中
ldp/stp 是 ldr/str 的衍生, 可以同时读/写两个寄存器, ldr/str只能读写一个
sub sp, sp, #0x20 ; 拉伸栈空间32(20 = 2*16)个字节 stp x0 , x1, [sp, #0x10] ; sp往上加16(10 = 1 * 16)个字节,存放x0 和 x1 ldp x1 , x0, [sp, #0x10] ; 将sp偏移16个字节的值取出来,放入x1 和 x0
注意: 拉伸栈空间是往低地址拉伸, 拉伸的字节数只能是16的倍数, 否则会崩溃(对照上面 16进制对齐理解 )
bl: 跳转指令 1. 将下一条指令的地址存放到 lr(x30) 寄存器中 2. 跳转到对应函数中执行指令
ret: 返回指令 默认使用 lr(x30) 寄存器的值, 通过底层指令提示CPU这是下一条指令的地址. ARM64架构中的特色指令, 面向硬件做了优化处理
注意: 在函数嵌套调用中, 需要将x30入栈, 否则可能会造成死循环.
注意: CPSR 寄存器是32位的
CPSR的低8位(包括 I , F, T 和 M[4-0])称为控制位, 程序无法修改, 除非CPU运行于特权模式下, 才能修改控制位.
N Z C V均为条件码标志位, 它们的内容可被算术或逻辑运算的结果所改变, 并且决定某条指令是否被执行, 意义重
CPSR 第31位是N, 符号标志位. 它记录相关指令执行后, 其结果是否为负, 如果为负,则 N 为1; 如果非负则N为0.
CPSR 第30位是Z, 0标志位. 它记录相关指令执行后, 其结果是否为0, 如果为0,则Z为1; 如果非0则Z为0.
CPSR 第29位是C, 进位标志位. 一般情况下, 进行无符号的运算. 加法运算: 当运算结果产生了进位时(无符号位溢出), 则 C = 1, 否则C=0. 减法运算(包括CMP): 当运算结果产生了借位时(无符号数溢出), 则C=0,否则C=1.
对于位数为N的无符号数来说,其对应的二进制信息的最高位,即第N - 1位,就是它的最高有效位,而假想存在的第N位,就是相对于最高有效位的更高位。如下图所示:
mov w0,#0xaaaaaaaa;0xa 的二进制是 1010 adds w0,w0,w0; 执行后 相当于 1010 << 1 进位1(无符号溢出) 所以C标记 为 1 adds w0,w0,w0; 执行后 相当于 0101 << 1 进位0(无符号没溢出) 所以C标记 为 0 adds w0,w0,w0; 重复上面操作 adds w0,w0,w0
mov w0,#0x0 subs w0,w0,#0xff ; subs w0,w0,#0xff subs w0,w0,#0xff
以上就是关于汇编知识点内容,希望对大家有所帮助,进入了解技术语言的底层知识!!!