Reputation: 4020
A while ago someone asked a question about how Golang actually swaps variables in statements like a, b = b, a
.
To answer, I got out my Golang compiler, put on my thinking cap and crafted an answer to said question. SO questions are supposed to be self-contained, so here's my answer truncated for brevity:
To figure out how the compiler makes native code, we need to look at the assembly code it generates, which is turned into machine code by the linker.
I wrote a little Go program to help with this:
package main import "fmt" func main() { fmt.Println(myfunction()) } func myfunction() []int { a, b := 10, 5 b, a = a, b return []int{a, b} }
Using
go tool compile -S > swap.s
, I found these four lines, which correspond to the first two lines ofmyfunction
in the Go code: (note this is for my 64-bit machine; the output will differ on other architechtures like 32-bit)0x0028 00040 (swap.go:10) MOVQ $10, CX ; var a = 10 0x002f 00047 (swap.go:10) MOVQ $5, AX ; var b = 5 0x0036 00054 (swap.go:11) MOVQ CX, "".b+16(SP) ; copy a to *b+16 0x003b 00059 (swap.go:11) MOVQ AX, "".a+24(SP) ; copy b to *a+24
Looking at the Golang docs on asm, we can see the assembler uses indirection to juggle the values.
When the program runs, the CPU is smart enough to see what's happening and use a register to avoid overwriting the existing value.
My comment, informed by my meager knowledge of (Intel) x86 Assembly, garnered 6 votes and my answer got an accept and 3 votes.
What are the four lines of Golang assembly actually doing? Was my answer correct?
I ask because the docs I linked to aren't very (at all) exhaustive.
Upvotes: 3
Views: 396
Reputation: 39551
It's loading the constants 10 and 5 into CPU registers and then storing registers into the stack locations reserved for the variables a
and b
.
It's the equivalent to:
CX := 10
AX := 5
b := CX
a := AX
Note a half decent optimizing compiler should optimize this into code that stores the constants directly into the locations on the stack:
b := 10
a := 5
Or better yet eliminates the variables entirely:
return []int{5, 10}
Upvotes: 3
Reputation: 166549
a, b := 10, 5
b, a = a, b
0x0028 00040 (swap.go:10) MOVQ $10, CX ; CX = 10
0x002f 00047 (swap.go:10) MOVQ $5, AX ; AX = 5
0x0036 00054 (swap.go:11) MOVQ CX, "".b+16(SP) ; b = CX or *(SP+16) = CX
0x003b 00059 (swap.go:11) MOVQ AX, "".a+24(SP) ; a = AX or *(SP+24) = CX
CX
, AX
, and SP
are registers. a
and b
are variables on the stack at SP+24 and SP+16 respectively.
Upvotes: 3