函数的本质

作者: 晨曦的简书 | 来源:发表于2022-07-07 14:05 被阅读0次

    寄存器的补充

    数据地址寄存器

    数据地址寄存器通常用来做数据计算的临时存储、做累加、计数、地址保存等功能。定义这些寄存器的作用主要是用于在 CPU 指令中保存操作数,在 CPU 中当做一些常规变量来使用。

    ARM64中

    • 64 位: X0-X30, XZR(零寄存器)
    • 32 位: W0-W30, WZR(零寄存器)

    需要注意的是,8086 汇编中有一种特殊的寄存器段寄存器:CS, DS, SS, ES 四个寄存器来保存这些段的基地址,这个属于 Intel 架构 CPU 中,在 ARM 中并没有。

    浮点和向量寄存器

    因为浮点数的存储以及其运算的特殊性,CPU 中专门提供浮点数寄存器来处理浮点数

    • 浮点寄存器 64位: D0 - D31,32位: S0 - S31

    现在的 CPU 支持向量运算,(向量运算在图形处理相关的领域用得非常的多)为了支持向量计算系统了也提供了众多的向量寄存器。

    • 向量寄存器 128位:V0-V31

    • 栈:是一种具有特殊的访问方式的存储空间(后进先出, Last In Out Firt,LIFO

    SP和FP寄存器

    • sp 寄存器在任意时刻会保存我们栈顶的地址。

    • fp 寄存器也称为 x29 寄存器属于通用寄存器,但是在某些时刻我们利用它保存栈底的地址!

    注意:ARM64 开始,取消 32 位的 LDM, STM, PUSH, POP 指令! 取而代之的是 ldr\ldp str\stpARM64 里面,对栈的操作是 16 字节对齐的。

    函数调用栈

    常见的函数调用开辟和恢复的栈空间

    sub    sp, sp, #0x40             ; 拉伸0x40(64字节)空间
    stp    x29, x30, [sp, #0x30]     ;x29\x30 寄存器入栈保护
    add    x29, sp, #0x30            ; x29指向栈帧的底部
    ... 
    ldp    x29, x30, [sp, #0x30]     ;恢复x29/x30 寄存器的值
    add    sp, sp, #0x40             ; 栈平衡
    ret
    

    关于内存读写指令

    注意:读/写 数据是都是往高地址读/写

    str(store register)指令

    将数据从寄存器中读出来,存到内存中。

    ldr(load register)指令

    将数据从内存中读出来,存到寄存器中,ldrstr 的变种 ldpstp 还可以操作2个寄存器。

    堆栈操作练习

    使用 32 个字节空间作为这段程序的栈空间,然后利用栈将 x0x1 的值进行交换。

    sub    sp, sp, #0x20; 拉伸栈空间32个字节
    stp    x0, x1, [sp, #0x10]; sp往上加16个字节,存放x0 和 x1
    ldp    x1, x0, [sp, #0x10]; 将sp偏移16个字节的值取出来,放入x1 和 x0
    

    bl和ret指令

    bl标号

    • 将下一条指令的地址放入 lr(x30) 寄存器
    • 转到标号处执行指令

    ret

    • 默认使用 lr(x30) 寄存器的值,通过底层指令提示 CPU 此处作为下条指令地址。

    ARM64 平台的特色指令,它面向硬件做了优化处理的。

    x30寄存器

    x30 寄存器存放的是函数的返回地址,当 ret 指令执行时刻,会寻找 x30 寄存器保存的地址值。

    注意:在函数嵌套调用的时候,需要将 x30 入栈。

    函数的参数和返回值

    ARM64下,函数的参数是存放在 X0X7W0W7) 这 8 个寄存器里面的,如果超过 8个参数,就会入栈。
    函数的返回值是放在 X0 寄存器里面的。

    函数的局部变量

    函数的局部变量放在栈里面。

    相关文章

      网友评论

        本文标题:函数的本质

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