3.1.2 定义整数变量
为了简单,我们先用Go语言定义并赋值一个整数变量,然后查看生成的汇编代码。
首先创建一个pkg.go文件,内容如下:
package pkg
var Id = 9527
代码中只定义了一个int类型的包级变量,并进行了初始化。然后用以下命令查看的Go语言程序对应的伪汇编代码:
$ go tool compile -S pkg.go
"".Id SNOPTRDATA size=8
0x0000 37 25 00 00 00 00 00 00 '.......
其中go tool compile
命令用于调用Go语言提供的底层命令工具,其中-S
参数表示输出汇编格式。输出的汇编比较简单,其中"".Id
对应Id变量符号,变量的内存大小为8个字节。变量的初始化内容为37 25 00 00 00 00 00 00
,对应十六进制格式的0x2537,对应十进制为9527。SNOPTRDATA是相关的标志,其中NOPTR表示数据中不包含指针数据。
以上的内容只是目标文件对应的汇编,和Go汇编语言虽然相似当并不完全等价。Go语言官网自带了一个Go汇编语言的入门教程,地址在:https://golang.org/doc/asm 。
Go汇编语言提供了DATA命令用于初始化包变量,DATA命令的语法如下:
DATA symbol+offset(SB)/width, value
其中symbol为变量在汇编语言中对应的标识符,offset是符号开始地址的偏移量,width是要初始化内存的宽度大小,value是要初始化的值。其中当前包中Go语言定义的符号symbol,在汇编代码中对应·symbol
,其中“·”中点符号为一个特殊的unicode符号。
我们采用以下命令可以给Id变量初始化为十六进制的0x2537,对应十进制的9527(常量需要以美元符号$开头表示):
DATA ·Id+0(SB)/1,$0x37
DATA ·Id+1(SB)/1,$0x25
变量定义好之后需要导出以供其它代码引用。Go汇编语言提供了GLOBL命令用于将符号导出:
GLOBL symbol(SB), width
其中symbol对应汇编中符号的名字,width为符号对应内存的大小。用以下命令将汇编中的·Id变量导出:
GLOBL ·Id, $8
现在已经初步完成了用汇编定义一个整数变量的工作。
为了便于其它包使用该Id变量,我们还需要在Go代码中声明该变量,同时也给变量指定一个合适的类型。修改pkg.go的内容如下:
package pkg
var Id int
现状Go语言的代码不再是定义一个变量,语义变成了声明一个变量(声明一个变量时不能再进行初始化操作)。而Id变量的定义工作已经在汇编语言中完成了。
我们将完整的汇编代码放到pkg_amd64.s文件中:
GLOBL ·Id(SB),$8
DATA ·Id+0(SB)/1,$0x37
DATA ·Id+1(SB)/1,$0x25
DATA ·Id+2(SB)/1,$0x00
DATA ·Id+3(SB)/1,$0x00
DATA ·Id+4(SB)/1,$0x00
DATA ·Id+5(SB)/1,$0x00
DATA ·Id+6(SB)/1,$0x00
DATA ·Id+7(SB)/1,$0x00
文件名pkg_amd64.s的后缀名表示AMD64环境下的汇编代码文件。
虽然pkg包是用汇编实现,但是用法和之前的Go语言版本完全一样:
package main
import pkg "pkg包的路径"
func main() {
println(pkg.Id)
}
对于Go包的用户来说,用Go汇编语言或Go语言实现并无任何区别。
学员评价