美文网首页
go语言汇编(学习笔记)

go语言汇编(学习笔记)

作者: 明神特烦恼 | 来源:发表于2017-03-20 09:14 被阅读0次

    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

    堆栈函数调用.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语言汇编(学习笔记)

          本文链接:https://www.haomeiwen.com/subject/reycnttx.html