0. Preface
existGo plan9 compilation: Getting through the application to the ground floor The article describes the conversion from an application program to assembly instructions. In this article, we will combine assembly and Go program implementations to handwrite basic assembly instructions to deepen our understanding of Go plan9 assembly.
1. Handwriting compilation
1.1 Global variables
First write a function that prints an integer variable as follows:
// ex1/
package main
var a = 9527
func main() {
print(a)
}
utilizationgo tool compile -S -N -l
Assembly code for the output program:
# go tool compile -S -N -l
STEXT size=50 args=0x0 locals=0x10 funcid=0x0 align=0x0
...
SNOPTRDATA size=8
0x0000 37 25 00 00 00 00 00 00 7%......
Omitted here compilation output, focusing on the
This variable. The output of the
denotes the identifier of the compilation.
SNOPTRDATA
Indicates that the variable is pointer-excluded, which is for the garbage collector, which skips the recycling of this variable when it is scanned.size=8
is the size of this variable. The focus is on the0x0000 37 25 00 00 00 00 00 00
This is the arrangement of 9527 in memory, and 0x2537 is the hexadecimal representation of 9527.
1.1.1 Assembly Implementation of Global Variables
We can write assembly to realize the output of global variables. Note that this article is not a tutorial on assembly, and will not go into too much detail about the syntax of Go plan9 assembly, you can read Cao Da'sAdvanced Programming in Go: Assembly Language(That was really well written!) .
First of all, the Go plan9 assembly is required to work with Go files. Here
// ex1/
package main
import (
"ex1/pkg"
)
func main() {
println()
}
existmain
Print the Id variable of the pkg package in the package.
// ex1/pkg/
package pkg
var Id int
We can write assembly to implement the definition of the Id variable as follows:
// ex1/pkg/pkg_amd64.s
#include ""
GLOBL ·Id(SB),NOPTR,$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
NOPTR
denotes that the variable Id does not include the pointer, and $8 denotes that the variable occupies 8 bytes.DATA
Declare that the variable is stored in memorydata
segments, the segments in memory are as follows.
Run the above program:
# go run
9527
The output variable 9527 has the following memory distribution:
From the variable memory distribution, we can see that only 2 bytes of the int (8 bytes) memory we requested are actually used, and the other bytes are 0. We can save space by requesting 2 bytes of Id as follows. The other bytes are 0. We can save space by requesting 2 bytes for Id as follows:
// ex1/pkg/
package pkg
var Id int16
// ex1/pkg/pkg_amd64.s
#include ""
GLOBL ·Id(SB),NOPTR,$8
DATA ·Id+0(SB)/1,$0x37
DATA ·Id+1(SB)/1,$0x25
Output:
# go run
9527
rewritepkg_amd64.s
:
#include ""
GLOBL ·Id(SB),NOPTR,$2
DATA ·Id+0(SB)/1,$0x37
DATA ·Id+1(SB)/1,$0x25
DATA ·Id+2(SB)/1,$0x20
Output:
# go run
9527
exist0x2537
1 byte above0x20
It will not be addressed by the CPU, but the CPU will read 2 bytes of the Id variable from memory according to the variable declaration and send it to the registers for processing.
1.2 Strings
Combines Go and assembly to print strings:
// ex2/
package main
import (
"ex2/pkg"
"fmt"
)
func main() {
()
}
// ex2/pkg/
package pkg
var Name string
string (computer science)Name
is declared in the pkg package, using the assembly definition variableName
:
// ex2/pkg/pkg_amd64.s
#include ""
GLOBL string<>(SB),NOPTR,$16
DATA string<>+0(SB)/8,$"Hello Wo"
DATA string<>+8(SB)/8,$"rld!"
GLOBL ·Name(SB),NOPTR|RODATA,$16
DATA ·Name+0(SB)/8,$string<>(SB)
DATA ·Name+8(SB)/8,$12
Here the string variable is actually a 16-byte structure including length and pointer. The variable is defined in:
GLOBL ·Name(SB),NOPTR|RODATA,$16
DATA ·Name+0(SB)/8,$string<>(SB)
DATA ·Name+8(SB)/8,$12
The first 8 bytes point to the memory address where the actual string is stored, and the last 8 bytes are the length of the string. The real string is stored in a data segment in memory. Herestring<>
denote the variablestring
No variables can be exported, otherwise external Go programs can access the string variables directly.
Draw the memory distribution as follows:
2. Summary
We can continue with the assembly implementation of functions along the above lines, but the point of this article is to understand how assembly is written, not to actually write it. We have two simple global variables and strings through the compilation of the example, to understand the assembly code to write. In the actual application will almost never write themselves, the emphasis is on understanding. For more on assembly implementation you can refer to Cao Da'sGo Advanced Programming。