一直在想 iOS 汇编是怎么样的,变量是怎么保存的?如何调函数的?如何判断条件的?昨天看了一天的汇编,也不是很懂,特别是adrp 指令有点难懂,碰到自己不会的东西,我自己是多去分析已知的汇编,将自己的汇编多看呗,看多自然就懂了。
阿里大牛知兵的知乎专栏
ARM64 汇编——寄存器和指令
iOS开发同学的arm64汇编入门
10分钟入门arm64汇编
ARM64 汇编——寄存器和指令
一般局部变量会存放在栈中,
OC 代码
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
int a = 10;
int b = 20;
int c = a + b;
NSLog(@"%d",c);
}
其中int a = 10; int b = 20; int c = a + b;对应汇编如下。局部变量存放在栈,然后再取,最后加法操作
0x10236e740 <+68>: mov w11, #0x14;将14存放在w11位
0x10236e744 <+72>: mov w12, #0xa;将10存放在w12位
-> 0x10236e748 <+76>: str w12, [sp, #0x1c];将w12存放在sp +28位,w只占用4位
0x10236e74c <+80>: str w11, [sp, #0x18];将w11存放在sp +24位
0x10236e750 <+84>: ldr w11, [sp, #0x1c];加载sp +28给w11
0x10236e754 <+88>: ldr w12, [sp, #0x18];加载sp +24位给w12
0x10236e758 <+92>: add w11, w11, w12;将w11 + w12 赋值给w11
转成汇编语言
-[ViewController viewDidLoad]:
0x10236e6fc <+0>: sub sp, sp, #0x50 ; =0x50 将 sp 向下移动 16 x 5 = 80个字节,
0x10236e700 <+4>: stp x29, x30, [sp, #0x40]; 将x29 = fp,x30 =lr ,lr 是下条返回地址,放在sp 向上移动64个的位置,x29 和 x30 各占用了8个字节
0x10236e704 <+8>: add x29, sp, #0x40 ; fp 指向其赋值的位置
0x10236e708 <+12>: add x8, sp, #0x20; 将sp+16数据存放在x8中
0x10236e70c <+16>: adrp x9, 2 ;将 pc 的地址取到,pc = 0x00000001029d2798, x9 = 0x00000001029d4000
0x10236e710 <+20>: add x9, x9, #0xca8; =0xca8 取方法的地址
0x10236e714 <+24>: adrp x10, 2 ;
0x10236e718 <+28>: add x10, x10, #0xcc8 ; =0xcc8 取方法地址
0x10236e71c <+32>: stur x0, [x29, #-0x8];将x0 的数据放在fp - 8的位置
0x10236e720 <+36>: stur x1, [x29, #-0x10];将x1 的数据放在fp - 16的位置
0x10236e724 <+40>: ldur x0, [x29, #-0x8];将fp - 8的数赋值给x0
0x10236e728 <+44>: str x0, [sp, #0x20];将x0 存放在 sp + 32地址中
0x10236e72c <+48>: ldr x10, [x10];将x10 存放地址所指向的数据赋值给 x10
0x10236e730 <+52>: str x10, [sp, #0x28];将x10数据存放在sp + 24
0x10236e734 <+56>: ldr x1, [x9];将x1 的数据赋值给x9存方地址所指的空间。
0x10236e738 <+60>: mov x0, x8;将x8 赋值给 x0
0x10236e73c <+64>: bl 0x10236eb84 ; symbol stub for: objc_msgSendSuper2; 调用父类方法
0x10236e740 <+68>: mov w11, #0x14;将14存放在w11位
0x10236e744 <+72>: mov w12, #0xa;将10存放在w12位
-> 0x10236e748 <+76>: str w12, [sp, #0x1c];将w12存放在sp +28位,w只占用4位
0x10236e74c <+80>: str w11, [sp, #0x18];将w11存放在sp +24位
0x10236e750 <+84>: ldr w11, [sp, #0x1c];加载sp +28给w11
0x10236e754 <+88>: ldr w12, [sp, #0x18];加载sp +24位给w12
0x10236e758 <+92>: add w11, w11, w12;将w11 + w12 赋值给w11
0x10236e75c <+96>: str w11, [sp, #0x14];将w11值给sp+20
0x10236e760 <+100>: ldr w11, [sp, #0x14];加载sp+20给w11
0x10236e764 <+104>: mov x0, x11;将x11的值给x0
0x10236e768 <+108>: mov x8, sp
0x10236e76c <+112>: str x0, [x8]
0x10236e770 <+116>: adrp x0, 2
0x10236e774 <+120>: add x0, x0, #0x60 ; =0x60 ;
0x10236e778 <+124>: bl 0x10236eb3c ; symbol stub for: NSLog
0x10236e77c <+128>: ldp x29, x30, [sp, #0x40];将sp + 64 位置将赋值给x29,x 30
0x10236e780 <+132>: add sp, sp, #0x50 ; =0x50 ;恢复sp平衡
0x10236e784 <+136>: ret
adrp, 用来定位数据段中的数据用, 因为aslr会导致代码及数据的地址随机化, 用adrp来根据pc做辅助定位(本人对adrp理解不够深入,里面不太懂);
sp 和 bp 之间空间是存放函数的变量。
x/s 打印寄存中的内容
po $x0
po (char*)$x0
(lldb) x/s $x1
0x18da1bbb3: "viewDidLoad"
(lldb) x/s $x0
0x113e0bd00: "\xffffffddL\xffffffa2"
(lldb) x/s $x2