1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-24 12:32:21 +00:00

ch3-04: 增加图

This commit is contained in:
chai2010 2018-06-15 14:24:06 +08:00
parent 51fbc4c27e
commit d9bd83a2ff

View File

@ -6,6 +6,9 @@
函数标识符通过TEXT汇编指令定义表示该行开始的指令定义在TEXT内存段。TEXT语句后的指令一般对应函数的实现但是对于TEXT指令本身来说并不关心后面是否有指令。我个人绝对TEXT和LABEL定义的符号是类似的区别只是LABEL是用于跳转标号但是本质上他们都是通过标识符映射一个内存地址。
![](../images/ch3-func-decl-01.ditaa.png)
函数的定义的语法如下:
```
@ -46,6 +49,8 @@ func Add() (a []int) // reflect.SliceHeader 切片头刚好也是 3 个 int 成
对于函数来说最重要是是函数对外提供的API约定包含函数的名称、参数和返回值。当名称和参数返回都确定之后如何精确计算参数和返回值的大小是第一个需要解决的问题。
![](../images/ch3-func-decl-02.ditaa.png)
比如有一个Foo函数的签名如下
```go
@ -129,8 +134,14 @@ func SomeFunc(FP *SomeFunc_args_and_returns) {
代码完全和Foo函数参数的方式类似。唯一的差异是每个函数的偏移量这有`unsafe.Offsetof`函数自动计算生成。因为Go结构体中的每个成员已经满足了对齐要求因此采用通用方式得到每个参数的偏移量也是满足对齐要求的。
![](../images/ch3-func-arg-01.ditaa.png)
<!-- TODO: 内容 -->
## 函数中的局部变量
<!-- TODO: 图 -->
从Go语言函数角度讲局部变量是函数内明确定义的变量同时也包含函数的参数和返回值变量。但是从Go汇编角度看局部变量是指函数运行时在当前函数栈帧所对应的内存内的变量不包含函数的参数和返回值因为访问方式有差异。函数栈帧的空间主要由函数参数和返回值、局部变量和被调用其它函数的参数和返回值空间组成。为了便于理解我们可以将汇编函数的局部变量类比为Go语言函数中显式定义的变量不包含参数和返回值部分。
为了便于访问局部变量Go汇编语言引入了伪SP寄存器对应当前栈帧的底部。因为在当前栈帧时间栈的底部是固定不变的因此局部变量的相对于伪SP的偏移量也就是固定的这可以简化局部变量的维护工作。SP真伪区分只有一个原则如果使用SP时有一个临时标识符前缀就是伪SP否则就是真SP寄存器。比如`a(SP)``b+8(SP)`有a和b临时前缀这里都是伪SP而前缀部分一般用于表示局部变量的名字。而`(SP)``+8(SP)`没有临时标识符作为前缀它们都是真SP寄存器。