zl程序教程

您现在的位置是:首页 >  其他

当前栏目

iOS汇编之ARM64基础介绍

2023-04-18 13:12:18 时间

大小端

计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。

但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

0x1234567的大端字节序和小端字节序的写法如下图:

ARM64寄存器

可以通过register read查看

通用寄存器

arm64提供了31个64位通用寄存器。参数寄存器是x0 ~ x7,大于8个会通过堆栈传参,x0一般表示返回值。

x8:间接寻址结果,当返回值(比如结构体size)大于16个字节的时候,该返回内容会被存到一个内存地址当中,然后这个内存地址的值会存入寄存器x8。

w0表示x0的低32位。

浮点寄存器

v0 ~ v31,一共有32个浮点寄存器,每个寄存器大小是128位。分别可以用的方式来访问不同的位数。可以通过Bn、Hn、Sn、Dn、Qn来访问不同的位数。

Bn:8位

Hn:16位

Sn:32位

Dn:64位

Qn:128位

参数寄存器:v0 ~ v7

特殊寄存器

WZR(word zero rigiser)或者XZR(64位)

寄存器r31是一个特殊的寄存器: Zero Register: 在大多数情况下,作为源寄存器使用时, r31读出来的值 是0; 作为目标寄存器使用时, 丢弃结果。 WZR(word zero rigiser)或者XZR(64位) Stack Register: 当 用作load/store 的base register时, 或者 一些算术指令中, r31提供当前的stack pointer WSP或者 SP

堆栈指针sp

sp,即x31,指向堆栈的顶部。每一个异常级别都有一个专用的SP寄存器。

程序计数器pc

pc,保存着当前CPU执行指令的地址。

链接寄存器lr

lr,既x30,存储着函数的返回地址。

FP栈帧地址

fp,即x29。保存当前栈帧的栈底为止。

寻址方式

立即寻址

操作数直接包含在指令中,把该操作数称为立即数。

MOV  AL, 6                 ;(AL)=6
MOV  AX, 3064H             ;(AX)=3064
复制代码

直接寻址

操作数的有效地址直接包含在指令中的寻址方式。这种寻址方式常用于存取简单变量。

MOV  AL, [78H]
复制代码

寄存器寻址

操作数直接包含在寄存器中,由指令指定寄存器号的寻址方式。

MOV  BX, AX                    ;(BX)=(AX)
复制代码

寄存器间接寻址

操作数的有效地址在基址寄存器中,而操作数在存储器中的寻址方式。

MOV  AL, [BX]
复制代码

寄存器相对寻址

也称为直接变址寻址方式。操作数的有效地址是一个基址(BX、BP)或变址(SI、DI)寄存器的内容和指令中给定的一个位移量(disp)之和。有效地址由2部分组成。

即:EA=(基址<或变址>寄存器)+disp

或:EA=(32位通用寄存器)+disp(386型号以上)

MOV  AL, 8[BX] 
MOV  AL, [BX+8]
复制代码

基址变址寻址

操作数的有效地址是一个基址寄存器(BX、BP)和一个变址寄存器(SI、DI)的内容之和

MOV AL,[BX][SI] 
MOV AL,[BX+SI]
复制代码

汇编指令介绍

参考链接

leylfl.github.io/2018/05/15/…

.MACRO/.ENDM

用.MACRO指令可以定义一个宏,可以把需要重复执行的一段代码,或者是一组指令缩写成一个宏。

str/ldr指令

str(store register):写入指令,将数据从寄存器中读出来,写入到内存中。

ldr(load register):读取指令,将数据从内存中读取出来,存到寄存器中。

str(条件) 源寄存器, <存储器地址>
ldr(条件) 目的寄存器, <存储器地址>
复制代码

ldp/stp指令

是ldr/str的衍生,可以同时读/写两个寄存器。

b/bl/blr指令

b指令:最简单的跳转指令。一旦遇到一个b指令,ARM处理器将立即跳转到给定的目标地址,从那里继续执行。

bl指令:同样是跳转指令,但是在跳转之前,会将下一条指令保存到LR寄存器中,因此,可以通过将lr的内容重新加载到pc中,来返回到跳转指令之后的那个指令处执行。

blr指令:与BL指令相似,但是跳转地址是从特定的寄存器中取得。

bl _hook_objc_msgSend_after
blr x17
复制代码

mov指令

mov指令可完成从另一个寄存器、被移位的寄存器或将一个l立即数加载到目的寄存器。其中s选项决定指令的操作是否影响CPSR中条件标志位的值,当没有s时指令不更新CPSR中条件标志位的值。

mov{条件}{s} 目的寄存器,源操作数
复制代码

adr/adrp伪指令

adr指令:小范围的地址读取指令。ADR指令将基于PC相对偏移的地址读取到寄存器。

原理:将有符号的21位的偏移,加上PC,结果写入到通用寄存器,可用来计算+/-1MB范围的任意字节的有效地址。

adrp指令:以页为单位的大范围的地址读取指令。

原理:将有符号的21位偏移,向左移动12位,PC的值低12位清零,然后把两者相加,结果写入到寄存器。范围:+/-4KB * 1M = +/-4GB。

    adrp    x17, _origin_objc_msgSend@PAGE     #label页偏移
    ldr    x17, [x17, _origin_objc_msgSend@PAGEOFF]		#label页内偏移
    blr x17
复制代码

栈帧布局

参考链接

developer.arm.com/documentati…

juejin.cn/post/684490…

cloud.tencent.com/developer/a…

en.wikipedia.org/wiki/Call_s…

www.cs.cornell.edu/courses/cs4…

eli.thegreenplace.net/2011/09/06/…