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

ch3.5: 修复代码错误

This commit is contained in:
chai2010 2018-12-07 09:45:44 +08:00
parent 7665b25687
commit dc4b9a251c

View File

@ -53,8 +53,8 @@ TEXT ·main(SB), $24-0
// 以a为参数调用函数 // 以a为参数调用函数
MOVQ AX, 0(SP) MOVQ AX, 0(SP)
CALL runtime·printint CALL runtime·printint(SB)
CALL runtime·printnl CALL runtime·printnl(SB)
// 函数调用后, AX/BX 寄存器可能被污染, 需要重新加载 // 函数调用后, AX/BX 寄存器可能被污染, 需要重新加载
MOVQ a-8*2(SP), AX // AX = a MOVQ a-8*2(SP), AX // AX = a
@ -63,13 +63,13 @@ TEXT ·main(SB), $24-0
// 计算b值, 并写入内存 // 计算b值, 并写入内存
MOVQ AX, BX // BX = AX // b = a MOVQ AX, BX // BX = AX // b = a
ADDQ BX, BX // BX += BX // b += a ADDQ BX, BX // BX += BX // b += a
MULQ AX, BX // BX *= AX // b *= a IMULQ AX, BX // BX *= AX // b *= a
MOVQ BX, b-8*1(SP) // b = BX MOVQ BX, b-8*1(SP) // b = BX
// 以b为参数调用函数 // 以b为参数调用函数
MOVQ BX, 0(SP) MOVQ BX, 0(SP)
CALL runtime·printint CALL runtime·printint(SB)
CALL runtime·printnl CALL runtime·printnl(SB)
RET RET
``` ```
@ -82,6 +82,8 @@ TEXT ·main(SB), $24-0
在调用函数返回之后全部的寄存器将被视为可能被调用的函数修改因此我们需要从a、b对应的内存中重新恢复寄存器AX和BX。然后参考上面Go语言中b变量的计算方式更新BX对应的值计算完成后同样将BX的值写入到b对应的内存。 在调用函数返回之后全部的寄存器将被视为可能被调用的函数修改因此我们需要从a、b对应的内存中重新恢复寄存器AX和BX。然后参考上面Go语言中b变量的计算方式更新BX对应的值计算完成后同样将BX的值写入到b对应的内存。
需要说明的是,上面的代码中`IMULQ AX, BX`使用了`IMULQ`指令来计算乘法。没有使用`MULQ`指令的原因是`MULQ`指令默认使用`AX`保存结果。读者可以自己尝试用`MULQ`指令改写上述代码。
最后以b变量作为参数再次调用runtime·printint函数进行输出工作。所有的寄存器同样可能被污染不过main函数马上就返回了因此不再需要恢复AX、BX等寄存器了。 最后以b变量作为参数再次调用runtime·printint函数进行输出工作。所有的寄存器同样可能被污染不过main函数马上就返回了因此不再需要恢复AX、BX等寄存器了。
重新分析汇编改写后的整个函数会发现里面很多的冗余代码。我们并不需要a、b两个临时变量分配两个内存空间而且也不需要在每个寄存器变化之后都要写入内存。下面是经过优化的汇编函数 重新分析汇编改写后的整个函数会发现里面很多的冗余代码。我们并不需要a、b两个临时变量分配两个内存空间而且也不需要在每个寄存器变化之后都要写入内存。下面是经过优化的汇编函数
@ -95,8 +97,8 @@ TEXT ·main(SB), $16-0
MOVQ AX, temp-8(SP) // temp = AX MOVQ AX, temp-8(SP) // temp = AX
// 以a为参数调用函数 // 以a为参数调用函数
CALL runtime·printint CALL runtime·printint(SB)
CALL runtime·printnl CALL runtime·printnl(SB)
// 函数调用后, AX 可能被污染, 需要重新加载 // 函数调用后, AX 可能被污染, 需要重新加载
MOVQ temp-8*1(SP), AX // AX = temp MOVQ temp-8*1(SP), AX // AX = temp
@ -104,7 +106,7 @@ TEXT ·main(SB), $16-0
// 计算b值, 不需要写入内存 // 计算b值, 不需要写入内存
MOVQ AX, BX // BX = AX // b = a MOVQ AX, BX // BX = AX // b = a
ADDQ BX, BX // BX += BX // b += a ADDQ BX, BX // BX += BX // b += a
MULQ AX, BX // BX *= AX // b *= a IMULQ AX, BX // BX *= AX // b *= a
// ... // ...
``` ```