mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
ch3-05-fix typo
This commit is contained in:
parent
5d9d697030
commit
576b4e28ff
@ -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变量对应的内存设置为10,AX也是10。为了输出a变量,需要将AX寄存器的值放到`0(SP)`位置,这个位置的变量将在调用runtime·printint函数时作为它的参数被打印。因为我们之前已经将AX的值保存到a变量内存中了,因此在调用函数前并不需要在进行寄存器的备份工作。
|
||||
然后给a变量分配一个AX寄存器,并且通过AX寄存器将a变量对应的内存设置为10,AX也是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两个临时变量分配两个内存空间,而且也不需要在每个寄存器变化之后都要写入内存。下面是经过优化的汇编函数:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user