汇编 - ARM64
1. 汇编文件
1.1 生成汇编文件
xcrun --sdk iphoneos clang -S -arch arm64 main.c -o main.s
1.2 新建汇编文件
汇编文件.s
后缀名,如xxx.s
1.2.1 基础汇编文件
新建Test.h
文件,声明test
函数
#ifndef Test_h
#define Test_h
void test(void);
#endif /* Test_h */
新建Test.s
文件,写入以下指令:
- 实现
test
函数。头文件声明的test
函数,对应函数实现
名称是_test
.global _test
代表_test
这个函数是公开的,需要增加这句才能正常编译
.text
.global _test
_test:
mov x0, 8
ret
在mov
指令处打个断点
在main
函数中调用:
运行:
至此,我们就使用汇编
语言,实现了一个test
方法,并在main
函数中调用了
arm64中
立即数
写法是#0x8
,我们自己写的汇编也改成这样的
2. 寄存器
2.1 通用寄存器
64bit
的:x0 ~ x28
32bit
的:w0 ~ w28
(属于x0 ~ x28
的低32bit
)x0 ~ x7
通常拿来存放函数的参数,更多的参数使用堆栈
来传递x0
通常拿来存放函数的返回值
2.2 程序计数器(pc:Program Counter)
- pc(Program Counter)
- 记录CPU
当前执行
的是哪一条指令 - 存储着当前CPU
正在执行
的指令的地址 - 类似8086汇编的ip寄存器
2.3 堆栈指针
2.3.1 sp
(Stack Pointer)
2.3.2 fp
(Frame Pointer),也就是x29
2.4 链接寄存器
2.4.1 lr
(Link Register),也就是x30
2.4.2 存储着函数
的返回地址
2.5 程序状态寄存器
2.5.1 cpsr
(Current Program Status Register)
2.5.2 spsr
(Saved Program Status Register),异常状态下使用
3. 指令
指令列表:
寻址方式
3.1 mov
指令说明:
示例:
mov x0, #0x8
运行:
断点停在该行,我们使用lldb
指令读一下x0
:
register read x0
使用si
往下执行一条指令,此时再读一下x0
:
此时已经将入立即数8
存入x0
寄存器
3.2 ret
- 函数返回
- 将
lr
(x30
)存储器的值赋值给pc
寄存器
3.3 add 加法
指令说明:
示例:
mov x0, #0x8
mov x1, #0x2
add x2, x0, x1
给x0
、x1
赋值,然后加起来赋值给x3
3.4 sub 减法
指令说明:
示例:
mov x0, #0x8
mov x1, #0x2
sub x2, x0, x1
给x0
、x1
赋值,然后x0
-x1
赋值给x3
3.5 cmp
指令说明:
- 将
2个
寄存器相减
相减
的结果会影响cpsr
寄存器的标志位
示例:
mov x0, #0x8
mov x1, #0x2
cmp x0, x1
cmp x1, #0x3
cmp x1, #0x1
cmp x1, #0x2
使用指令
p/t $cpsr
,以二进制
形式打印cpsr
的值
3.6 跳转指令(b、bl)
3.6.1 b
- 跳转指令
- 可以带条件跳转,一般跟
cmp
配合使用
示例:
3.6.1.1 b指令
b mycode
mov x0, #0x5
mycode:
mov x1, #0x6
运行进入断点:
si
执行下一条指令
跳转到mov x1, #0x6
继续执行
再次si
就到执行到ret
,继续si
,程序已经跳出test
方法了
程序继续往下执行,
3.6.1.2 带条件的b指令
3.6.2 bl
- 带返回的跳转指令
- 执行的操作
-
- 将
下一条
指令的地址存储到lr(x30)
寄存器中
- 将
-
跳转
到标记处开始执行代码
示例:
3.6.2.1
与上面b
指令使用一样的代码,只不过把b
改成bl
bl mycode
mov x0, #0x5
mycode:
mov x1, #0x6
运行进入断点:
si
执行下一条指令
跳转到mov x1, #0x6
继续执行
再次si
就到执行到ret
,继续si
,程序回到 mov x0, #0x5
继续执行
3.7 条件域
- EQ:equal,相等
- NE:not equal,不相等
- GT:great than,大于
- GE:great equal,大于等于
- LT:less than,小于
- LE:less equal,小于等于
参考书:
3.8 内存操作
3.8.1 load,从内存中读取数据
- ldr、ldur
- ldp(p是pair的简称,表示一对)
3.8.2 store,往内存中写入数据
- str、stur
- stp
- 零寄存器。里面存储的值是0
-
- wzr(32bit,Word Zero Register)
-
- xzr(64bit)
4. iOS汇编
4.1 真机:arm64汇编
- 寄存器
- 指令
- 堆栈
4.2 模拟器:x86汇编
5. 函数的堆栈
5.1 函数的类型
- 叶子函数
- 非叶子函数
@oubijiexi