mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
ch3-01: 完善
This commit is contained in:
parent
32865f9369
commit
537decf3bd
@ -1,6 +1,108 @@
|
|||||||
# 3.1. 快速入门
|
# 3.1. 快速入门
|
||||||
|
|
||||||
在第一章的“Hello, World 的革命”一节中,我们已经见过一个Go汇编程序。本节我们将通过由浅入深的一系列小例子来快速掌握Go汇编的简单用法。
|
在第一章的“Hello, World 的革命”一节中,我们已经见过一个Go汇编程序。本节我们将通过分析简单的Go程序输出的汇编代码,然后照猫画虎用汇编实现一个简单的输出程序。
|
||||||
|
|
||||||
|
## 实现和声明
|
||||||
|
|
||||||
|
Go汇编语言并不是一个独立的语言,主要原因是因为Go汇编程序无法独立使用。Go汇编代码必须以Go包的方式被组织,同时包中至少要有一个Go语言文件。如果Go汇编代码中定义的变量和函数要被其它Go语言代码引用,还需要通过Go语言代码将汇编中定义的符号声明出来。用于变量的定义和函数的定义Go汇编文件类似于C语言中的.c文件。而用于导出汇编中定义符号的Go源文件类似于C语言的.h文件。
|
||||||
|
|
||||||
|
## 定义整数变量
|
||||||
|
|
||||||
|
为了简单,我们先用Go语言定义并赋值一个整数变量,然后查看生成的汇编代码。
|
||||||
|
|
||||||
|
创建pkg.go文件,内容如下:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
var Id = 9527
|
||||||
|
```
|
||||||
|
|
||||||
|
然后用以下命令查看的Go语言程序对应的伪汇编代码:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go tool compile -S pkg.go
|
||||||
|
"".Id SNOPTRDATA size=8
|
||||||
|
0x0000 37 25 00 00 00 00 00 00 '.......
|
||||||
|
```
|
||||||
|
|
||||||
|
输出的汇编比较简单,其中`"".Id`对应Id变量符号,变量的内存大小为8个字节。变量的初始化内容为`37 25 00 00 00 00 00 00`,对应十六进制格式的0x2537,对应十进制为9527。SNOPTRDATA是相关的标志,暂时忽略。
|
||||||
|
|
||||||
|
以上的内容只是目标文件对于的汇编,和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的内容如下:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
var Id int
|
||||||
|
```
|
||||||
|
|
||||||
|
表示声明一个一个int类型的Id变量。因为该变量已经在汇编中定义,因此Go语言部分只是声明变量,声明的变量不能含义初始化的操作。
|
||||||
|
|
||||||
|
完整的汇编代码在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语言实现并无区别。
|
||||||
|
|
||||||
|
## 定义字符串变量
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
## Go语言版本
|
## Go语言版本
|
||||||
|
|
||||||
|
3
ch3-asm/pkg.go
Normal file
3
ch3-asm/pkg.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
var id int = 9527
|
@ -6,5 +6,5 @@ Go语言中很多设计思想和工具都是传承自Plan9操作系统,Go汇
|
|||||||
|
|
||||||
对于每一个严肃的Gopher,Go汇编语言都是一个不可忽视的技术。因为哪怕只懂一点点汇编,也便于更好地理解计算机,将更容易理解Go语言中动态栈/接口等高级特性的实现原理。而且掌握了Go汇编语言之后,你将不用担心再被其它所谓的任何高级编程语言用户鄙视。
|
对于每一个严肃的Gopher,Go汇编语言都是一个不可忽视的技术。因为哪怕只懂一点点汇编,也便于更好地理解计算机,将更容易理解Go语言中动态栈/接口等高级特性的实现原理。而且掌握了Go汇编语言之后,你将不用担心再被其它所谓的任何高级编程语言用户鄙视。
|
||||||
|
|
||||||
本章我们将简单地探讨Go汇编语言的基础用法。
|
本章我们将以AMD64为主要开发环境,简单地探讨Go汇编语言的基础用法。
|
||||||
|
|
||||||
|
3
examples/ch3-01-quick-guide/id-01/pkg.go
Normal file
3
examples/ch3-01-quick-guide/id-01/pkg.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
var Id = 9527
|
9
examples/ch3-01-quick-guide/id-01/runme.go
Normal file
9
examples/ch3-01-quick-guide/id-01/runme.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import pkg "."
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(pkg.Id)
|
||||||
|
}
|
3
examples/ch3-01-quick-guide/id-02/pkg.go
Normal file
3
examples/ch3-01-quick-guide/id-02/pkg.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
var Id int
|
11
examples/ch3-01-quick-guide/id-02/pkg_amd64.s
Normal file
11
examples/ch3-01-quick-guide/id-02/pkg_amd64.s
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
GLOBL ·Id(SB),$8
|
11
examples/ch3-01-quick-guide/id-02/runme.go
Normal file
11
examples/ch3-01-quick-guide/id-02/runme.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
pkg "."
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(pkg.Id)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user