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

ch3-05-fix typo

This commit is contained in:
sfw 2018-06-29 17:06:13 +08:00
parent 5d9d697030
commit 576b4e28ff

View File

@ -38,7 +38,7 @@ func main() {
}
```
首选模仿C语言的处理方式在函数入口出声明全部的局部变量。然后将根据MOV、ADD、MUL等指令的风格将之前的变量表达式展开为用`=``+=``*=`几种运算表达的多个指令。最后用runtime包内部的printint和printnl函数代替之前的println函数输出结果。
首选模仿C语言的处理方式在函数入口处声明全部的局部变量。然后根据MOV、ADD、MUL等指令的风格将之前的变量表达式展开为用`=``+=``*=`几种运算表达的多个指令。最后用runtime包内部的printint和printnl函数代替之前的println函数输出结果。
经过用汇编的思维改写过后上述的Go函数虽然看着繁琐了一点但是还是比较容易理解的。下面我们进一步尝试将改写后的函数继续转译为汇编函数
@ -78,11 +78,11 @@ TEXT ·main(SB), $24-0
在函数的开始处先将变量初始化为0值其中`a-8*2(SP)`对应a变量、`a-8*1(SP)`对应b变量因为a变量先定义因此a变量的地址更小
然后给a变量分配一个AX寄存器并且通过AX寄存器将a变量对应的内存设置为10AX也是10。为了输出a变量需要将AX寄存器的值放到`0(SP)`位置这个位置的变量将在调用runtime·printint函数时作为它的参数被打印。因为我们之前已经将AX的值保存到a变量内存中了因此在调用函数前并不需要进行寄存器的备份工作。
然后给a变量分配一个AX寄存器并且通过AX寄存器将a变量对应的内存设置为10AX也是10。为了输出a变量需要将AX寄存器的值放到`0(SP)`位置这个位置的变量将在调用runtime·printint函数时作为它的参数被打印。因为我们之前已经将AX的值保存到a变量内存中了因此在调用函数前并不需要进行寄存器的备份工作。
在调用函数返回之后全部的寄存器将被视为被调用的函数修改因此我们需要从a、b对应的内存中重新恢复寄存器AX和BX。然后参考上面Go语言中b变量的计算方式更新BX对应的值计算完成后同样将BX的值写入到b对应的内存。
最后以b变量作为参数再次调用runtime·printint函数进行输出工作。所有的寄存器通样可能被污染不过main马上就返回不在需要使用AX、BX等寄存器因此就不需要再次恢复寄存器的值了。
最后以b变量作为参数再次调用runtime·printint函数进行输出工作。所有的寄存器同样可能被污染不过main马上就返回不再需要使用AX、BX等寄存器因此就不需要再次恢复寄存器的值了。
重新分析汇编改写后的整个函数会发现里面很多的冗余代码。我们并不需要a、b两个临时变量分配两个内存空间而且也不需要在每个寄存器变化之后都要写入内存。下面是经过优化的汇编函数