iOS开发者要知道的汇编入门知识

100 阅读3分钟

iOS汇编

iphone ARM64 汇编 GNU
模拟器 x86汇编 AT&T

寄存器

  • 通用寄存器
    • 64bit的 x0 ~ x28
    • 32bit的 w0 ~ w28
    • x0 - x7 一般为请求参数
    • x0 一般为返回参数
  • 程序计数器
    • pc (Program Counter)    记录CPU当前执行的是哪一条指令,存储着当前CPU正在执行的地址,相当于 8086里的IP。
  • 堆栈指针
    • sp (Stack Pointer)    当前函数的栈顶
    • fp (Frame Pointer) x29    当前函数的栈低
  • 链接寄存器
    • lr (Link Register) x30    调用函数的地址 A -> B A调用B, lr为A调用B函数时候的地址(B结束后要返回的地址)
  • 程序状态寄存器
    • cpsr (current program Status Register)    当前程序状态寄存器
    • spsr (Saved Program Status Register)    异常状态下使用

汇编指令

  • ret 函数返回
  • mov (move)
  • add sub 加 or 减
    add x0, x1, x2        ; x0 = x1 + x2
    add x0, x1, #256      ; x0 = x1 + 256
    add x0, x1, x2 LSL#1  ; x0 = x1 + (x2 << 1)
    add x0, x1, x2, LSR#1 ; x0 = x1 + (x2 >> 1)
    
    sub x0, x1, x2        ; x0 = x1 - x2
    sub x0, x1, #256      ; x0 = x1 - 256
    sub x0, x1, x2 LSL#1  ; x0 = x1 - (x2 << 1)
    sub x0, x1, x2, LSR#1 ; x0 = x1 - (x2 >> 1)
    
    
  • cmp 比较
    • 两个寄存器相减
    • 相减的结果影响CPSR寄存器
      cmp x1, x0  
    
  • b 跳转
  • bl 带返回的跳转指令 bl A
    • bl的时候同时设置lr的地址为下一条指令的地址。
    • A中执行ret的时候,把lr赋值给pc寄存器: PC=LR,这样程序下一条要执行的地址就是lr。这样就可以返回、
mycode:
mov x0, #01
mov x1, #02
ret

bl mycode   ;跳转mycode 用bl mycode中的ret后回到mov x4, #0x1执行
mov x4, #0x1
mov x2, #0x1
mycode:
mov x0, #01
mov x1, #02
ret

b mycode   ;跳转mycode 用b mycode中的ret没有效果,不会回到mov x4 #0x1
mov x4, #0x1
mov x2, #0x1
  • 条件域

    • eq (equal)相等就跳转。   CPSR Z位为1,就跳转
    • ne (no equeal) 不等于
    • gt (great than) 大于
    • ge (great equal) 大于等于
    • lt (less than) 小于
    • le (less equal) 小于等于
  • 内存操作

    • load 从内存中装载数据
      • ldr ldur
      • ldp  成对装载 p:pairs
    • store 往内存中存储数据
      • str stur
      • stp
      • 零寄存器
        • wzr(32bit) word zero register
        • xzr(64bit)
ldr x0,[x1, #4]   ;x0 = x1 + 4
ldr x0,[x1, #4]!  ;x0 = x1 + 4   x1 = x1 + 4
ldr x0,[x1], #4   ;x0 = x1   x1 = x1 + 4
ldr x0 [r1, r2]   ;x0 = r1 + r2

ldp x0, x1 [x2, #5]  ;x0 = x2 + 5   从x2+5的地址取8个字节
                     ;x1 = x2 + 5 + 8  从x2+5+8的地址取8个字节
                     ;因为x0, x1大小是8个字节
                     
str x0, [x1]         ;把x0的数据写入到x1中   x1为地址。
str x0, [x1],#0x3    ;把x0的数据写入到x1中   x1为地址。
                     ;x1 = x1 + 0x3
str x0, [x1, #0x3]   ;把x0数据写入到  (x1地址+3)地址中
str x0, [x1, #0x3]!  ;把x0数据写入到  (x1地址+3)地址中   x1 = x1 + 3
str x0, x1, [x2, #0x3]  ;把x0数据写入到  (x1地址+3)地址中
                        ;把x1数据写入到  (x2地址+3)+ 8  地址中   其中8是x0的长度,8个字节。

堆栈空间

  • 叶子函数
    • 内部不在调用其他函数
  • 非叶子函数

叶子函数栈平衡不需要存LR和FP,因为不调用其他函数,不会更改。 非叶子函数栈平衡需要存LR和FP,因为调用内部函数会更改LR和FP

void A(){
    B();
}
void B(){
    c();
}
void C(){

}

image.png

LLDB 指令

register read 
register read x0
regisster write x0  0x123