go语言汇编(学习笔记)

GO语言汇编:plan9(贝尔操作系统)

go开发者与plan 9开发者同一人,Rob Pike

寄存器:

数据寄存器:R0-R7,地址寄存器:A0-A7,浮点寄存器:F0-F7。

伪栈寄存器:FP, SP, TOS

数据:

PC用来控制程序执行,SB用来引用全局变量。

Go语言汇编
FUNCDATA和PCDATA是编译器产生的,用于保存一些给垃圾收集的信息。

NOPTR和RODATA的数据不需要被垃圾收集。比指针还要小的数据也被当做NOPTR。不要在go汇编里写非只读数据。

plan9函数调用协议中采用的是caller-save的模式,也就是由调用者负责保存寄存器。

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 四字节mov intel指令集
movq 八字节

例子中的TEXT指令就定义了一个叫bytes·Equal的符号(注意是中点号·),接下来就是对应的指令(可以理解成函数体),而最后RET则是返回指令(退出当前stack)。通常情况下,参数大小后跟随着stack frame的大小,使用减号(-)分割。$0-49意味着这是一个0-byte的栈,并且有49-byte长的参数。NOSPLIT说明,不允许调度器调整stack frame的大小,这就意味着必须人工指定stack frame大小。

字符串 函数都放在SB stack basic register

go语言汇编(学习笔记)_第1张图片
堆栈函数调用.png

问题:
go是如何实现多值返回的?
go结构体是如何排布的?
go 数组入参的长度是多少?
如何查看go开辟空间位置 堆栈?
数组汇编是怎么玩的?

用例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,发现add方法的locals扩大,其把入参与出参都当做返回值,处理。

用例三:研究一下结构体特点
代码:

    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函数堆栈,将数值拷贝到偏移为0 和 4的位置,而f1函数直接从FP+64也就是SP+0的位置修改数据,所以数据修改无效
SP

     0---
     4---
    16---
    20---

FP

你可能感兴趣的:(go语言汇编(学习笔记))