认识ARM64汇编





之前说过学习汇编就是学习寄存器和指令,查看代码请连接真机。

寄存器

arm64汇编中寄存器是64bit的,使用X[n]表示,低32位以w[n]表示

64位架构中有3164位的通用寄存器。

可以通过register read查看

x0~x7:一般是函数的参数,大于8个的会通过堆栈传参。

可以看到当参数的个数大于8个的时候就不会从寄存器中去取参数了。

x0:一般表示返回值

汇编代码

通过lldb指令

确实是10

pc:表示当前执行的指令的地址

这个类似8086汇编里面的ip

比如我们断点该改代码处,查看pc寄存器的值

lr:链接寄存器,存放着函数的返回地址

lr也就是x30,这个里面存放着函数的返回地址

比如有下面2个方法,方法fooFp方法内部调用fooFp2

fooFp的汇编代码

0x100dbe788 <+28>: bl 0x100dbe798这行就是在调用方法fooFp2,如果调用完fooFp2后函数应该要继续执行,那么肯定是要到0x100dbe788 <+28>: bl 0x100dbe798下一行也就是地址0x100dbe78c处,我们到fooFp2中查看下lr寄存器的值

当然, 本质上还是将lr的值给了pc寄存器了,也就是ret指令做的事情。

栈寄存器

分为sp栈顶寄存器和fp栈底寄存器。(如果熟悉8086汇编的话类似于分别类似于spbp

还是用上面的方法fooFpfooFp2来说明这2个寄存器。

不嫌啰嗦这边还是复制下fooFp的汇编代码

整个过程如下图

cpsr:程序状态寄存器

cpsr(Current Program Status Register )

spsr (Saved Program Status Register) 异常状况下使用

xzr:零寄存器

表示zero register,一般用来默认值,里面存储的值都是0。

  1. xzr:64位的
  2. wzr:32位的

指令

寻址方式大概规则说明

  1. []一般表示是取值的意思,[R2]表示取出R2所存的内存地址比如是0x10000所对应的值比如是66
  2. LDR R0 [R1,#4] :寄存器 R1 的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器 R0 中。
  3. LDR R0,[R1,#4]!:将寄存器 R1 的内容加上 4 形成操作数的有效地址,从而取得操作数存入寄 存器 R0 中,然后,R1 的内容自增 4 个字节。
  4. LDR R0,[R1] ,#4:以寄存器 R1 的内容作为操作数的有效地址,从而取得操作数存入寄存器 R0 中,然后,R1 的内容自增 4 个字节。
  5. LDR R0,[R1,R2]:将寄存器 R1 的内容加上寄存器 R2 的内容形成操作数的有效地址,从而取得 操作数存入寄存器 R0 中。

计算指令

ADD 加法

SUB 减法

逻辑运算

AND逻辑与、EOR逻辑异或、ORR逻辑或、LSL逻辑左移、LSR逻辑右移

内存指令

一般是ST开头的为存数据,比如说STRSTPSTUR
LD开头的表示取数据,比如说LDRLDPlDUR

P:可以理解为pair
u: 表示负数

跳转指令

bbl一般搭配cmp指令使用

b:无条件跳转,一般是什么函数内部的ifswitch条件判断;
bl:带函数返回值的跳转,一般是调用其他的函数;

<1>. CMP:将寄存器 R1 的值与立即数 0x1 相减,并根据结果设置 CPSR 的标志位

标志位的可能值如下表

条件码 助记符后缀 标志 含义
0000 EQ Z 置位 相等 ==
0001 NE Z 清零 不相等 !=
0010 CS C 置位 无符号数大于或等于
0011 CC C 清零 无符号数小于
0100 MI N 置位 负数
0101 PL N 清零 正数或零
0110 VS V 置位 溢出
0111 VC V 清零 未溢出
1000 HI C 置位 Z 清零 无符号数大于
1001 LS C 清零 Z 置位 无符号数小于或等于
1010 GE N 等于 V 带符号数大于或等于
1011 LT N 不等于 V 带符号数小于
1100 GT Z 清零且(N 等于 V) 带符号数大于
1101 LE Z 置位或(N 不等于 V) 带符号数小于或等于
1110 AL 忽略 无条件执行

<2>. b.le 0x100432630:表示如果w10 <= 0x1那么就执行0x100432630

ret指令

  1. 函数返回
  2. lr(x30)寄存器器的值赋值给pc寄存器器。

了解了这些基本知识读一些汇编代码应该没问题了,没有提到的自己查下资料也差不多了。

ARM-GNU汇编

如果你只会arm汇编去看runtime汇编源码的时候会发现还是有些东西不明白,比如下面的代码

ARM汇编开发指用ARM提供的汇编指令,进行ARM程序的开发。
ARM汇编开发,有两种开发方式,一种是使用ARM汇编,一种是使用ARM GNU汇编。两种汇编开发,使用的汇编指令是完全一样的,区别是宏指令,伪指令,伪操作不一样。其实两种开发方式的区别在于所使用的编译工具不一样。
对于ARM汇编,使用的是ARM公司开发的编译器,而ARM GNU汇编,是使用GNU为ARM指令集开发的编译器,也就是arm-gcc。

2种方式的不同之处就是伪操作的不同,苹果遵循的是GNU汇编规范的。点击这个可以查看各个伪操作的意思,比如:

.global:全局声明;
.macro:定义一个宏;
.align:对齐方式
.text:指定程序在哪个段
...

关于汇编还有很多,比如书写汇编代码,内联汇编,有了目前的基础,相信学起来也是很快的。

感谢

  1. https://zh.wikipedia.org/wiki/ARM%E6%9E%B6%E6%A7%8B#cite_note-v8arch-1
  2. https://www.arm.com/files/downloads/ARMv8_Architecture.pdf
  3. http://www.lujun.org.cn/?p=3943
  4. https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/Assembler/000-Introduction/introduction.html#//apple_ref/doc/uid/TP30000851-CH211-SW1

参考链接


认识ARM64汇编

发布者

发表评论

电子邮件地址不会被公开。 必填项已用*标注