iOS之ARM64汇编

iOS的程序都是跑在ARM架构的机器上,所以iOS的汇编用到的就是ARM汇编

对于iOS开发汇编的分类:

  1. x86汇编 模拟器
  2. ARM64/ARM32汇编 真机64位/真机32位,目前真机大多数都是64位。

ARM64汇编三个重要概念:

  1. 寄存器
    ARM64 有34个寄存器,包括31个通用寄存器、SP、PC、CPSR。
(lldb) register read
General Purpose Registers:
        x0 = 0x000000012c025350
        x1 = 0x000000012c025350
        x2 = 0x000000000000000d
        x3 = 0x0000000000000000
        x4 = 0x000000016f43dab8
        x5 = 0x0000000000000040
        x6 = 0x0000000000000000
        x7 = 0x0000000000000d20
        x8 = 0x00000001009cd688  (void *)0x00000001009cd790: LGPerson
        x9 = 0x56f24077b16c00de
       x10 = 0x000000012c025350
       x11 = 0x00000000000007fb
       x12 = 0x00000000000007fd
       x13 = 0x0000000000000000
       x14 = 0x000000008afee000
       x15 = 0x00000000000003dc
       x16 = 0x00000001aa01d4e8  libobjc.A.dylib`objc_autoreleasePoolPop
       x17 = 0x000000000ae00000
       x18 = 0x0000000000000000
       x19 = 0x0000000000000000
       x20 = 0x000000012be04110
       x21 = 0x00000001efcaf000  
       x22 = 0x00000001e1bb3984  
       x23 = 0x0000000000000001
       x24 = 0x0000000000000001
       x25 = 0x00000001e71bf690  CoreFoundation`__NSArray0__struct
       x26 = 0x000000012be0b130
       x27 = 0x00000001efc2e000  
       x28 = 0x00000001e1bbcfae  
        fp = 0x000000016f43dc60
        lr = 0x00000001009c5bac  001-alloc&init探索`-[ViewController viewDidLoad] + 76 at ViewController.m:28:5
        sp = 0x000000016f43dc30
        pc = 0x00000001009c5bb4  001-alloc&init探索`-[ViewController viewDidLoad] + 84 at ViewController.m:30:20
      cpsr = 0x60000000
  • 通用寄存器:x0~x28(64位的) (w0~w28(32位)对应的的x0~x28的低32位) ,x0~x7一般是用来存储函数的参数,更多参数,则用堆栈来传递,x0一般用作函数的返回值
  • PC: 程序计数器:存储着当前执行的指令
  • FP: x29保存栈帧地址(栈底指针)
  • SP:保存栈指针,使用 SP/WSP来进行对SP寄存器的访问
  • CPSR:状态寄存器
    NZCV是状态寄存器的条件标志位,分别代表运算过程中产生的状态,其中:
    N, negative condition flag,一般代表运算结果是负数
    Z, zero condition flag, 指令结果为0时Z=1,否则Z=0;
    C, carry condition flag, 无符号运算有溢出时,C=1。
    V, oVerflow condition flag 有符号运算有溢出时,V=1。
  • LR:通常称X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令
    每个寄存器的大小都是8字节的
  • wzr:32位零寄存器
  • xzr:64位零寄存器
  1. 指令
MOV    X1,X0         ;将寄存器X0的值传送到寄存器X1
ADD    X0,X1,X2     ;寄存器X1和X2的值相加后传送到X0
SUB    X0,X1,X2     ;寄存器X1和X2的值相减后传送到X0

AND    X0,X0,#0xF    ; X0的值与0xF相位与后的值传送到X0
ORR    X0,X0,#9      ; X0的值与9相位或后的值传送到X0
EOR    X0,X0,#0xF    ; X0的值与0xF相异或后的值传送到X0

LDR    X5,[X6,#0x08]        ;ld:load; X6寄存器加0x08的和的地址值内的数据传送到X5
LDP  x29, x30, [sp, #0x10]    ; ldp :load pair ; 一对寄存器, 从内存读取数据到寄存器

STR X0, [SP, #0x8]         ;st:store,str:往内存中写数据(偏移值为正); X0寄存器的数据传送到SP+0x8地址值指向的存储空间
STUR   w0, [x29, #-0x8]   ;往内存中写数据(偏移值为负)
STP  x29, x30, [sp, #0x10]    ;store pair,存放一对数据, 入栈指令

CBZ  ;比较(Compare),如果结果为零(Zero)就转移(只能跳到后面的指令)
CBNZ ;比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令)
CMP  ;比较指令,相当于SUBS,影响程序状态寄存器CPSR 

B   ;跳转指令,可带条件跳转与cmp配合使用
BL  ;带返回的跳转指令, 返回地址保存到LR(X30)
BLR  ; 带返回的跳转指令,跳转到指令后边跟随寄存器中保存的地址(例:blr    x8 ;跳转到x8保存的地址中去执行)
RET   ;子程序返回指令,返回地址默认保存在LR(X30)
  • ret:函数返回,相当于return
  • mov:数据传输指令
    mov 目的寄存器 被操作数,被操作数可以是变量,也可以是寄存器
    例如 mov x0 ,#0x08 或者 mov x0, x1
  • add: 相加后存储到目标寄存器
    例如 :
mov x1 ,#0x09
mov x2 ,#0x010
add x0, x1 ,x2 //x0 = x1 + x2
  • sub:相减,与add类似
mov x1 ,#0x09
mov x2 ,#0x010
sub x0, x1 ,x2 //x0 = x1 - x2
  • cmp:操作数1,操作数2
    比较的结果放在cpsr中
mov x1 ,#0x09
mov x2 ,#0x010
cmp x1, x2 //将x1-x2的结果放到cpsr状态寄存器中
  • b 指令 跳转指令 相当于goto
b myCode //跳转到myCode
  • b指令带条件
    条件域:EQ:相等、NE:不等于、GE:大于等于、LE:小于等于、GT:大于、LT:小于
mov x1 ,#0x09
mov x2 ,#0x010
cmp x1, x2
beq myCode//结果相等,即cpsr的z位的值为1时,跳转到myCode
  • bl指令:带返回的跳转指令(函数调用的汇编代码跳转实现)
mov x1 ,#0x09
mov x2 ,#0x010
cmp x1, x2
bleq myCode//结果相等,即cpsr的z位的值为1时,跳转到myCode
mov x8 ,#0x09 //myCode执行完会返回到这
  • ldr指令,从内存中加载数据
    例如:
ldr/ldur x0, [x1] //将x1存储的地址指向的值存入到x0,x1如果为不存在的地址值,就会报错,野指针
ldr x0, [x1, #0x04] //将x1存储的地址值加上0x04后的新地址值指向的值存入到x0
  • ldp指令,从内存中加载数据,放在一对寄存器中
    例如:
ldp w0,w1, [x2] //将x2存储的地址指向的值存入到w0、w1,前4字节存放在w0,后4字节放在w1
  • str/stur指令,往内存中写数据
    例如:
str x0, [x2] //将x0的数据,写入到x2地址指向的内存中
  • stp 存放一对数据, 入栈指令
    例如
stp x29, x30, [sp, #0x10]  //将x29中的值写入到sp偏移0x10后的地址指向的内存的前8个字节,x30写入后面8个字节
  1. 堆栈
    对应寄存器:
  • FP: x29保存栈帧地址(栈底指针)
  • LR:通常称X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令
    每个寄存器的大小都是8字节的
    函数的分类:
  • 叶子函数,内部不再调用其他函数的函数,汇编代码如下:
    对应的c代码:
void test(){
    int a = 2;
    int b = 3;
}

汇编代码

_test:                                  ; @test
    .cfi_startproc
; %bb.0:
    sub sp, sp, #16             ; =16,sp栈顶指针上移16个字节
    .cfi_def_cfa_offset 16
    mov w8, #2 ;将2存入w8寄存器
    str w8, [sp, #12] ;将w8寄存器的数据存入到sp下移12个字节的所在位置下面的4字节
    mov w8, #3 ;将3存入w8寄存器
    str w8, [sp, #8] ;将w8寄存器的数据存入到sp下移8个字节的所在位置下面的4字节
    add sp, sp, #16             ; =16,sp栈顶指针下移16个字节,恢复到初始位置
    ret
    .cfi_endproc
  • 非叶子函数,除了叶子函数,其他函数叫非叶子函数
    对应的c代码:
void test(){
    int a = 2;
    int b = 3;
}

void testh(){
    test();
    int a = 4;
    int b = 5;
}

汇编代码

_test:                                  ; @test,与上面的test一致
    .cfi_startproc
; %bb.0:
    sub sp, sp, #16             ; =16
    .cfi_def_cfa_offset 16
    mov w8, #2
    str w8, [sp, #12]
    mov w8, #3
    str w8, [sp, #8]
    add sp, sp, #16             ; =16
    ret
    .cfi_endproc
                                        ; -- End function
    .globl  _testh                  ; -- Begin function testh
    .p2align    2
_testh:                                 ; @testh,非叶子函数
    .cfi_startproc
; %bb.0:
    sub sp, sp, #32             ; =32 ,开辟32字节栈空间
    stp x29, x30, [sp, #16]     ; 16-byte Folded Spill,在一开始分配的32字节空间上,给fp(x29)寄存器,lr(x30)寄存器各分配8字节的空间
    add x29, sp, #16            ; =16,将fp寄存器指向栈底向上偏移16字节位置,即存储fp和lr寄存器后剩余的空间。
    .cfi_def_cfa w29, 16
    .cfi_offset w30, -8
    .cfi_offset w29, -16
    bl  _test  ;跳转到test
    mov w8, #4  ;给a,b两个变量分配内存空间,在剩余的16字节空间上分配,与test类似
    stur    w8, [x29, #-4]
    mov w8, #5
    str w8, [sp, #8]
    ldp x29, x30, [sp, #16]     ; 16-byte Folded Reload,读取fp,lr
    add sp, sp, #32             ; =32,收回函数调用栈空间
    ret
    .cfi_endproc
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342