为什么要学习汇编
- 1.当我们调式别人App时候,比如给微信打断点,发现断点后,看到的不是源码,而是汇编代码
- 2.当我开发的程序崩溃时,Xcode的控制台打印输出一般大都是汇编代码
iOS汇编
- 真机 : arm64 ,GNU汇编
- 模拟器: x86, AT&T汇编
汇编是严重依赖机器的,架构不一样,汇编指令也不一样 一般来说,我们先学习真机设备的汇编
如何学好汇编
1.寄存器 2.指令 3.堆栈
寄存器
通用寄存器
- 1.64bit的: x0 ~ x28 共29个, 64bit意味着8个字节,一个寄存器能放8个字节,
- 2.32bit的: w0 ~w28 (属于x0 ~ x28的低32bit)
x0 ~ x7通常拿来存放函数的参数,更多的参数使用堆栈来传递,寄存器运行速度比堆栈更快 x0 通常拿来作为函数的返回值
连接真机状态下,在touchBegin方法断点
register read x0
register :寄存器
register read w0
register write x0 0x1000000001
write 写东西,x0 被写入 0x1000000001
register read
会列出所有寄存器
x19 = 0x000000014ed50410
x20 = 0x000000014ee87d00
x21 = 0x000000014ed08d00
x22 = 0x0000000188ad276e "touchesBegan:withEvent:"
x23 = 0x000000014ed47890
x24 = 0x000000014ee3cb80
x25 = 0x000000014ed47890
x26 = 0x000000014ed08d00
x27 = 0x0000000188acdbc6 "layer"
x28 = 0x000000014ed50410
fp = 0x000000016fd5dea0
sp = 0x000000016fd5de70
pc = 0x00000001000a594c -[ViewController touchesBegan:withEvent:] + 104 at ViewController.m:62
21 registers were unavailable.
如何学习写汇编代码
- 1.内嵌汇编代码,这种不好写
- 2.外部建立文件
外部建立文件学习汇编代码
1.新建汇编文件
新建iOS ->Other -> Empty
汇编是.asm ,一般我们用.s 比如arm.s
2.新建头文件arm.h
声明函数
void test();
3.调用汇编函数
在main函数调用
int main(int argc, char * argv[]) {
@autoreleasepool {
test();
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
汇编指令学习
第一条汇编指令:返回指令ret
mov 数据传输指令(全称move),用法示例
// 声明它是代码段 .data 就是数据段, .stack就是栈段
.text
; 默认函数是私有的,需要声明成全局的函数
.global _test
; 调用test()函数,底层会做转换,变成_test
_test:
; 将8赋值给x0
mov x0, 8
ret
注:
汇编注释用; 也可以用// 汇编不区分大小写,写mov == MOV
ADD指令
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中.操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或是一个立即数.
加法add指令示例
mov x0, #0x1
mov x1, #0x2
add x2, x0, x1
断点停在汇编后,控制台使用lldb指令查看
si
register read x2
x2 = 0x0000000000000003
减法sub指令示例
mov x0, #0x5
mov x1, #0x2
sub x2, x0, x1
相当于x0-x1赋值给x2
lldb指令查看
register read x2
x2 = 0x0000000000000003
加法函数示例
.h声明
int add(int a,int b);
arm.s文件实现
// add函数的实现
_add:
add x0, x0, x1
ret
声明为全局函数
.global _test ,_add
外部调用示例
NSLog(@"%d",add(1, 2));
注意: x0 通常拿来作为函数的返回值
x0 ~ x7通常拿来存放函数的参数,更多的参数使用堆栈来传递,寄存器运行速度比堆栈更快
add 指令不可以使用 =,而是使用
函数后面必须要有ret不然会继续往下走,直到遇到ret