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:
parent
51fbc4c27e
commit
d9bd83a2ff
@ -6,6 +6,9 @@
|
||||
|
||||
函数标识符通过TEXT汇编指令定义,表示该行开始的指令定义在TEXT内存段。TEXT语句后的指令一般对应函数的实现,但是对于TEXT指令本身来说并不关心后面是否有指令。我个人绝对TEXT和LABEL定义的符号是类似的,区别只是LABEL是用于跳转标号,但是本质上他们都是通过标识符映射一个内存地址。
|
||||
|
||||

|
||||
|
||||
|
||||
函数的定义的语法如下:
|
||||
|
||||
```
|
||||
@ -46,6 +49,8 @@ func Add() (a []int) // reflect.SliceHeader 切片头刚好也是 3 个 int 成
|
||||
|
||||
对于函数来说,最重要是是函数对外提供的API约定,包含函数的名称、参数和返回值。当名称和参数返回都确定之后,如何精确计算参数和返回值的大小是第一个需要解决的问题。
|
||||
|
||||

|
||||
|
||||
比如有一个Foo函数的签名如下:
|
||||
|
||||
```go
|
||||
@ -129,8 +134,14 @@ func SomeFunc(FP *SomeFunc_args_and_returns) {
|
||||
代码完全和Foo函数参数的方式类似。唯一的差异是每个函数的偏移量,这有`unsafe.Offsetof`函数自动计算生成。因为Go结构体中的每个成员已经满足了对齐要求,因此采用通用方式得到每个参数的偏移量也是满足对齐要求的。
|
||||
|
||||
|
||||

|
||||
|
||||
<!-- TODO: 内容 -->
|
||||
|
||||
## 函数中的局部变量
|
||||
|
||||
<!-- TODO: 图 -->
|
||||
|
||||
从Go语言函数角度讲,局部变量是函数内明确定义的变量,同时也包含函数的参数和返回值变量。但是从Go汇编角度看,局部变量是指函数运行时,在当前函数栈帧所对应的内存内的变量,不包含函数的参数和返回值(因为访问方式有差异)。函数栈帧的空间主要由函数参数和返回值、局部变量和被调用其它函数的参数和返回值空间组成。为了便于理解,我们可以将汇编函数的局部变量类比为Go语言函数中显式定义的变量,不包含参数和返回值部分。
|
||||
|
||||
为了便于访问局部变量,Go汇编语言引入了伪SP寄存器,对应当前栈帧的底部。因为在当前栈帧时间栈的底部是固定不变的,因此局部变量的相对于伪SP的偏移量也就是固定的,这可以简化局部变量的维护工作。SP真伪区分只有一个原则:如果使用SP时有一个临时标识符前缀就是伪SP,否则就是真SP寄存器。比如`a(SP)`和`b+8(SP)`有a和b临时前缀,这里都是伪SP,而前缀部分一般用于表示局部变量的名字。而`(SP)`和`+8(SP)`没有临时标识符作为前缀,它们都是真SP寄存器。
|
||||
|
Loading…
x
Reference in New Issue
Block a user