Programming/golang2023. 8. 23. 17:19

go 프로그램도 java와 같은 독립된 환경이 아닌 일반적인 c와 같은 실행환경에서 도는 애다 보니

결국에는 기계어로 전환되고 objdump를 통해 디스어셈블을 할 수 있긴한데

go tool objdump를 통해 나오는 결과와 objdump를 통해 나오는 결과가 상이하다

go build -gcflags -S program.go
If you already have a compiled program and want to see the assembly code you can disassemble it with 
go tool objdump binaryFile.

[링크 : https://www.grant.pizza/blog/dissecting-go-binaries/]

 

명렁어 자체는 특이한 건 없다.

go tool objdump [-s symregexp] binary

[링크 : https://pkg.go.dev/cmd/objdump]

 

요런 go 소스를 작성하고

$ vi neon.go 
  1 package main
  2 
  3 func main() {
  4         add()
  5 }
  6 
  7 func add() {
  8         a := make([]int32, 256)
  9         b := make([]int32, 256)
 10         c := make([]int32, 256)
 11 
 12         var i int32
 13         for i = 0; i < 256; i++ {
 14                 b[i] = i;
 15                 c[i] = 256 - i;
 16         }
 17 
 18         for i = 0; i < 256; i++ {
 19                 a[i] = b[i] + c[i]
 20         }
 21 }

 

go build를 통해 빌드하면 디스어셈블 해주는데

출력 포맷이 objdump와 다른데다가.. 소스 라인만 보이고 매칭이 안되서 이래저래 불편..

그 와중에 먼가.. x86 ASM 같은 느낌은 왜일까..

일종의 중간(?) 언어로 어셈을 쓰고 이걸 다시 아키텍쳐별로 변환하는건가?

$ GOARCH=arm64 go build -gcflags -S .
# tt
main.main STEXT size=240 args=0x0 locals=0x818 funcid=0x0 align=0x0
0x0000 00000 (/home/user/work/src/goneon/neon.go:3) TEXT main.main(SB), ABIInternal, $2080-0
0x0000 00000 (/home/user/work/src/goneon/neon.go:3) MOVD 16(g), R16
0x0004 00004 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-2
0x0004 00004 (/home/user/work/src/goneon/neon.go:3) SUB $1952, RSP, R17
0x0008 00008 (/home/user/work/src/goneon/neon.go:3) CMP R16, R17
0x000c 00012 (/home/user/work/src/goneon/neon.go:3) BLS 220
0x0010 00016 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-1
0x0010 00016 (/home/user/work/src/goneon/neon.go:3) SUB $2080, RSP, R20
0x0014 00020 (/home/user/work/src/goneon/neon.go:3) STP (R29, R30), -8(R20)
0x0018 00024 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-2
0x0018 00024 (/home/user/work/src/goneon/neon.go:3) MOVD R20, RSP
0x001c 00028 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-1
0x001c 00028 (/home/user/work/src/goneon/neon.go:3) SUB $8, RSP, R29
0x0020 00032 (/home/user/work/src/goneon/neon.go:3) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0020 00032 (/home/user/work/src/goneon/neon.go:3) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0020 00032 (<unknown line number>) NOP
0x0020 00032 (/home/user/work/src/goneon/neon.go:4) MOVD $main..autotmp_5-1024(SP), R20
0x0024 00036 (/home/user/work/src/goneon/neon.go:9) PCDATA $0, $-2
0x0024 00036 (/home/user/work/src/goneon/neon.go:9) ADR 52, runtime.duffzero(R27)(R27)(REG)
0x0028 00040 (/home/user/work/src/goneon/neon.go:9) STP (R29, R27), -24(RSP)
0x002c 00044 (/home/user/work/src/goneon/neon.go:9) SUB $24, RSP, R29
0x0030 00048 (/home/user/work/src/goneon/neon.go:9) DUFFZERO runtime.duffzero(SB)
0x0034 00052 (/home/user/work/src/goneon/neon.go:9) SUB $8, RSP, R29
0x0038 00056 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-1
0x0038 00056 (/home/user/work/src/goneon/neon.go:10) MOVD $main..autotmp_6-2048(SP), R20
0x003c 00060 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-2
0x003c 00060 (/home/user/work/src/goneon/neon.go:10) ADR 76, runtime.duffzero(R27)(R27)(REG)
0x0040 00064 (/home/user/work/src/goneon/neon.go:10) STP (R29, R27), -24(RSP)
0x0044 00068 (/home/user/work/src/goneon/neon.go:10) SUB $24, RSP, R29
0x0048 00072 (/home/user/work/src/goneon/neon.go:10) DUFFZERO runtime.duffzero(SB)
0x004c 00076 (/home/user/work/src/goneon/neon.go:10) SUB $8, RSP, R29
0x0050 00080 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-1
0x0050 00080 (/home/user/work/src/goneon/neon.go:10) MOVD ZR, R0
0x0054 00084 (/home/user/work/src/goneon/neon.go:13) JMP 120
0x0058 00088 (/home/user/work/src/goneon/neon.go:14) SBFIZ $2, R0, $32, R2
0x005c 00092 (/home/user/work/src/goneon/neon.go:14) MOVD $main..autotmp_5-1024(SP), R3
0x0060 00096 (/home/user/work/src/goneon/neon.go:14) MOVW R0, (R3)(R2)
0x0064 00100 (/home/user/work/src/goneon/neon.go:15) MOVD $256, R4
0x0068 00104 (/home/user/work/src/goneon/neon.go:15) SUB R0, R4, R5
0x006c 00108 (/home/user/work/src/goneon/neon.go:15) MOVD $main..autotmp_6-2048(SP), R6
0x0070 00112 (/home/user/work/src/goneon/neon.go:15) MOVW R5, (R6)(R2)
0x0074 00116 (/home/user/work/src/goneon/neon.go:13) ADD $1, R0, R0
0x0078 00120 (/home/user/work/src/goneon/neon.go:13) CMPW $256, R0
0x007c 00124 (/home/user/work/src/goneon/neon.go:13) BGE 144
0x0080 00128 (/home/user/work/src/goneon/neon.go:14) MOVW R0, R2
0x0084 00132 (/home/user/work/src/goneon/neon.go:14) CMP $256, R2
0x0088 00136 (/home/user/work/src/goneon/neon.go:14) BLO 88
0x008c 00140 (/home/user/work/src/goneon/neon.go:14) JMP 204
0x0090 00144 (/home/user/work/src/goneon/neon.go:14) MOVD ZR, R0
0x0094 00148 (/home/user/work/src/goneon/neon.go:13) JMP 156
0x0098 00152 (/home/user/work/src/goneon/neon.go:18) ADD $1, R0, R0
0x009c 00156 (/home/user/work/src/goneon/neon.go:18) CMPW $256, R0
0x00a0 00160 (/home/user/work/src/goneon/neon.go:18) BGE 180
0x00a4 00164 (/home/user/work/src/goneon/neon.go:19) MOVW R0, R2
0x00a8 00168 (/home/user/work/src/goneon/neon.go:19) CMP $256, R2
0x00ac 00172 (/home/user/work/src/goneon/neon.go:19) BLO 152
0x00b0 00176 (/home/user/work/src/goneon/neon.go:19) JMP 192
0x00b4 00180 (/home/user/work/src/goneon/neon.go:5) LDP -8(RSP), (R29, R30)
0x00b8 00184 (/home/user/work/src/goneon/neon.go:5) ADD $2080, RSP
0x00bc 00188 (/home/user/work/src/goneon/neon.go:5) RET (R30)
0x00c0 00192 (/home/user/work/src/goneon/neon.go:19) MOVD R2, R0
0x00c4 00196 (/home/user/work/src/goneon/neon.go:19) MOVD $256, R1
0x00c8 00200 (/home/user/work/src/goneon/neon.go:19) PCDATA $1, $0
0x00c8 00200 (/home/user/work/src/goneon/neon.go:19) CALL runtime.panicIndex(SB)
0x00cc 00204 (/home/user/work/src/goneon/neon.go:14) MOVD R2, R0
0x00d0 00208 (/home/user/work/src/goneon/neon.go:14) MOVD $256, R1
0x00d4 00212 (/home/user/work/src/goneon/neon.go:14) CALL runtime.panicIndex(SB)
0x00d8 00216 (/home/user/work/src/goneon/neon.go:14) HINT $0
0x00dc 00220 (/home/user/work/src/goneon/neon.go:14) NOP
0x00dc 00220 (/home/user/work/src/goneon/neon.go:3) PCDATA $1, $-1
0x00dc 00220 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-2
0x00dc 00220 (/home/user/work/src/goneon/neon.go:3) MOVD R30, R3
0x00e0 00224 (/home/user/work/src/goneon/neon.go:3) CALL runtime.morestack_noctxt(SB)
0x00e4 00228 (/home/user/work/src/goneon/neon.go:3) PCDATA $0, $-1
0x00e4 00228 (/home/user/work/src/goneon/neon.go:3) JMP 0
0x0000 90 0b 40 f9 f1 83 1e d1 3f 02 10 eb 89 06 00 54  ..@.....?......T
0x0010 f4 83 20 d1 9d fa 3f a9 9f 02 00 91 fd 23 00 d1  .. ...?......#..
0x0020 f4 63 10 91 9b 00 00 10 fd ef 3e a9 fd 63 00 d1  .c........>..c..
0x0030 00 00 00 94 fd 23 00 d1 f4 63 00 91 9b 00 00 10  .....#...c......
0x0040 fd ef 3e a9 fd 63 00 d1 00 00 00 94 fd 23 00 d1  ..>..c.......#..
0x0050 e0 03 1f aa 09 00 00 14 02 7c 7e 93 e3 63 10 91  .........|~..c..
0x0060 60 68 22 b8 e4 03 78 b2 85 00 00 cb e6 63 00 91  `h"...x......c..
0x0070 c5 68 22 b8 00 04 00 91 1f 00 04 71 aa 00 00 54  .h"........q...T
0x0080 02 7c 40 93 5f 00 04 f1 83 fe ff 54 10 00 00 14  .|@._......T....
0x0090 e0 03 1f aa 02 00 00 14 00 04 00 91 1f 00 04 71  ...............q
0x00a0 aa 00 00 54 02 7c 40 93 5f 00 04 f1 63 ff ff 54  ...T.|@._...c..T
0x00b0 04 00 00 14 fd fb 7f a9 ff 83 20 91 c0 03 5f d6  .......... ..._.
0x00c0 e0 03 02 aa e1 03 78 b2 00 00 00 94 e0 03 02 aa  ......x.........
0x00d0 e1 03 78 b2 00 00 00 94 1f 20 03 d5 e3 03 1e aa  ..x...... ......
0x00e0 00 00 00 94 c7 ff ff 17 00 00 00 00 00 00 00 00  ................
rel 48+4 t=9 runtime.duffzero+0
rel 72+4 t=9 runtime.duffzero+0
rel 200+4 t=9 runtime.panicIndex+0
rel 212+4 t=9 runtime.panicIndex+0
rel 224+4 t=9 runtime.morestack_noctxt+0
main.add STEXT size=240 args=0x0 locals=0x818 funcid=0x0 align=0x0
0x0000 00000 (/home/user/work/src/goneon/neon.go:7) TEXT main.add(SB), ABIInternal, $2080-0
0x0000 00000 (/home/user/work/src/goneon/neon.go:7) MOVD 16(g), R16
0x0004 00004 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-2
0x0004 00004 (/home/user/work/src/goneon/neon.go:7) SUB $1952, RSP, R17
var symregexp = flag.String("s", "", "only dump symbols matching this regexp")
var gnuAsm = flag.Bool("gnu", false, "print GNU assembly next to Go assembly (where supported)")
var symRE *regexp.Regexp
0x0008 00008 (/home/user/work/src/goneon/neon.go:7) CMP R16, R17
0x000c 00012 (/home/user/work/src/goneon/neon.go:7) BLS 220
0x0010 00016 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-1
0x0010 00016 (/home/user/work/src/goneon/neon.go:7) SUB $2080, RSP, R20
0x0014 00020 (/home/user/work/src/goneon/neon.go:7) STP (R29, R30), -8(R20)
0x0018 00024 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-2
0x0018 00024 (/home/user/work/src/goneon/neon.go:7) MOVD R20, RSP
0x001c 00028 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-1
0x001c 00028 (/home/user/work/src/goneon/neon.go:7) SUB $8, RSP, R29
0x0020 00032 (/home/user/work/src/goneon/neon.go:7) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0020 00032 (/home/user/work/src/goneon/neon.go:7) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0020 00032 (/home/user/work/src/goneon/neon.go:9) MOVD $main..autotmp_5-1024(SP), R20
0x0024 00036 (/home/user/work/src/goneon/neon.go:9) PCDATA $0, $-2
0x0024 00036 (/home/user/work/src/goneon/neon.go:9) ADR 52, runtime.duffzero(R27)(R27)(REG)
0x0028 00040 (/home/user/work/src/goneon/neon.go:9) STP (R29, R27), -24(RSP)
0x002c 00044 (/home/user/work/src/goneon/neon.go:9) SUB $24, RSP, R29
0x0030 00048 (/home/user/work/src/goneon/neon.go:9) DUFFZERO runtime.duffzero(SB)
0x0034 00052 (/home/user/work/src/goneon/neon.go:9) SUB $8, RSP, R29
0x0038 00056 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-1
0x0038 00056 (/home/user/work/src/goneon/neon.go:10) MOVD $main..autotmp_6-2048(SP), R20
0x003c 00060 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-2
0x003c 00060 (/home/user/work/src/goneon/neon.go:10) ADR 76, runtime.duffzero(R27)(R27)(REG)
0x0040 00064 (/home/user/work/src/goneon/neon.go:10) STP (R29, R27), -24(RSP)
0x0044 00068 (/home/user/work/src/goneon/neon.go:10) SUB $24, RSP, R29
0x0048 00072 (/home/user/work/src/goneon/neon.go:10) DUFFZERO runtime.duffzero(SB)
0x004c 00076 (/home/user/work/src/goneon/neon.go:10) SUB $8, RSP, R29
0x0050 00080 (/home/user/work/src/goneon/neon.go:10) PCDATA $0, $-1
0x0050 00080 (/home/user/work/src/goneon/neon.go:10) MOVD ZR, R0
0x0054 00084 (/home/user/work/src/goneon/neon.go:13) JMP 120
0x0058 00088 (/home/user/work/src/goneon/neon.go:14) SBFIZ $2, R0, $32, R2
0x005c 00092 (/home/user/work/src/goneon/neon.go:14) MOVD $main..autotmp_5-1024(SP), R3
0x0060 00096 (/home/user/work/src/goneon/neon.go:14) MOVW R0, (R3)(R2)
0x0064 00100 (/home/user/work/src/goneon/neon.go:15) MOVD $256, R4
0x0068 00104 (/home/user/work/src/goneon/neon.go:15) SUB R0, R4, R5
0x006c 00108 (/home/user/work/src/goneon/neon.go:15) MOVD $main..autotmp_6-2048(SP), R6
0x0070 00112 (/home/user/work/src/goneon/neon.go:15) MOVW R5, (R6)(R2)
0x0074 00116 (/home/user/work/src/goneon/neon.go:13) ADD $1, R0, R0
0x0078 00120 (/home/user/work/src/goneon/neon.go:13) CMPW $256, R0
0x007c 00124 (/home/user/work/src/goneon/neon.go:13) BGE 144
0x0080 00128 (/home/user/work/src/goneon/neon.go:14) MOVW R0, R2
0x0084 00132 (/home/user/work/src/goneon/neon.go:14) CMP $256, R2
0x0088 00136 (/home/user/work/src/goneon/neon.go:14) BLO 88
0x008c 00140 (/home/user/work/src/goneon/neon.go:14) JMP 204
0x0090 00144 (/home/user/work/src/goneon/neon.go:14) MOVD ZR, R0
0x0094 00148 (/home/user/work/src/goneon/neon.go:13) JMP 156
0x0098 00152 (/home/user/work/src/goneon/neon.go:18) ADD $1, R0, R0
0x009c 00156 (/home/user/work/src/goneon/neon.go:18) CMPW $256, R0
0x00a0 00160 (/home/user/work/src/goneon/neon.go:18) BGE 180
0x00a4 00164 (/home/user/work/src/goneon/neon.go:19) MOVW R0, R2
0x00a8 00168 (/home/user/work/src/goneon/neon.go:19) CMP $256, R2
0x00ac 00172 (/home/user/work/src/goneon/neon.go:19) BLO 152
0x00b0 00176 (/home/user/work/src/goneon/neon.go:19) JMP 192
0x00b4 00180 (/home/user/work/src/goneon/neon.go:21) LDP -8(RSP), (R29, R30)
0x00b8 00184 (/home/user/work/src/goneon/neon.go:21) ADD $2080, RSP
0x00bc 00188 (/home/user/work/src/goneon/neon.go:21) RET (R30)
0x00c0 00192 (/home/user/work/src/goneon/neon.go:19) MOVD R2, R0
0x00c4 00196 (/home/user/work/src/goneon/neon.go:19) MOVD $256, R1
0x00c8 00200 (/home/user/work/src/goneon/neon.go:19) PCDATA $1, $0
0x00c8 00200 (/home/user/work/src/goneon/neon.go:19) CALL runtime.panicIndex(SB)
0x00cc 00204 (/home/user/work/src/goneon/neon.go:14) MOVD R2, R0
0x00d0 00208 (/home/user/work/src/goneon/neon.go:14) MOVD $256, R1
0x00d4 00212 (/home/user/work/src/goneon/neon.go:14) CALL runtime.panicIndex(SB)
0x00d8 00216 (/home/user/work/src/goneon/neon.go:14) HINT $0
0x00dc 00220 (/home/user/work/src/goneon/neon.go:14) NOP
0x00dc 00220 (/home/user/work/src/goneon/neon.go:7) PCDATA $1, $-1
0x00dc 00220 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-2
0x00dc 00220 (/home/user/work/src/goneon/neon.go:7) MOVD R30, R3
0x00e0 00224 (/home/user/work/src/goneon/neon.go:7) CALL runtime.morestack_noctxt(SB)
0x00e4 00228 (/home/user/work/src/goneon/neon.go:7) PCDATA $0, $-1
0x00e4 00228 (/home/user/work/src/goneon/neon.go:7) JMP 0
0x0000 90 0b 40 f9 f1 83 1e d1 3f 02 10 eb 89 06 00 54  ..@.....?......T
0x0010 f4 83 20 d1 9d fa 3f a9 9f 02 00 91 fd 23 00 d1  .. ...?......#..
0x0020 f4 63 10 91 9b 00 00 10 fd ef 3e a9 fd 63 00 d1  .c........>..c..
0x0030 00 00 00 94 fd 23 00 d1 f4 63 00 91 9b 00 00 10  .....#...c......
0x0040 fd ef 3e a9 fd 63 00 d1 00 00 00 94 fd 23 00 d1  ..>..c.......#..
0x0050 e0 03 1f aa 09 00 00 14 02 7c 7e 93 e3 63 10 91  .........|~..c..
0x0060 60 68 22 b8 e4 03 78 b2 85 00 00 cb e6 63 00 91  `h"...x......c..
0x0070 c5 68 22 b8 00 04 00 91 1f 00 04 71 aa 00 00 54  .h"........q...T
0x0080 02 7c 40 93 5f 00 04 f1 83 fe ff 54 10 00 00 14  .|@._......T....
0x0090 e0 03 1f aa 02 00 00 14 00 04 00 91 1f 00 04 71  ...............q
0x00a0 aa 00 00 54 02 7c 40 93 5f 00 04 f1 63 ff ff 54  ...T.|@._...c..T
0x00b0 04 00 00 14 fd fb 7f a9 ff 83 20 91 c0 03 5f d6  .......... ..._.
0x00c0 e0 03 02 aa e1 03 78 b2 00 00 00 94 e0 03 02 aa  ......x.........
0x00d0 e1 03 78 b2 00 00 00 94 1f 20 03 d5 e3 03 1e aa  ..x...... ......
0x00e0 00 00 00 94 c7 ff ff 17 00 00 00 00 00 00 00 00  ................
rel 48+4 t=9 runtime.duffzero+0
rel 72+4 t=9 runtime.duffzero+0
rel 200+4 t=9 runtime.panicIndex+0
rel 212+4 t=9 runtime.panicIndex+0
rel 224+4 t=9 runtime.morestack_noctxt+0
go:cuinfo.producer.main SDWARFCUINFO dupok size=0
0x0000 72 65 67 61 62 69                                regabi
go:cuinfo.packagename.main SDWARFCUINFO dupok size=0
0x0000 6d 61 69 6e                                      main
go:info.main.add$abstract SDWARFABSFCN dupok size=45
0x0000 05 6d 61 69 6e 2e 61 64 64 00 01 01 0e 61 00 08  .main.add....a..
0x0010 00 00 00 00 0e 62 00 09 00 00 00 00 0e 63 00 0a  .....b.......c..
0x0020 00 00 00 00 0e 69 00 0c 00 00 00 00 00           .....i.......
rel 16+4 t=31 go:info.[]int32+0
rel 24+4 t=31 go:info.[]int32+0
rel 32+4 t=31 go:info.[]int32+0
rel 40+4 t=31 go:info.int32+0
main..inittask SNOPTRDATA size=24
0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x0010 00 00 00 00 00 00 00 00                          ........
type:.eqfunc1024 SRODATA dupok size=16
0x0000 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00  ................
rel 0+8 t=1 runtime.memequal_varlen+0
runtime.memequal64·f SRODATA dupok size=8
0x0000 00 00 00 00 00 00 00 00                          ........
rel 0+8 t=1 runtime.memequal64+0
runtime.gcbits.0100000000000000 SRODATA dupok size=8
0x0000 01 00 00 00 00 00 00 00                          ........
type:.namedata.*[256]int32- SRODATA dupok size=13
0x0000 00 0b 2a 5b 32 35 36 5d 69 6e 74 33 32           ..*[256]int32
type:*[256]int32 SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00  ................
0x0010 5c eb 0a 2f 08 08 08 36 00 00 00 00 00 00 00 00  \../...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x0030 00 00 00 00 00 00 00 00                          ........
rel 24+8 t=1 runtime.memequal64·f+0
rel 32+8 t=1 runtime.gcbits.0100000000000000+0
rel 40+4 t=5 type:.namedata.*[256]int32-+0
rel 48+8 t=1 type:[256]int32+0
runtime.gcbits. SRODATA dupok size=0
type:[256]int32 SRODATA dupok size=72
0x0000 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x0010 1e 16 ae f5 0a 04 04 11 00 00 00 00 00 00 00 00  ................
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x0040 00 01 00 00 00 00 00 00                          ........
rel 24+8 t=1 type:.eqfunc1024+0
rel 32+8 t=1 runtime.gcbits.+0
rel 40+4 t=5 type:.namedata.*[256]int32-+0
rel 44+4 t=-32763 type:*[256]int32+0
rel 48+8 t=1 type:int32+0
rel 56+8 t=1 type:[]int32+0
gclocals·g2BeySu+wFnoycgXfElmcg== SRODATA dupok size=8
0x0000 01 00 00 00 00 00 00 00                          ........

 

go tool objdump를 통해 디스어셈블 하고 vadd를 찾으면 먼가 나오는데

위에서 테스트한 코드가 아니라 다른 어셈블리 코드의 것이 나온다.

go tool objdump tt | grep -i vadd
  indexbyte_arm64.s:61 0x11cc4 4e24bc66 VADDP V4.B16, V3.B16, V6.B16
  indexbyte_arm64.s:62 0x11cc8 4e26bcc6 VADDP V6.B16, V6.B16, V6.B16
  indexbyte_arm64.s:82 0x11cfc 4ee6bcc6 VADDP V6.D2, V6.D2, V6.D2
  indexbyte_arm64.s:91 0x11d10 4e24bc66 VADDP V4.B16, V3.B16, V6.B16
  indexbyte_arm64.s:92 0x11d14 4e26bcc6 VADDP V6.B16, V6.B16, V6.B16

 

경로와 파일명만 보면 arm64용 배열에 대한 내부 변환 알고리즘 같긴한데..

Text file src/internal/bytealg/indexbyte_arm64.s

[링크 : https://tip.golang.org/src/internal/bytealg/indexbyte_arm64.s]

 

그래서 그냥 디스어셈블 하니 87만 라인?

$ aarch64-linux-gnu-objdump -d tt > t2
$ wc -l t2
87170 t2

 

vadd로 검색하면 하나도 안나온다 -_-

$ aarch64-linux-gnu-objdump -d tt | grep -i vadd
$

 

그래서 된다고 봐야 하나 말아야 하나..

 

 

+

일단 실행시간으로 비교!

$ cat neon.go 
package main

func main() {
add()
}

func add() {
cnt := 10000000
a := make([]int32, cnt)
b := make([]int32, cnt)
c := make([]int32, cnt)

i := 0
for i = 0; i < cnt; i++ {
b[i] = int32(i);
c[i] = int32(cnt - i);
}

for i = 0; i < cnt; i++ {
a[i] = b[i] + c[i]
}
}

 

위의 소스로 테스트를 해보니 arm64가 좀 빨라지긴 한데... 미묘하네

/// GOARCH=arm go build -gcflags -S .
# time ./tt

real    0m0.196s
user    0m0.161s
sys     0m0.036s
/// GOARCH=arm64 go build -gcflags -S .
# time ./tt.aarch64 

real    0m0.162s
user    0m0.087s
sys     0m0.075s

 

 

+

c로 하려는데

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 void main()
  5 {
  6         int cnt = 10000000;
  7         int *a,*b,*c;
  8         a = malloc(sizeof(int) * cnt);
  9         b = malloc(sizeof(int) * cnt);
 10         c = malloc(sizeof(int) * cnt);
 11 
 12         for(int i = 0; i < cnt; i++)
 13         {
 14                 b[i] = i;
 15                 c[i] = cnt - i;
 16         }
 17 
 18         for(int i = 0; i < cnt; i++)
 19         {
 20                 a[i] = b[i] + c[i];
 21         }
 22 
 23         printf("%d %d %d\n",a[0],b[0],c[0]);
 24 
 25         return 0;
 26 }

 

아무래도 printf가 없어서 계산은 하지만 사용하지 않는(출력이 없어서) 그냥 최적화 옵션에서 제외해버리니까

결과에 대해서만 출력하도록 두고 해보니

$ aarch64-poky-linux-gcc --sysroot=/opt/fsl-imx-wayland/5.15-kirkstone/sysroots/armv8a-poky-linux -march=armv8-a -O3 -fopt-info-vec neon.c
neon.c:18:19: optimized: loop vectorized using 16 byte vectors
neon.c:12:19: optimized: loop vectorized using 16 byte vectors

 

음.. 0.213s라.. go가 오히려 빠른가 싶었는데, user space로 보면 그래도 c가 빠르긴 한 듯.

# time ./a.out 
10000000 0 10000000

real    0m0.213s
user    0m0.076s
sys     0m0.135s

 

다시 출력을 추가해서

  1 package main
  2 
  3 import "fmt"
  4 
  5 func main() {
  6         add()
  7 }
  8 
  9 func add() {
 10         cnt := 10000000
 11         a := make([]int32, cnt)
 12         b := make([]int32, cnt)
 13         c := make([]int32, cnt)
 14 
 15         i := 0
 16         for i = 0; i < cnt; i++ {
 17                 b[i] = int32(i);
 18                 c[i] = int32(cnt - i);
 19         }
 20 
 21         for i = 0; i < cnt; i++ {
 22                 a[i] = b[i] + c[i]
 23         }
 24 
 25         fmt.Println("neon");
 26         fmt.Println(a[0], b[0], c[0])
 27 }

 

실행해보니 0.204s go가 조금 더 빠르다? 그런데 희한할 정도로 sys가 짧은 건 왜일까?

# time ./neon
neon
10000000 0 10000000

real    0m0.204s
user    0m0.179s
sys     0m0.025s

 

혹시나 해서 c로 짠걸 neon 옵션 빼고(-O3) 해보니 속도 상으로는 맞는 듯?

# time ./a.out.none
10000000 0 10000000

real    0m0.699s
user    0m0.550s
sys     0m0.144s

 

'Programming > golang' 카테고리의 다른 글

go packed struct  (0) 2023.09.01
golang asm  (0) 2023.08.24
golang echo 서버 이상한 버그 발견?  (0) 2023.06.27
go ws server client example  (0) 2023.06.08
golang waitgroup  (0) 2023.05.24
Posted by 구차니