GO語言匯編:plan9(貝爾操作系統(tǒng))
go開發(fā)者與plan 9開發(fā)者同一人累澡,Rob Pike
寄存器:
數(shù)據(jù)寄存器:R0-R7,地址寄存器:A0-A7仁连,浮點寄存器:F0-F7敬飒。
偽棧寄存器:FP, SP, TOS
數(shù)據(jù):
PC用來控制程序執(zhí)行级遭,SB用來引用全局變量。
Go語言匯編
FUNCDATA和PCDATA是編譯器產(chǎn)生的凿渊,用于保存一些給垃圾收集的信息梁只。
NOPTR和RODATA的數(shù)據(jù)不需要被垃圾收集缚柳。比指針還要小的數(shù)據(jù)也被當做NOPTR。不要在go匯編里寫非只讀數(shù)據(jù)敛纲。
plan9函數(shù)調(diào)用協(xié)議中采用的是caller-save的模式喂击,也就是由調(diào)用者負責保存寄存器。
TEXT !$Add(SB),$0
MOVQ x+0(FP), BX
MOVQ y+8(FP), BP
ADDQ BP, BX
MOVQ BX, ret+16(FP)
RET
TEXT "".main(SB), $56-0
56 代表local 大小
0 代表args大小
movl 四字節(jié)mov intel指令集
movq 八字節(jié)
例子中的TEXT指令就定義了一個叫bytes·Equal的符號(注意是中點號·)淤翔,接下來就是對應的指令(可以理解成函數(shù)體)翰绊,而最后RET則是返回指令(退出當前stack)。通常情況下旁壮,參數(shù)大小后跟隨著stack frame的大小监嗜,使用減號(-)分割。$0-49意味著這是一個0-byte的棧抡谐,并且有49-byte長的參數(shù)裁奇。NOSPLIT說明,不允許調(diào)度器調(diào)整stack frame的大小,這就意味著必須人工指定stack frame大小。
字符串 函數(shù)都放在SB stack basic register
問題:
go是如何實現(xiàn)多值返回的麦撵?
go結構體是如何排布的刽肠?
go 數(shù)組入?yún)⒌拈L度是多少?
如何查看go開辟空間位置 堆棧免胃?
數(shù)組匯編是怎么玩的音五?
用例1:
代碼:
func fuck(a int){
time.Sleep(time.Duration((a)))
}
func add(a,b int) int{
//a = (b*2)
fuck(a)
return (a+b)
}
func main() {
haha:=add(3,2)
add(haha,4)
}
asm:
"".fuck t=1 size=65 args=0x4 locals=0x10
0x0000 00000 (myLove.go:10) TEXT "".fuck(SB), $16-4
0x0000 00000 (myLove.go:10) MOVL TLS, CX
0x0007 00007 (myLove.go:10) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:10) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:10) JLS 58
0x0012 00018 (myLove.go:10) SUBL $16, SP
0x0015 00021 (myLove.go:10) FUNCDATA $0, gclocals·5184031d3a32a42d85027f073f873668(SB)
0x0015 00021 (myLove.go:10) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:11) MOVL "".a+20(FP), AX
0x0019 00025 (myLove.go:11) CDQ
0x001a 00026 (myLove.go:11) MOVL AX, "".autotmp_0+8(SP)
0x001e 00030 (myLove.go:11) MOVL DX, "".autotmp_0+12(SP)
0x0022 00034 (myLove.go:11) MOVL "".autotmp_0+8(SP), AX
0x0026 00038 (myLove.go:11) MOVL AX, (SP)
0x0029 00041 (myLove.go:11) MOVL "".autotmp_0+12(SP), AX
0x002d 00045 (myLove.go:11) MOVL AX, 4(SP)
0x0031 00049 (myLove.go:11) PCDATA $0, $0
0x0031 00049 (myLove.go:11) CALL time.Sleep(SB)
0x0036 00054 (myLove.go:12) ADDL $16, SP
0x0039 00057 (myLove.go:12) RET
0x003a 00058 (myLove.go:12) NOP
0x003a 00058 (myLove.go:10) CALL runtime.morestack_noctxt(SB)
0x003f 00063 (myLove.go:10) JMP 0
0x0000 64 8b 0d 14 00 00 00 8b 89 00 00 00 00 3b 61 08 d............;a.
0x0010 76 28 83 ec 10 8b 44 24 14 99 89 44 24 08 89 54 v(....D$...D$..T
0x0020 24 0c 8b 44 24 08 89 04 24 8b 44 24 0c 89 44 24 $..D$...$.D$..D$
0x0030 04 e8 00 00 00 00 83 c4 10 c3 e8 00 00 00 00 eb ................
0x0040 bf .
rel 9+4 t=15 TLS+0
rel 50+4 t=7 time.Sleep+0
rel 59+4 t=7 runtime.morestack_noctxt+0
"".add t=1 size=72 args=0xc locals=0x8
0x0000 00000 (myLove.go:13) TEXT "".add(SB), $8-12
0x0000 00000 (myLove.go:13) MOVL TLS, CX
0x0007 00007 (myLove.go:13) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:13) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:13) JLS 65
0x0012 00018 (myLove.go:13) SUBL $8, SP
0x0015 00021 (myLove.go:13) FUNCDATA $0, gclocals·790e5cc5051fc0affc980ade09e929ec(SB)
0x0015 00021 (myLove.go:13) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:13) MOVL $0, "".~r2+20(FP)
0x001d 00029 (myLove.go:15) MOVL "".a+12(FP), BX
0x0021 00033 (myLove.go:15) MOVL BX, (SP)
0x0024 00036 (myLove.go:15) PCDATA $0, $0
0x0024 00036 (myLove.go:15) CALL "".fuck(SB)
0x0029 00041 (myLove.go:16) MOVL "".a+12(FP), BX
0x002d 00045 (myLove.go:16) MOVL BX, "".autotmp_1+4(SP)
0x0031 00049 (myLove.go:16) MOVL "".autotmp_1+4(SP), BX
0x0035 00053 (myLove.go:16) ADDL "".b+16(FP), BX
0x0039 00057 (myLove.go:16) MOVL BX, "".~r2+20(FP)
0x003d 00061 (myLove.go:16) ADDL $8, SP
0x0040 00064 (myLove.go:16) RET
0x0041 00065 (myLove.go:16) NOP
0x0041 00065 (myLove.go:13) CALL runtime.morestack_noctxt(SB)
0x0046 00070 (myLove.go:13) JMP 0
0x0000 64 8b 0d 14 00 00 00 8b 89 00 00 00 00 3b 61 08 d............;a.
0x0010 76 2f 83 ec 08 c7 44 24 14 00 00 00 00 8b 5c 24 v/....D$......\$
0x0020 0c 89 1c 24 e8 00 00 00 00 8b 5c 24 0c 89 5c 24 ...$......\$..\$
0x0030 04 8b 5c 24 04 03 5c 24 10 89 5c 24 14 83 c4 08 ..\$..\$..\$....
0x0040 c3 e8 00 00 00 00 eb b8 ........
rel 9+4 t=15 TLS+0
rel 37+4 t=7 "".fuck+0
rel 66+4 t=7 runtime.morestack_noctxt+0
"".main t=1 size=80 args=0x0 locals=0x10
0x0000 00000 (myLove.go:18) TEXT "".main(SB), $16-0
0x0000 00000 (myLove.go:18) MOVL TLS, CX
0x0007 00007 (myLove.go:18) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:18) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:18) JLS 73
0x0012 00018 (myLove.go:18) SUBL $16, SP
0x0015 00021 (myLove.go:18) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:18) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:19) MOVL $3, (SP)
0x001c 00028 (myLove.go:19) MOVL $2, 4(SP)
0x0024 00036 (myLove.go:19) PCDATA $0, $0
0x0024 00036 (myLove.go:19) CALL "".add(SB)
0x0029 00041 (myLove.go:19) MOVL 8(SP), BX
0x002d 00045 (myLove.go:19) MOVL BX, "".haha+12(SP)
0x0031 00049 (myLove.go:20) MOVL "".haha+12(SP), BX
0x0035 00053 (myLove.go:20) MOVL BX, (SP)
0x0038 00056 (myLove.go:20) MOVL $4, 4(SP)
0x0040 00064 (myLove.go:20) PCDATA $0, $0
0x0040 00064 (myLove.go:20) CALL "".add(SB)
0x0045 00069 (myLove.go:21) ADDL $16, SP
0x0048 00072 (myLove.go:21) RET
0x0049 00073 (myLove.go:21) NOP
0x0049 00073 (myLove.go:18) CALL runtime.morestack_noctxt(SB)
0x004e 00078 (myLove.go:18) JMP 0
0x0000 64 8b 0d 14 00 00 00 8b 89 00 00 00 00 3b 61 08 d............;a.
0x0010 76 37 83 ec 10 c7 04 24 03 00 00 00 c7 44 24 04 v7.....$.....D$.
0x0020 02 00 00 00 e8 00 00 00 00 8b 5c 24 08 89 5c 24 ..........\$..\$
0x0030 0c 8b 5c 24 0c 89 1c 24 c7 44 24 04 04 00 00 00 ..\$...$.D$.....
0x0040 e8 00 00 00 00 83 c4 10 c3 e8 00 00 00 00 eb b0 ................
rel 9+4 t=15 TLS+0
rel 37+4 t=7 "".add+0
rel 65+4 t=7 "".add+0
rel 74+4 t=7 runtime.morestack_noctxt+0
用例二:
多值返回
代碼:
func add(a,b int) (int,int){
//a = (b*2)
fuck(a)
return (a+b),(a-b)
}
func main() {
haha,lala:=add(3,2)
add(haha,lala)
}
asm:
"".main t=1 size=88 args=0x0 locals=0x18
0x0000 00000 (myLove.go:18) TEXT "".main(SB), $24-0
0x0000 00000 (myLove.go:18) MOVL TLS, CX
0x0007 00007 (myLove.go:18) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:18) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:18) JLS 81
0x0012 00018 (myLove.go:18) SUBL $24, SP
0x0015 00021 (myLove.go:18) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:18) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:19) MOVL $3, (SP)
0x001c 00028 (myLove.go:19) MOVL $2, 4(SP)
0x0024 00036 (myLove.go:19) PCDATA $0, $0
0x0024 00036 (myLove.go:19) CALL "".add(SB)
0x0029 00041 (myLove.go:19) MOVL 8(SP), BX
0x002d 00045 (myLove.go:19) MOVL BX, "".haha+20(SP)
0x0031 00049 (myLove.go:19) MOVL 12(SP), BX
0x0035 00053 (myLove.go:19) MOVL BX, "".lala+16(SP)
0x0039 00057 (myLove.go:20) MOVL "".haha+20(SP), BX
0x003d 00061 (myLove.go:20) MOVL BX, (SP)
0x0040 00064 (myLove.go:20) MOVL "".lala+16(SP), BX
0x0044 00068 (myLove.go:20) MOVL BX, 4(SP)
0x0048 00072 (myLove.go:20) PCDATA $0, $0
0x0048 00072 (myLove.go:20) CALL "".add(SB)
0x004d 00077 (myLove.go:21) ADDL $24, SP
"".add t=1 size=100 args=0x10 locals=0xc
0x0000 00000 (myLove.go:13) TEXT "".add(SB), $12-16
0x0000 00000 (myLove.go:13) MOVL TLS, CX
0x0007 00007 (myLove.go:13) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:13) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:13) JLS 93
0x0012 00018 (myLove.go:13) SUBL $12, SP
對比用例一與用例二的locals,發(fā)現(xiàn)add方法的locals擴大羔沙,其把入?yún)⑴c出參都當做返回值躺涝,處理。
用例三:研究一下結構體特點
代碼:
type test1 struct {
a int
b int
}
func f1(t1 test1){
t1.a = 5
fmt.Println(t1.a)
}
func main() {
aa := test1{1,2}
f1(aa)
}
ASM:
"".main t=1 size=94 args=0x0 locals=0x18
0x0000 00000 (myLove.go:14) TEXT "".main(SB), $24-0
0x0000 00000 (myLove.go:14) MOVL TLS, CX
0x0007 00007 (myLove.go:14) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:14) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:14) JLS 87
0x0012 00018 (myLove.go:14) SUBL $24, SP
0x0015 00021 (myLove.go:14) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:14) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0015 00021 (myLove.go:15) MOVL $0, BX
0x0017 00023 (myLove.go:15) MOVL BX, "".aa+16(SP)
0x001b 00027 (myLove.go:15) MOVL BX, "".aa+20(SP)
0x001f 00031 (myLove.go:15) MOVL $1, "".autotmp_6+12(SP)
0x0027 00039 (myLove.go:15) MOVL "".autotmp_6+12(SP), BX
0x002b 00043 (myLove.go:15) MOVL BX, "".aa+16(SP)
0x002f 00047 (myLove.go:15) MOVL $2, "".autotmp_7+8(SP)
0x0037 00055 (myLove.go:15) MOVL "".autotmp_7+8(SP), BX
0x003b 00059 (myLove.go:15) MOVL BX, "".aa+20(SP)
0x003f 00063 (myLove.go:16) MOVL "".aa+16(SP), BX
0x0043 00067 (myLove.go:16) MOVL BX, (SP)
0x0046 00070 (myLove.go:16) MOVL "".aa+20(SP), BX
0x004a 00074 (myLove.go:16) MOVL BX, 4(SP)
0x004e 00078 (myLove.go:16) PCDATA $0, $0
0x004e 00078 (myLove.go:16) CALL "".f1(SB)
0x0053 00083 (myLove.go:18) ADDL $24, SP
"".f1 t=1 size=200 args=0x8 locals=0x3c
0x0000 00000 (myLove.go:10) TEXT "".f1(SB), $60-8
0x0000 00000 (myLove.go:10) MOVL TLS, CX
0x0007 00007 (myLove.go:10) MOVL (CX)(TLS*2), CX
0x000d 00013 (myLove.go:10) CMPL SP, 8(CX)
0x0010 00016 (myLove.go:10) JLS 190
0x0016 00022 (myLove.go:10) SUBL $60, SP
0x0019 00025 (myLove.go:10) FUNCDATA $0, gclocals·8edb5632446ada37b0a930d010725cc5(SB)
0x0019 00025 (myLove.go:10) FUNCDATA $1, gclocals·ff5e069297bc4e135ac51ef96d4582a2(SB)
0x0019 00025 (myLove.go:11) MOVL $5, "".autotmp_5+24(SP)
0x0021 00033 (myLove.go:11) MOVL "".autotmp_5+24(SP), BX
0x0025 00037 (myLove.go:11) MOVL BX, "".t1+64(FP)
0x0029 00041 (myLove.go:12) MOVL $0, BX
0x002b 00043 (myLove.go:12) MOVL BX, "".autotmp_3+40(SP)
0x002f 00047 (myLove.go:12) MOVL BX, "".autotmp_3+44(SP)
0x0033 00051 (myLove.go:12) LEAL "".autotmp_3+40(SP), BX
0x0037 00055 (myLove.go:12) MOVL BX, "".autotmp_1+28(SP)
0x003b 00059 (myLove.go:12) MOVL $type.int(SB), (SP)
0x0042 00066 (myLove.go:12) LEAL "".t1+64(FP), BX
0x0046 00070 (myLove.go:12) MOVL BX, 4(SP)
main函數(shù)堆棧扼雏,將數(shù)值拷貝到偏移為0 和 4的位置坚嗜,而f1函數(shù)直接從FP+64也就是SP+0的位置修改數(shù)據(jù),所以數(shù)據(jù)修改無效
SP
0---
4---
16---
20---
FP