最近有时间研究下Golang的汇编,在开始之前,最好能了解下X86的汇编。
Go汇编使用的是Plan9汇编,网上有很多资料可以查看,不过这篇我打算从自己亲手调试过的代码开始记录。Go使用的版本是1.15,如果要跟着文章调试,最好版本一样避免差别。
main函数的汇编代码(main_amd64.s):
TEXT ·main(SB),$24 //当处于main时,打印当前的BP指向 LEAQ 0(BP),AX MOVQ AX,0(SP) CALL ·println(SB) //打印SP指向 MOVQ Q+0(SP),AX MOVQ AX,0(SP) CALL ·println(SB) MOVQ SP,AX MOVQ AX,0(SP) CALL ·println(SB) LEAQ Q-8*2(SP),AX MOVQ AX,0(SP) CALL ·println(SB) LEAQ a-8*2(SP),AX MOVQ AX,0(SP) CALL ·println(SB) //初始化两个变量a,b MOVQ $0,a-8*2(SP) MOVQ $0,b-8*1(SP) MOVQ $10,AX //将新值写入AX MOVQ AX,a-8*2(SP) // a=AX,a=10 MOVQ AX,0(SP) //以AX(a)为参数,调用println CALL ·println(SB) MOVQ a-8*2(SP),AX // AX=10 MOVQ b-8*1(SP),BX // BX=0 MOVQ AX,BX //BX=10 ADDQ BX,BX //BX=20 IMULQ AX,BX //BX=200 MOVQ BX,b-8*1(SP) MOVQ BX,0(SP) CALL ·println(SB) MOVQ $100,AX MOVQ AX,0(SP) CALL ·printnl_nosplit(SB) RET
测试方法(12_amd64.s)
#include "textflag.h" TEXT ·printnl_nosplit(SB),NOSPLIT,$8 MOVQ BP,AX MOVQ AX,+0(SP) CALL ·println(SB) MOVQ a+8*0(SP),AX MOVQ AX,+0(SP) CALL ·println(SB) MOVQ SP,AX MOVQ AX,+0(SP) CALL ·println(SB) LEAQ a+0(SP),AX MOVQ AX,+0(SP) CALL ·println(SB) RET
main主文件代码
package main import "fmt" func printnl_nosplit(a int) func println(a int){ fmt.Printf("%x\n",a) } func main()