package main

func main() {
  var x int32 = 1
  nop(x)
}

//go:noinline
func nop(x int32) {}

*Go version: go1.16.15 windows/amd64*

I wrote above code and compiled it into assembly with `go1.16.15 tool 
compile -S -N -l main.go` for truly understanding Go functions call.

The following is the assembly code of nop function:

"".nop STEXT nosplit size=1 args=0x8 locals=0x0 funcid=0x0
        0x0000 00000 (main.go:9)        TEXT    "".nop(SB), 
NOSPLIT|ABIInternal, $0-8
        0x0000 00000 (main.go:9)        FUNCDATA        $0, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (main.go:9)        FUNCDATA        $1, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (main.go:9)        RET

Obviously, the nop function returns directly without doing anything. It 
only has a `int32` type parameter, but we can see the `argsize` is 8 bytes 
in the assembly:

TEXT    "".nop(SB), NOSPLIT|ABIInternal, $0-*8*

*Question1: Why the `argsize` is 8 bytes not 4 bytes?*

The following is the assembly code of main function:

"".main STEXT size=73 args=0x0 locals=0x18 funcid=0x0
        0x0000 00000 (main.go:3)        TEXT    "".main(SB), ABIInternal, 
$24-0
        0x0000 00000 (main.go:3)        MOVQ    TLS, CX
        0x0009 00009 (main.go:3)        PCDATA  $0, $-2
        0x0009 00009 (main.go:3)        MOVQ    (CX)(TLS*2), CX
        0x0010 00016 (main.go:3)        PCDATA  $0, $-1
        0x0010 00016 (main.go:3)        CMPQ    SP, 16(CX)
        0x0014 00020 (main.go:3)        PCDATA  $0, $-2
        0x0014 00020 (main.go:3)        JLS     66
        0x0016 00022 (main.go:3)        PCDATA  $0, $-1
        0x0016 00022 (main.go:3)        SUBQ    $24, SP
        0x001a 00026 (main.go:3)        MOVQ    BP, 16(SP)
        0x001f 00031 (main.go:3)        LEAQ    16(SP), BP
        0x0024 00036 (main.go:3)        FUNCDATA        $0, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0024 00036 (main.go:3)        FUNCDATA        $1, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0024 00036 (main.go:4)        MOVL    $1, "".x+12(SP)
        0x002c 00044 (main.go:5)        MOVL    $1, (SP)
        0x0033 00051 (main.go:5)        PCDATA  $1, $0
        0x0033 00051 (main.go:5)        CALL    "".nop(SB)
        0x0038 00056 (main.go:6)        MOVQ    16(SP), BP
        0x003d 00061 (main.go:6)        ADDQ    $24, SP
        0x0041 00065 (main.go:6)        RET

I drawn a picture of stack according to the assembly code:
https://i.stack.imgur.com/AHN1b.png

*Question2: I find there are confusing 8 bytes in the stack, why do these 8 
bytes exist?*

* Question3:  Why *MOVL    $1, "".x*+*12(SP)*but not  *MOVL    $1, "".x*-*
12(SP)? 

I think memory alignment causes the above phenomenon, but I'm not sure.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/4f87acc6-def5-414b-b835-7f1e6ee192ddn%40googlegroups.com.

Reply via email to