提示:閱讀本節需要有一定的組合基礎,想學習組合的同學,我們這裡準備了一套《組合語言入門教學》供大家學習。
push ebp; mov esp ebp
這樣的程式碼,相反其是在主調函數呼叫被調函數的前後有一個儲存現場和恢復現場的動作。//開闢棧空間,壓棧 BP 儲存現場 SUBQ $x, SP //為函數開闢裁空間 MOVQ BP, y(SP) //儲存當前函數 BP 到 y(SP)位直, y 為相對 SP 的偏移量 LEAQ y(SP), BP //重直 BP,使其指向剛剛儲存 BP 舊值的位置,這裡主要 //是方便後續 BP 的恢復 //彈出棧,恢復 BP MOVQ y(SP), BP //恢復 BP 的值為呼叫前的值 ADDQ $x, SP //恢復 SP 的值為函數開始時的位
package main func swap (a, b int) (x int, y int) { x = b y = a return } func main() { swap(10, 20) }
//- S 產生組合的程式碼
//- N 禁用優化
//- 1 禁用內聯
GOOS=linux GOARCH=amd64 go tool compile -1 -N -S swap.go >swap.s 2>&1
"".swap STEXT nosplit size=39 args=0x20 locals=0x0 0x0000 00000 (swap.go:4) TEXT "".swap(SB), NOSPLIT, $0 - 32 0x0000 00000 (swap.go:4) FUNCDATA $0, gclocals.ff19ed39bdde8a01a800918ac3ef0ec7(SB) 0x0000 00000 (swap.go:4) FUNCDATA $1, gclocals.33cdeccccebe80329flfdbee7f5874cb(SB) 0x0000 00000 (swap.go:4) MOVQ $0, "".x+24(SP) 0x0009 00009 (swap.go:4) MOVQ $0, "".y+32(SP) 0x0012 00018 (swap.go:5) MOVQ "".b+16(SP), AX 0x0017 00023 (swap.go:5) MOVQ AX, "".x+24(SP) 0xOO1c 00028 (swap.go:6) MOVQ "".a+8(SP), AX 0x0021 00033 (swap.go:6) MOVQ AX, "".y+32(SP) 0x0026 00038 (swap.go:7) RET "".main STEXT size=68 args=0x0 locals=0x28 0x0000 00000 (swap.go:10) TEXT "".main(SB), $40 - 0 0x0000 00000 (swap.go:10) MOVQ (TLS), CX 0x0009 00009 (swap.go:10) CMPQ SP, 16(CX) 0x000d 00013 (swap.go:10) JLS 61 0x000f 00015 (swap.go:10) SUBQ $40, SP 0x0013 00019 (swap.go:10) MOVQ BP, 32 (SP) 0x0018 00024 (swap.go:10) LEAQ 32(SP), BP 0x001d 00029 (swap.go:10) FUNCDATA $0, gclocals ·33cdeccccebe80329flfdbee7f5874cb(SB) 0x001d 00029 (swap.go:10) FUNCDATA $1, gclocals ·33cdeccccebe80329flfdbee7f5874cb(SB) 0x001d 00029 (swap.go:11) MOVQ $10, (SP) 0x0025 00037 (swap.go:11) MOVQ $20 , 8 (SP) 0x002e 00046 (swap.go:11) PCDATA $0 , $0 0x002e 00046 (swap.go:11) CALL "". swap(SB) 0x0033 00051 (swap.go:12) MOVQ 32(SP), BP 0x0038 00056 (swap.go:12) ADDQ $40, SP 0x003c 00060 (swap.go:12) RET 0x003d 00061 (swap.go:12) NOP 0x003d 00061 (swap.go:10) PCDATA $0, $ - 1