mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 12:32:21 +00:00
ch3-02: 完善
This commit is contained in:
parent
2794974b19
commit
047c5a6185
@ -140,3 +140,17 @@ Go汇编为了简化汇编代码的编写,引入了PC、FP、SP、SB四个伪
|
||||
|
||||
当需要区分伪寄存器和真寄存器的时候只需要记住一点:伪寄存器一般需要一个标识符和偏移量为前缀,如果没有标识符前缀则是真寄存器。比如`(SP)`、`+8(SP)`没有标识符前缀为真SP寄存器,而`a(SP)`、`b+8(SP)`有标识符为前缀表示伪寄存器。
|
||||
|
||||
|
||||
## Go函数调用规范
|
||||
|
||||
和C语言函数不同,Go语言函数的参数和返回值完全通过栈传递。下面是Go函数调用时栈的布局图:
|
||||
|
||||

|
||||
|
||||
在汇编定义函数时,我们需要关注framesize和argsize,分别对应函数帧大学和函数参数和返回值的大小。
|
||||
|
||||
因为函数的参数和返回大学可以通过Go函数的签名解析得到,因此argsize一般是可以省略的。需要注意的是,输入参数和返回值依此从低地址向高地址顺序排列。同时每个参数的类型需要满足地址对齐要求。
|
||||
|
||||
帧大小相对复杂一点:其中包含函数的局部变量和调用其它函数时的参数和返回值空间。局部变量也是从低地址向高地址顺序排列的,因此它们栈增长方向是相反的。
|
||||
|
||||
在最下面灰色的部分是调用函数后的返回地址。当执行CALL指令时,会自动将SP向下移动,并将返回地址和SP寄存器存入栈中。然后被调用的函数执行RET返回指令时,先从栈恢复BP和SP寄存器,并根取出的返回地址跳转到对应的指令执行。
|
||||
|
BIN
images/ch3-func-stack-frame-layout-01.ditaa.png
Normal file
BIN
images/ch3-func-stack-frame-layout-01.ditaa.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
63
images/ch3-func-stack-frame-layout-01.ditaa.txt
Normal file
63
images/ch3-func-stack-frame-layout-01.ditaa.txt
Normal file
@ -0,0 +1,63 @@
|
||||
Stack frame layout X86/AMD64
|
||||
|
||||
---=- +-=-------------------------+
|
||||
^ | |
|
||||
| | ret1 to caller |
|
||||
| | |
|
||||
| +-=-------------------------+<--ret1+24(FP)
|
||||
| | |
|
||||
: | ret0 to caller |
|
||||
| |
|
||||
argsize +-=-------------------------+<--ret0+16(FP)
|
||||
| |
|
||||
: | arg1 from caller |
|
||||
| | |
|
||||
| +-=-------------------------+<--arg1+8(FP)
|
||||
| | |
|
||||
| | arg0 from caller |
|
||||
v | |
|
||||
---=- +-=-------------------------+<--arg0+0(FP)
|
||||
| |
|
||||
| parent return address |
|
||||
| |
|
||||
+---------------------------+
|
||||
| c9D5 |
|
||||
| caller's BP |
|
||||
| (if framepointer_enabled) |
|
||||
---=- +---------------------------+<--BP(pseudo SP)
|
||||
^ | cD0A |
|
||||
| | local varable2 |
|
||||
| | |
|
||||
| +---------------------------+<--var2-8(SP)
|
||||
| | cD0A |
|
||||
| | local varable1 |
|
||||
| | |
|
||||
| +---------------------------+<--var1-16(SP)
|
||||
| | cD0A |
|
||||
| | local varable0 |
|
||||
| | |
|
||||
| +---------------------------+<--var0-24(SP)
|
||||
: | cYEL |
|
||||
| | ret1 from callee |
|
||||
| |
|
||||
framesize+---------------------------+<--24(SP)
|
||||
| cYEL |
|
||||
| | ret0 from callee |
|
||||
: | |
|
||||
| +---------------------------+<--16(SP)
|
||||
| | cF51 |
|
||||
| | arg1 to callee |
|
||||
| | |
|
||||
| +---------------------------+<--8(SP)
|
||||
| | cF51 |
|
||||
| | arg0 to callee |
|
||||
v | |
|
||||
---=- +---------------------------+<--0(SP)
|
||||
| cAAA |
|
||||
| return address |
|
||||
| |
|
||||
+---------------------------+
|
||||
| cAAA |
|
||||
| caller's BP |
|
||||
| (if framepointer_enabled) |
|
||||
+---------------------------+
|
Loading…
x
Reference in New Issue
Block a user