这几天倒腾了一下Go的ASM,然后写了一个简单的汇编代码,记录一下以防忘记。首先要说明的是Go的ASM是一种中间码,或者说是 众多汇编语言的一种抽象体,但是呢,又不完全是抽象,总之,揉合了Go自定义的一部分,和真实汇编语言。这里主要记录的就是 Go自己定义的那部分。
首先如果你想查看一段Go代码产生的汇编码,可以这样:
$ cat main.go
package main
func add(int64, int64) int64
func main() {
println(add(1, 2))
}
$ go build -gcflags -S .
# github.com/jiajunhuang/test
"".main STEXT size=107 args=0x0 locals=0x28
0x0000 00000 (/home/jiajun/Code/test/main.go:5) TEXT "".main(SB), ABIInternal, $40-0
0x0000 00000 (/home/jiajun/Code/test/main.go:5) MOVQ (TLS), CX
0x0009 00009 (/home/jiajun/Code/test/main.go:5) CMPQ SP, 16(CX)
0x000d 00013 (/home/jiajun/Code/test/main.go:5) PCDATA $0, $
...
首先Go定义了4个虚拟寄存器:
- FP: Frame pointer: arguments and locals. 这个是用来指向当前frame的起始位置
- PC: Program counter: jumps and branches. 这个用来指向下一条要执行的指令的位置
- SB: Static base pointer: global symbols. 这个用来指向全局变量的位置,可以把它看作是程序起始地址
- SP: Stack pointer: top of stack. 这个指向栈顶
然后Go说了:All user-defined symbols are written as offsets to the pseudo-registers FP (arguments and locals) and SB (globals).
也就是说,所有我们自定义的变量,都是基于FP和SB的一个偏移的位置。只不过呢,这个偏移的写法有点不同:foo+4(SB)
。它的意思是:
- 这个变量叫做foo(但是和实际变量不是同一个东西,它不能直接作为变量名使用,只是为了更容易看懂,但是一般会生成和变量名一样的)。
+4
表示相对SB的位置,偏移4byte- 如果有
<>
,说明这个变量是局限于本文件的,相当于C语言里,在函数前加一个static
对于FP的使用&