zoukankan      html  css  js  c++  java
  • 9.9Go之函数之函数底层实现

    9.9Go之函数之函数底层实现

    为什么函数是语言的一个核心元素

    由基于堆栈的程序执行模型决定的

    分析函数底层实现的两种方式

    • 语言编译器源码

    • 反汇编


    需要有一定的汇编基础

    本章会用到的一些汇编指令

    Go语言编译器特点:

    • 产生的汇编代码是中间抽象态,不是对机器码的映射

    • 有些寄存器真实存在,有些是抽象的寄存器

    Go中一些抽象的寄存器:

    1. SB(Static base pointer):静态基址寄存器。和全局符号一起表示全局变量的地址

    2. FR(Frame pointer):栈帧寄存器。 指向当前函数调用栈帧的栈底位置

    3. PC(Program counter):程序计数器。 存放下一条指令的执行地址 --->一般是CALL、RET等指令隐式操作

    4. SP(Stack pointer):栈顶寄存器。

      1. 在函数调用前由主调函数设置SP

      2. 负责对栈空间进行分配或回收

    特点:

    Go 汇编编译器对内嵌汇编程序自动做了调整,增加了保护现场,以及函数调用前的保持 PC 、SP 偏移地址重定位等逻辑,反汇编代码更能反映程序的真实执行逻辑

    函数调用规约

    采取模式:

    • caller-save模式:由调用者负责保护寄存器

    • 在主调函数调用被调函数的前后有一个保存现场和恢复现场的动作

    Go中多返回值实现的分析

    交换函数swap:

    package main

    import "fmt"

    /*
    手写一个交换函数,实现传入两个数,交换他们的值
    */
    func swap(arr int, brr int) (int, int) { //函数调用前己经为返回值和参数分配了栈空间,分配顺序是从右向左的,先是返回值,然后是参数
    /*交换值*/
    arr, brr = brr, arr
    return arr, brr
    }

    func main() {
    fmt.Println(swap(10, 20))
    }

    省略掉汇编代码,只看结果可知:

    • 函数的调用者负责环境准备,包括为参数和返回值开辟栈空间。

    • 寄存器的保存和恢复也由调用方负责。

    • 函数调用后回收栈空间,恢复 BP 也由主调函数负责。

    函数多指返回的实质:

    • 在栈上开辟多个地址分别存放返回值

    • 如果返回值是存放到堆上,则多了一个复制的动作

    main调用swap的栈的结构图:

    函数多值返回的实现:

    • 主调函数预先分配好空间来存放返回值,被调函数执行时将返回值复制到该返回位置

    • 分配空间的特点:

    Go语言闭包实现的分析

    闭包的结构:

    • 函数指针

    • 对外部环境的引用

    Go闭包的示例代码:

    package main

    /*
    实现一个闭包函数,打印形参的值
    */
    func close(arr int) func() {
    return func() {
    print(arr)
    }
    }

    func main() {
    //设置函数变量
    f := close(100)
    //调用函数
    f()
    }

    在汇编中是通过返回一个结构体来实现闭包的功能:

    type Closure struct {
       F uintptr
       env *Type
    }

    代码分析:

    • F 是返回的匿名函数指针

    • env 是对外部环境变量的引用集合

      • 如果闭包内没有修改外部变量,则 Go 编译器直接优化为值传递。否则是通过指针传递

    章节小结:

    • 函数的底层实现在汇编层面的应用

    • 多值返回在内存层面的实现

    • 闭包在汇编层面的实现以及闭包所返回的结构体的字段内容

  • 相关阅读:
    jquery获得option的值和对option进行操作
    laravel 在添加操作自动完成对时间保存修改
    laravel使用ajax
    mysql操作查询结果case when then else end用法举例
    Laravel框架数据库CURD操作、连贯操作总结
    laravel5.1关于lists函数的bug
    详解AngularJS中的filter过滤器用法
    javascript中的时间处理
    angularJs--$on、$emit和$broadcast的使用
    angularJs--<ui-select>
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/15248495.html
Copyright © 2011-2022 走看看