Assembly language

As we all know, Go language is a compiled language. The XXx. Go file we write will eventually be compiled into executable files to run (in Windows, it is the file with the suffix exe, and in Linux, it is the file with executable information in the header information).

In between the go file and the final executable, there is an object file.

Go files are code files that we write according to the go language syntax.

The executable file is stored in the 01 binary file known by the operating system.

The object file is assembly language code.

For example

This article will not delve deeply into assembly language knowledge, but will share with you a small example of one of the ways to think about learning Go.

As we all know, Go allows multiple assignments to variables, that is, multiple variables assigned simultaneously in one line of code:

a, b := 1.2
Copy the code

As you can see, we assign both variables A and B in one line of code.

Since multiple assignment is to calculate the result on the right-hand side of the equal sign first and then assign the whole variable on the left-hand side of the equal sign, we can complete the process of interchanging the values of the two variables in one line:

a, b = b, a
Copy the code

So how does the Go language implement this operation at the bottom?

Let’s write a complete main.go file:

package main

func main(a) {
        a := 888
        b := 999
        a, b = b, a
}
Copy the code

Then, we went to the Internet and found the following commands to generate assembly code:

$ go tool compile -S main.go
Copy the code

We get the following output:

"".main STEXT nosplit size=1 args=0x0 locals=0x0 funcid=0x0 0x0000 00000 (main.go:3) TEXT "".main(SB), NOSPLIT|ABIInternal, $0-0 0x0000 00000 (main.go:3) FUNCDATA $0, Gclocals · 33 cdeccccebe80329f1fdbee7f5874cb (SB) 0 x0000 00000 (main) go: 3) FUNCDATA $1. Gclocals · 33 cdeccccebe80329f1fdbee7f5874cb (SB) 0 x0000 00000 (main) go: 7) RET 0 x0000 c3. Go. Cuinfo. Packagename. SDWARFCUINFO dupok size=0 0x0000 6d 61 69 6e main "".. inittask SNOPTRDATA size=24 0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x0010 00 00 00 00 00 00 00 00 ........ Gclocals · 33 cdeccccebe80329f1fdbee7f5874cb SRODATA dupok x0000 size = 8 0 01 00 00 00 00 00 00 00...Copy the code

We found that the assembly code jumped directly from main.go:3 to main.go:7, leaving out lines 4, 5, and 6.

A guess: since variables A and B are only declared and assigned, they are not used, so these three lines are optimized out when assembly code is generated.

Let’s look at the official documentation to see how each parameter of go Tool compile is used.

The official documentation address: golang. Google. Cn/CMD/compile…

Looking back, it seems that the fourth parameter is related to compile-time optimization:

-N
        Disable optimizations.
Copy the code

Translation: Disable optimization

Yi? Isn’t that exactly what we’re looking for?

We added it to the command. The complete command reads as follows:

$ go tool compile -N -S main.go
Copy the code

You can get the full assembly code this time, but let’s focus on just a few important lines:

0x000e 00014 (main.go:4)        MOVQ    $888."".a+8(SP)
0x0017 00023 (main.go:5)        MOVQ    $999."".b(SP)
0x001f 00031 (main.go:6)         MOVQ    "".a+8(SP), AX
0x0024 00036 (main.go:6)        MOVQ    AX, ""..autotmp_2+16(SP)
0x0029 00041 (main.go:6)        MOVQ    "".b(SP), AX
0x002d 00045 (main.go:6)        MOVQ    AX, "".a+8(SP)
0x0032 00050 (main.go:6)        MOVQ    ""..autotmp_2+16(SP), AX
0x0037 00055 (main.go:6)        MOVQ    AX, "".b(SP)
Copy the code

Because the assembly language used by Go is Plan9, all the assembly instructions are different from those we learned about x86, but there are similarities.

MOVQ is followed by two parameters, which write 8 bytes of data from the first parameter to the address of the second parameter.

Then, introduce some registers used:

  • AX: temporary register, used to store temporary data, correspondingrax
  • BX: temporary register, used to store temporary data, correspondingrbx
  • SP:Stack PointerTop of stack pointer, here isPseudo register

SP is a pointer to the top of the stack. It is a pointer to the top of the stack.

  1. You need to enclose it with parentheses when you use it.
  2. The number before plus or minus represents the displacement of the current top of the stack pointer address;
  3. Before the numberaorbJust a symbol, no specific meaning, we can simply understand to increase readability. In fact, it is this notation that distinguishes pseudo-registers from hardware registers.

Let’s take a look at each piece of assembly code:

MOVQ $888, “”. A +8(SP) : writes the decimal number 888 to the memory at address SP+8. So a: is equal to 888

MOVQ $999, “”. B (SP) : writes the decimal number 999 to the memory at address SP. So b: is equal to 999

MOVQ “”. A +8(SP), AX: write data in memory at address SP+8 to AX register. That’s putting the value of variable A into the AX register.

MOVQ AX, “”.. Autotmp_2 +16(SP) : Puts the AX register into a temporary variable with the address SP+16

MOVQ “”. B (SP), AX: Similarly, place the value of variable b in the AX register.

MOVQ AX, “”. A +8(SP) : write a value from AX to SP+8.

MOVQ “”.. Autotmp_2 +16(SP), AX: Puts the value of the temporary variable into the AX register.

MOVQ AX, “”. B (SP) : Assigns data from the AX register to variable B.

At this point, the exchange of variables A and B is completed.

As you can see, in assembly code, variable A corresponds to the block of memory at address SP+8, and variable B corresponds to the block of memory at address SP.

The block of memory at address SP+16 is used to assist in the exchange of temporary variables.

conclusion

Although we do not introduce temporary variables to exchange variables in Go language like C language, by observing its corresponding assembly code, we find that Go language still uses temporary variables to assist the exchange of variables.

extension

As a little homework assignment, if you have a computer around you, you can try to see how the assembly code for three variable swaps is implemented:

a := 777
b := 888
c := 999
a, b, c  = b, c, a
Copy the code