美文网首页
iOS汇编研究-2-寄存器

iOS汇编研究-2-寄存器

作者: 行知路 | 来源:发表于2021-05-17 21:10 被阅读0次

一、寄存器

        对于日常使用高级语言的程序员来说,其看到的是连续的主存(内存)空间,使用的也是主存储器(简称内存)的空间。但是对于使用汇编的程序原来说,其面对的主要是寄存器。事实上,CPU内部也是分为运算器、控制器、寄存器、多级缓存。对于基于汇编语言的程序开发来说,寄存器是必须了解的一个概念。


CPU的多级缓存

二、通用寄存器

        通用原来寄存器命名是r[0]、r[1]、r[2]、r[3]......,但是随着armv8,也就是64位的处理器推出,寄存器命名修改为x[n],但是为了保持兼容,x[n]的低32位被命名为w[n]


寄存器

        通用寄存器从名字上看就是做一些通用得工作的寄存器,通用工作有哪些呢?一般就是存储内存的地址、各种计算所需的临时数据、堆栈地址等。

2.0 栈概述

        由于寄存器与栈这种数据结构有密切的关系,并且在后面也会详细讲到函数调用堆栈,为使后面顺利讲述,在这里先概要介绍一下栈。
        栈是一种先进后出的数据结构。在日常生活中能够见到的典型栈类型的东西就是——箱子,先装进箱子的东西只能后拿出来,而后装进去的东西则可以先拿出来。


栈示意

注意
在ARM64汇编中,栈是从高地址向低地址生长的、先开劈栈空间然后再使用。这句话可能暂时不理解,但是一定请先记住。

_addwwj:                                ; @addwwj
Lfunc_begin0:
    sub sp, sp, #16                     ; 开辟栈空间
    str w0, [sp, #12]
    str w1, [sp, #8]
Ltmp1:
    ldr w8, [sp, #12]
    ldr w9, [sp, #8]
    add w0, w8, w9
    add sp, sp, #16                     ; 回收栈空间
    ret
Ltmp2:
Lfunc_end0:

        在上面汇编代码中(sub sp, sp, #16),sub是减的意思,由于栈空间是向低地址增长的,那么所以在当前栈底的基础之上再扩展16个字节的空间。
        在上面汇编代码中(add sp, sp, #16),把栈底又加16个字节,所以栈又恢复到初始调用此函数的状态。

2.1 传参寄存器

        有人说xo-x7,这8个寄存器一般用来存储函数的入参,多于8个的参数会存放在内存的之中。但是经过我的测试,发现其与优化等级相关,如果不优化(o0)的情况下,多达18个参数的情况下依然会通过寄存器来传参,用于测试的电脑是:MacBook Pro (13-inch, M1, 2020)。如果选择(o3)级别的优化,在参数太多的情况下会通过内存来传递。
        总的来说,前几个寄存器一般用于传递函数的参数

一个参数的函数寄存器状态
一个需要18个参数的函数
此时的寄存器状态

2.2 x0寄存器

        对于x0(w0)寄存器来说,其还有一个特殊用途,就是用来存储函数的返回值,如下图所示。


w0用于存储函数返回值

        图中左边是一个返回10的函数,右边是对应的汇编代码,可见直接把16进制的10复制到w0寄存器来实现传递返回值。

2.3 fp/x29

        fp(frame pointer)寄存器是x29寄存器的简称,用于存储函数调用堆栈的栈底信息。


fp寄存器

2.4 lr/x30

        lr寄存器用来保存函数返回的路。

int aTestFun(int para1) {
    return para1 + 3;
}

int theOtherTestFun(int para1) {
    return para1 + aTestFun(para1);
}
;theOtherTestFun 对应的汇编代码如下
0x100003f20 <+0>:  sub    sp, sp, #0x20             ; =0x20 
    0x100003f24 <+4>:  stp    x29, x30, [sp, #0x10]
    0x100003f28 <+8>:  add    x29, sp, #0x10            ; =0x10 
    0x100003f2c <+12>: stur   w0, [x29, #-0x4]
->  0x100003f30 <+16>: ldur   w8, [x29, #-0x4]
    0x100003f34 <+20>: ldur   w0, [x29, #-0x4]
    0x100003f38 <+24>: str    w8, [sp, #0x8]
    0x100003f3c <+28>: bl     0x100003f08               ; aTestFun at CImp.c:10 这里是调用 aTestFun函数,进入此函数之后,lr的地址是0x100003f40
    0x100003f40 <+32>: ldr    w8, [sp, #0x8]             ; 就是这个地址
    0x100003f44 <+36>: add    w0, w8, w0
    0x100003f48 <+40>: ldp    x29, x30, [sp, #0x10]
    0x100003f4c <+44>: add    sp, sp, #0x20             ; =0x20 
    0x100003f50 <+48>: ret    
lr寄存器的作用

        在上面的截图中,函数theOtherTestFun调用aTestFun函数,当从aTestFun函数返回是需要执行theOtherTestFun中调用aTestFun函数的下一行。

0x100003f3c <+28>: bl     0x100003f08               ; aTestFun at CImp.c:10 实现调用aTestFun函数
0x100003f40 <+32>: ldr    w8, [sp, #0x8]             ; aTestFun返回后,需要执行的下语句汇编代码
;从上面的截图来看,当前lr地址就是上面汇编指令的地址

2.5 sp/x31

        sp(stack pointer)寄存器是寄存器x31的简称,用于存储函数调用堆栈的栈顶信息。

int need1Parameter(int para1) {
    return 10;
}
    ; 这里就是上述 need1Parameter 函数的汇编代码

    0x100003dac <+0>:  sub    sp, sp, #0x10             ; =0x10   此时移动栈顶空间,为need1Parameter函数开辟堆栈空间
    0x100003db0 <+4>:  str    w0, [sp, #0xc]
    0x100003db4 <+8>:  mov    w0, #0xa
->  0x100003db8 <+12>: add    sp, sp, #0x10             ; =0x10  need1Parameter函数执行完毕,回收刚才开辟的堆栈空间
    0x100003dbc <+16>: ret  

2.6 pc/x32

        所有的数据、指令、常量等,在内存中,都是01001。那么,cpu怎么知道哪段01序列是命令,需要CPU来执行呢?其实很简单,pc寄存器所指的内容就会被当做指令。


pc

2.7 cpsr/x33

        目前,上面介绍的寄存器都是作为一个整体来使用的,但是cpsr寄存器是每个位都单独来使用的。其标识当前程序所处的状态,目前暂未涉及,先不做深入介绍,如果想要深入理解的话,可以自行百度。


cpsr.jpeg

三、浮点数寄存器

        为了加速浮点数的处理,现在arm提供专用的浮点数寄存器。64位的浮点数寄存器是V0-V31、spsr、spcr。


浮点数寄存器

四、向量寄存器

        为了支持游戏等用到向量计算比较多的情况,CPU针对向量计算,提供了向量寄存器。


向量寄存器

五、寄存器相关lldb命令

  • register read 读取所有通用寄存器
  • register read x0 读取某个寄存器
  • register write x0 0x0001 向寄存器写入值

注意

例如,pc寄存器是不能直接写入值得。

相关文章

  • iOS汇编研究-2-寄存器

    一、寄存器 对于日常使用高级语言的程序员来说,其看到的是连续的主存(内存)空间,使用的也是主存储器(简称内存)的空...

  • ARM64 学习

    iOS汇编 真机 arm64汇编,GNU 模拟器 x86, AT&T 汇编 寄存器 指令 堆栈 通用寄存器 64b...

  • iOS 汇编Day01

    iOS 汇编 8086CPU 机器语言 由0和1组成 将寄存器BX的内容送入寄存器AX汇编语言 用符...

  • 汇编

    iOS汇编 arm64,x86,armv7 生成汇编文件 寄存器 通用寄存器64bit:x0-x2832bit:w...

  • arm64汇编基础

    iOS汇编 真机:arm64汇编 模拟器:x86汇编 将c语言的代码转化成汇编: 1. 寄存器 lldb查看当前a...

  • 十七.AT&T汇编

    之前将的都是8086汇编,现在聊一聊AT&T汇编,基本都是相同的汇编就是使用寄存器存储数据和操作内存; ios基本...

  • 有关汇编相关参考博客

    汇编之常识(一)汇编基础 CPU等硬件结构 数据总线 地址总线 控制总线 汇编之寄存器(二)寄存器 数据地址寄存器...

  • IOS arm64常用的汇编

    导论 生成汇编文件 寄存器 arm64 汇编条件域 arm64 汇编指令 总结 1. 生成汇编文件 2. 寄存器 ...

  • 简单汇编

    程序的本质 软件\程序的执行过程 寄存器和内存 编程语言的发展 汇编语言的种类 ios 最主要的汇编语言 AT&T...

  • ARM64汇编

    不同架构的汇编代码是不同的,这里研究的是真机ARM64架构的汇编 通用寄存器 可以通过$register read...

网友评论

      本文标题:iOS汇编研究-2-寄存器

      本文链接:https://www.haomeiwen.com/subject/sdkrjltx.html