ARM 汇编

2020-12-31  本文已影响0人  蓝天白云_Sam

1. 寄存器

ARMv8-aarch64 寄存器和指令集

1.1 通用寄存器(X0-31)

1.2 特殊用途寄存器(X8,X16-X18,X29,X30,X31):

  1. XR(X8): 是间接结果寄存器,用于保存子程序返回地址,尽量不使用
  2. X16 和 X17: 程序内调用临时寄存器
  3. X18: 平台寄存器,保留用于平台 ABI,尽量不使用
  4. FP(X29, Frame Pointer): 帧指针寄存器(FP),存储着当前栈底的地址
  5. LR(X30, Link Register): 链接寄存器(LR)
  6. SP(X31, Stack Pointer): 堆栈指针寄存器 ,存储的是栈顶的地址
  7. PC:PC寄存器中存的是当前执行的指令的地址。在arm64中,软件是不能改写PC寄存器的

1.3 向量寄存器(浮点寄存器):V0 - V31

V0 - V31 是向量寄存器,也可以说是浮点型寄存器。它的特点是每个寄存器的大小是 128 位的。 分别可以用 Bn Hn Sn Dn Qn的方式来访问不同的位数:

2. 栈

栈就是指令执行时存放临时变量的内存空间。在学习汇编代码的执行过程中,了解栈的结构非常重要。一下是栈的一些特性:

  1. 栈是从高地址到低地址扩展的, 栈底是高地址,栈顶是低地址。
  2. FP指向当前frame的栈底,也就是高地址。
  3. SP指向栈顶,也就是低地址。

其中3行汇编代码就是方法B的前三行汇编指令。它们做的事情就是图中描述的事情 (x29就是fp, x30就是lr):

注: lr 是link register中的值,它存的是方法_funcA的执行的最后一行指令的下一行。它的作用是:当_funcB执行完了之后要返回_funcA继续执行,但是计算机要如何知道返回到哪执行呢? 就是靠lr记录了返回的地址,方法才能得以正常返回。

当 _funcB执行完毕后,是如何把栈恢复到_funcA的过程的呢? 我们直接分析 _funcB的最后3条指令:

mov  sp, fp;              //sp 设置为fp, 就是图中 -->fp_B 的位置
ldp  fp, lr, [sp], #0x10; //  从sp指向的地址中读取 2个64位,分别存入fp,lr。 然后将sp += 0x10
// 这一步执行完之后,fp就执行了图中 -->fp_A. lr恢复成 _funcA的返回地址。 sp指向了 -->sp_A. 
// 这个时候状态已经完全恢复到了 _funcA 的环境
ret;    // 返回指令,这一步直接执行lr的指令。

上面描述了方法如何调用的。我们知道在编程语言里面方法都有入参,有返回值的。在汇编里面如何体现呢?

2 指令

2.1 Loads and stores

LDR<Sign><Size> <Destination>, [<address>] 
STR<Size> <Destination>, [<address>]

3.1.1 Size

LDRSTR 的大小由目标寄存器决定

LDR W0, [<address>]   ;32bits
LDR X0, [<address>]  ;64bits

LDR/STR指令也可以限定大小

STRB W0, [<address>] ;stores the bottom byte (B) of W0 to <address>
STRH W0, [<address>] ;stores the bottom halfword (H) of W0 to <address>:
STRW X0, [<address>] ;stores the bottom word (W) of X0 to <address>:

3.1.2 Zero and sign extension

3.1.3 寻址方式

3.1.4 Load pair and store pair

LDP W3, W7, [X0] ;  loads [X0] into W3, and loads [X0 + 4] into W7
STP D0, D1, [X4] ; stores D0 into [X4] and stores D1 to [X4 + 8]:
STP X0, X1, [SP, #-16]!  ;  pushes X0 and X1 onto the stack:
LDP X0, X1, [SP], #16 ;pops X0 and X1 from the stack

procedure-call-standard

入参

返回值

参考

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000101da06b0 QQKSong`initData(forWhat="") at WSHookObjcMsgSend.cpp:141:10
    frame #1: 0x0000000101da0c48 QQKSong`::startHook(forWhat="") at WSHookObjcMsgSend.cpp:193:5
    frame #2: 0x0000000100de3ad8 QQKSong`main(argc=1, argv=0x000000016f027760) at main.m:76:5
    frame #3: 0x00000001aad298f0 libdyld.dylib`start + 4
(lldb) register read
General Purpose Registers:
        fp = 0x000000016f027640
        lr = 0x0000000101da0c48  QQKSong`::startHook(char *) + 24 at WSHookObjcMsgSend.cpp
        sp = 0x000000016f027620
        pc = 0x0000000101da06b0  QQKSong`initData(char*) + 32 at WSHookObjcMsgSend.cpp:141:10
      cpsr = 0x60000000
(lldb)  x/20x $fp
0x16f027640: 0x000000016f027670 0x0000000101da0c48
0x16f027650: 0x00000001092b15d0 0x0000000104487880
0x16f027660: 0x00000001092452c0 0x00000001092a8040
0x16f027670: 0x000000016f027720 0x0000000100de3ad8
0x16f027680: 0x0000000042000000 0x0000000109245260
0x16f027690: 0x00000001092a8010 0x000000016f0276b0
0x16f0276a0: 0x0000000109244000 0x0000000109244000
0x16f0276b0: 0x0000000000000000 0x000000016f0276b0
0x16f0276c0: 0x0000003002000000 0x000000010924524c
0x16f0276d0: 0x0000000109245258 0x0000000000000000
0x16f0276e0: 0x0000000000000000 0x0000000000000000
0x16f0276f0: 0x000000016f027760 0x0000000000000001
0x16f027700: 0x0000000000000000 0x0000000000000000
0x16f027710: 0x0000000000000000 0x730d36aa5ab60031
0x16f027720: 0x000000016f027740 0x00000001aad298f0
0x16f027730: 0x00000001aad298f0 0x0000000000000000
0x16f027740: 0x0000000000000000 0x0000000000000000
  1. 0x000000016f027670 : 上一个堆栈的栈底
  2. '0x0000000101da0c48': 上层调用函数返回地址,也就是QQKSong::startHook(char *)`
(lldb) image lookup -a 0x0000000101da0c48
      Address: QQKSong[0x0000000100fc8c48] (QQKSong.__TEXT.__text + 16532744)
      Summary: QQKSong`::startHook(char *) + 24 at WSHookObjcMsgSend.cpp
  1. 0x000000016f027720 : 上一个堆栈的栈底
  2. '0x0000000100de3ad8': 上层调用函数返回地址,也就是QQKSong main
(lldb) image lookup -a 0x0000000100de3ad8
      Address: QQKSong[0x000000010000bad8] (QQKSong.__TEXT.__text + 29592)
      Summary: QQKSong`main + 52 at main.m
  1. 0x000000016f027740 : 上一个堆栈的栈底
  2. '0x00000001aad298f0': 上层调用函数返回地址,也就是libdyld.dylib start
(lldb) image lookup -a 0x00000001aad298f0
      Address: libdyld.dylib[0x00000001802998f0] (libdyld.dylib.__TEXT.__text + 4)
      Summary: libdyld.dylib`start + 4
上一篇 下一篇

猜你喜欢

热点阅读