Goè¨èªä½ã¬ã¤ã¤ã¼å ¥é�Hello world ã�ç»é¢ã«è¡¨ç¤ºãããã¾ã§
@DQNEO (ããã¥ããª)
Go Conference Tokyo 2021
2021-04-24
èªå·±ç´¹ä»
ç®æ¬¡
仿¥ã®è©±ã®åæ
package main
import (
"fmt"
)
func main() {
fmt.Print("Hello world\n")
}
Hello world
Hello world
ã©ã®ãããªããã»ã¹ãçµã¦
ç»é¢ã«æåã表示ãããã®ã§ããããï¼
å°ãæ³åãã¦ã¿ã¦ãã ãã
�(â»OSå é¨ãè¡¨ç¤ºè£ ç½®ã®æåã¯é¤ã)
package main
func main() {
}
Goã®æå°ã®ããã°ã©ã
ãªã«ãããªãããã°ã©ã
package main
func main() {
}
ããã°ã©ã ã¯ï¿½ã©ãããå§ã¾ã£ã¦ã©ãã§çµããã®ãï¼
ããã°ã©ã ã¯ã©ãããå§ã¾ãã®ãï¼
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
ããã°ã©ã ã¯ã©ãããå§ã¾ãã®ãï¼
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
_rt0_amd64_linux
TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
JMP _rt0_amd64(SB)
src/runtime/rt0_linux_amd64.s
éå§
ããã°ã©ã ã¯ã©ãããå§ã¾ãã®ãï¼
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
_rt0_amd64_linux
åæåå¦ç
main.main()
éå§
ããã°ã©ã ã¯ã©ãã§çµããã®ãï¼
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
_rt0_amd64_linux
...
main.main()
...
ãexit 0ãã¦ãã
çµäº
éå§
TEXT runtime·exit(SB),NOSPLIT,$0-4
MOVL code+0(FP), DI
MOVL $SYS_exit_group, AX
SYSCALL
RET
src/runtime/sys_linux_amd64.s
package main
func main() {
}
Goã®æå°ã®ããã°ã©ã
ãªã«ãããªãããã°ã©ã �exit 0 ããããã°ã©ã
ããã°ã©ã ã¨runtime
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
_rt0_amd64_linux
â¦.
main.main()
â¦
ãexit 0ãã¦ãã
runtime
ããã°ã©ã ã¨runtime
func main() { }
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
mainããã±ã¼ã¸
_rt0_amd64_linux
â¦.
main.main()
â¦
ãexit 0ãã¦ãã
runtime
runtimeã¨ã¯ã
ãã«ãæã«ããã°ã©ã ã«èªåã§çµã¿è¾¼ã¾ããã³ã¼ãã®ãã¨
package main
func main() {
}
Goã®æå°ã®ããã°ã©ã
ãªã«ãããªãããã°ã©ã �exit 0 ããããã°ã©ã
runtimeã®åãåã㦠exit 0 ããããã°ã©ã
exit 0ã£ã¦ã
çµäºãããåæã«ãããªãã®ã§ã¯ï¼
ããã°ã©ã ã¨OS
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
OS (Kernel)
ã³ã³ãã¥ã¼ã¿ã§åãã³ã¼ãã¯ä¸»ã«ãã®ï¼ã¤
ããã°ã©ã ã¨OS
1 + 2
s = âhelloâ
OS (Kernel)
ç°¡åãªè¨ç®ãä»£å ¥ãªã©ã¯ãOSã®å©ããªãã«è¡ããã¨ãã§ãã
(CPUãæ©æ¢°èªåããã®ã¾ã¾å®è¡ãã)
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
ããã°ã©ã ã¨OS
1 + 2
s = âhelloâ
OS (Kernel)
OSã®å©ããªãã§ã¯ãç»é¢è¡¨ç¤º/ãã¡ã¤ã«æä½/ãããã¯ã¼ã¯éä¿¡ãªã©ãã§ããªã
ããã°ã©ã ãæ£å¸¸çµäº (exit 0)ãããã¨ãã§ããªã
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
exit 0 ã®ä»çµã¿
OS (Kernel)
runtime
ãexit 0 ãã¦ãã
func main() { }
ãããã¾ãã
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
ã·ã¹ãã ã³ã¼ã«
ããã°ã©ã ã®æå¾ã§ OS ã« exit 0ãä¾é ¼ãã¦ãã�(ãããªãã¨ã¯ã©ãã·ã¥ï¼
package main
func main() {
}
Goã®æå°ã®ããã°ã©ã
ãªã«ãããªãããã°ã©ã �exit 0 ããããã°ã©ã
runtimeã®åãåã㦠exit 0 ãã�OSã« exit 0 ãä¾é ¼ããããã°ã©ã
ä½ã¬ã¤ã¤ã¯å®æãã¥ãã
OS (Kernel)
runtime
ã0ã§exitãã¦ãã
package main
func main() { }
ãããã¾ãã
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
ãã®ã¸ã
ããã èªåã§ãã£ã¦ã¿ãã
OS (Kernel)
runtime
ãããã¾ãã
ããã°ã©ã �(ãã¤ããªå®è¡ãã¡ã¤ã«)
package main
ã0ã§exitãã¦ãã
ã³ã³
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
èªåã§ exit(0) ãã
runtimeã®åãåããã«
OS ã«exit 0ãä¾é ¼ããããã°ã©ã
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
func main() {
os.Exit(0)
}
èªåã§ exit(0) ãã
Kernel ã«ï¿½231çªç®ã®ã«ã¼ãã«å½ä»¤ (exit_group)ãï¿½å¼æ°0ã§ï¿½å®è¡ããé¡ããã(syscall)
â
main颿°
ã®ããã£
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $231, AX
MOVQ $1, DI
SYSCALL
-- main.go --
package main
func main()
func main() {
os.Exit(1)
}
ã¡ãã£ã¨å¤ãã¦ã¿ã
弿°ã1ã«ããã¨ã1ã§exitãã
â
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
ã¡ãªã¿ã«
éæåã®ç®æã¯ä»ã¯æ°ã«ããªãã§ãã ãã
ç¾ç¶ç¢ºèª
ããã°ã©ã
OS (Kernel)
runtime
func main() {
}
ãããã¾ãã
ã0ã§exitãã¦ãã
ã·ã¹ãã ã³ã¼ã«
ã·ã¹ãã ã³ã¼ã«ã§ã§ãããã¨
package main
import (
"fmt"
)
func main() {
fmt.Print("Hello world\n")
}
Hello world
Hello world
ããã°ã©ã
OS (Kernel)
runtime
func main() {
}
ãããã¾ãã
fmt.Print(âH..â)
ã·ã¹ãã ã³ã¼ã«?
ã·ã¹ãã ã³ã¼ã«ã§å®ç¾ããã¦ãã...ï¼
ããã確ãããã
ã·ã¹ãã ã³ã¼ã«ã確èªããæ¹æ³
straceã³ãã³ã
straceä½¿ãæ¹
$ strace ./hello > /dev/null
straceã®ãã¢
straceã®åºå
writeã·ã¹ãã ã³ã¼ã«ã§ç»é¢è¡¨ç¤º
ããã°ã©ã
OS (Kernel)
func main() {
}
å¦ç
fmt.Print(âH..â)
write(1, âH⦠)
hello world
ã¿ã¼ããã«
straceã®åºå (æç²)
write(1, "Hello world\n", 12) = 12
straceã®åºå (æç²)
write(1, "Hello world\n", 12) = 12
ã·ã¹ãã ã³ã¼ã«ã®ç¨®é¡
弿°
æ»ãå¤
ä¾: write
ã·ã¹ãã ã³ã¼ã«ã®ä½¿ãæ¹ã調ã¹ã
ssize_t write(int fd, const void *buf, size_t count);
ãã¡ã¤ã«ãã£ã¹ã¯ãªãã¿
ãããã¡
(ãã¤ãåã®å é ã¢ãã¬ã¹)
ãã¤ãæ°
æ»ãå¤
å®éã«æ¸ãè¾¼ãã ãã¤ãæ°
(失ææã¯ -1)
write(2) â Linux manual page
straceã®åºå (æç²)
write(1, "Hello world\n", 12)
ã·ã¹ãã ã³ã¼ã«
æ¨æºåºå
12ãã¤ã
ãããã¡
(ãã¤ãåã®å é ã¢ãã¬ã¹)
gdb
gdb ã§ããã°å®è¡ãã¦ã¿ãã
ãã¢
(Hello World ãgdbã§ããã°)
writeã®ããã¯ãã¬ã¼ã¹
#0 syscall.Syscall () at /usr/lib/go-1.15/src/syscall/asm_linux_amd64.s:24
#1 0x000000000048ccba in syscall.write (fd=1, p=..., n=<optimized out>, err=...)
at /usr/lib/go-1.15/src/syscall/zsyscall_linux_amd64.go:914
#2 0x000000000048e877 in syscall.Write (fd=<optimized out>, p=..., n=<optimized out>, err=...)
at /usr/lib/go-1.15/src/syscall/syscall_unix.go:212
#3 internal/poll.(*FD).Write.func1 (~r0=<optimized out>, ~r1=...)
at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#4 0x000000000048e7a7 in internal/poll.ignoringEINTR (fn={void (int *, error *)} 0xc0000a0da0, ~r1=<optimized out>,
~r2=...) at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:567
#5 0x000000000048e49c in internal/poll.(*FD).Write (fd=0xc0000bc060, p=..., ~r1=<optimized out>, ~r2=...)
at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#6 0x000000000048ecf7 in os.(*File).write (f=0xc0000ba008, b=..., n=<optimized out>, err=...)
at /usr/lib/go-1.15/src/os/file_posix.go:48
#7 os.(*File).Write (f=0xc0000ba008, b=..., n=<optimized out>, err=...) at /usr/lib/go-1.15/src/os/file.go:173
#8 0x0000000000492c6b in fmt.Fprint (w=..., a=..., n=<optimized out>, err=...)
at /usr/lib/go-1.15/src/fmt/print.go:233
#9 0x00000000004990f5 in fmt.Print (a=..., n=<optimized out>, err=...) at /usr/lib/go-1.15/src/fmt/print.go:242
#10 main.main () at /mnt/main.go:6
writeã®ããã¯ãã¬ã¼ã¹
#0 syscall.Syscall () at /usr/lib/go-1.15/src/syscall/asm_linux_amd64.s:24
#1 syscall.write () at /usr/lib/go-1.15/src/syscall/zsyscall_linux_amd64.go:914
#2 syscall.Write () at /usr/lib/go-1.15/src/syscall/syscall_unix.go:212
#3 internal/poll.(*FD).Write.func1 at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#4 internal/poll.ignoringEINTR () at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:567
#5 internal/poll.(*FD).Write () at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#6 os.(*File).write () at /usr/lib/go-1.15/src/os/file_posix.go:48
#7 os.(*File).Write () at /usr/lib/go-1.15/src/os/file.go:173
#8 fmt.Fprint () at /usr/lib/go-1.15/src/fmt/print.go:233
#9 fmt.Print () at /usr/lib/go-1.15/src/fmt/print.go:242
#10 main.main () at /mnt/main.go:6
è¦ãããããã¨ãããªæã
ã½ã¼ã¹ã³ã¼ãã�fmt.Print()ãããã©ã£ã¦ã¿ãã
Golandã®å ´å
OS, Archã Linux / amd64 ã«è¨å®ãã¦ãã
ãã¢
(Golandã§ã³ã¼ããªã¼ãã£ã³ã°)
æä½ã¬ã¤ã¤ã¼ã¯ syscall.Syscall颿°
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
MOVQ a1+8(FP) , DI
MOVQ a2+16(FP) , SI
MOVQ a3+24(FP) , DX
MOVQ trap+0(FP), AX // syscall entry
SYSCALL
...
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr,� err Errno)
ã·ã°ããã£
ããã£
src/syscall/asm_linux_amd64.s
src/syscall/syscall_unix.go
syscall.Syscall颿°ãèªã
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
MOVQ a1+8(FP) , DI
MOVQ a2+16(FP) , SI
MOVQ a3+24(FP) , DX
MOVQ trap+0(FP), AX
SYSCALL
...
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr,� err Errno)
ã·ã°ããã£
ããã£
syscall.Syscall颿°ãèªã
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
MOVQ a1+8(FP) , DI
MOVQ a2+16(FP) , SI
MOVQ a3+24(FP) , DX
MOVQ trap+0(FP), AX
SYSCALL
...
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr,� err Errno)
ã·ã°ããã£
ããã£
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
CPUå½ä»¤
弿°1
弿°2
,
弿°ã«ã¯ã
ãªã©ãæå®ã§ãã
ã¬ã¸ã¹ã¿ã£ã¦ï¼
CPUå é¨ã®è¨æ¶è£ ç½®
è¶ å°å®¹éã»è¶ é«é
Intel 8086 CPU
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
MOV : Move (ã³ãã¼å½ä»¤)
Q : Quad word (4word = 4*16bit = 64bit)
ã弿°1ãã弿°2ã« 64bitåã³ãã¼ãã¦ãã
æå³çã«ã¯ MOVQ ã¨ãããã COPY64
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
ã¡ã¢
ã¡ã¢ãªã¢ãã¬ã¹
(颿°ãã¼ã«ã«ã®ã¨ããå°ç¹ + 8byteå¾ã)
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
ã¬ã¸ã¹ã¿ã®åå
(æ¬å½ã®åå㯠RDI)
Goã¢ã»ã³ããªã®èªã¿æ¹
MOVQ a1+8(FP), DI
syscall.Syscall颿°ã®èªã¿æ¹
ã·ã°ããã£
ããã£
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
MOVQ a1+8(FP) , DI
MOVQ a2+16(FP) , SI
MOVQ a3+24(FP) , DX
MOVQ trap+0(FP), AX
SYSCALL
...
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr,� err Errno)
syscall.Syscall颿°ã®èªã¿æ¹
ã·ã°ããã£
ããã£
TEXT ·Syscall(SB),NOSPLIT,$0-56
CALL runtime·entersyscall(SB)
MOVQ trap+0(FP), AX
MOVQ a1+8(FP) , DI
MOVQ a2+16(FP) , SI
MOVQ a3+24(FP) , DX
SYSCALL
...
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr,� err Errno)
ãã£ã¦ããã¨
System V Application Binary Interface
æé ã¯ã«ã¼ãã«ã®å¼ã³åºãè¦ç´ã§æ±ºã¾ã£ã¦ãã
ä½è«:ã¬ã¸ã¹ã¿ã®ååããããã«ãã
ã©ã¤ãã³ã¼ãã£ã³ã°
èªåã§ã·ã¹ãã ã³ã¼ã«ãå©ãã¦
hello worldãåºåããã
package main
import (
"fmt"
)
func main() {
fmt.Print("Hello world\n")
}
ãµã¤ãã®Hello world
ããã¯ãã¬ã¼ã¹ãéé ã§åç¾ãã¦ããã¾ã
#0 syscall.Syscall () at /usr/lib/go-1.15/src/syscall/asm_linux_amd64.s:24
#1 syscall.write () at /usr/lib/go-1.15/src/syscall/zsyscall_linux_amd64.go:914
#2 syscall.Write () at /usr/lib/go-1.15/src/syscall/syscall_unix.go:212
#3 internal/poll.(*FD).Write.func1 at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#4 internal/poll.ignoringEINTR () at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:567
#5 internal/poll.(*FD).Write () at /usr/lib/go-1.15/src/internal/poll/fd_unix.go:267
#6 os.(*File).write () at /usr/lib/go-1.15/src/os/file_posix.go:48
#7 os.(*File).Write () at /usr/lib/go-1.15/src/os/file.go:173
#8 fmt.Fprint () at /usr/lib/go-1.15/src/fmt/print.go:233
#9 fmt.Print () at /usr/lib/go-1.15/src/fmt/print.go:242
#10 main.main () at /mnt/main.go:6
package main
import (
"fmt"
"os"
)
func main() {
fmt.Fprint(os.Stdout, "Hello world\n")
}
fmt.Fprint
package main
import (
"os"
)
func main() {
os.Stdout.Write([]byte("Hello world\n"))
}
os.File.Write
package main
import (
"syscall"
)
func main() {
syscall.Write(1, []byte("Hello world\n"))
}
syscall.Write
package main
import (
"syscall"
"unsafe"
)
func main() {
var buf = []byte("Hello world\n")
syscall.Syscall(1, 1, uintptr(unsafe.Pointer(&buf[0])), 12)
}
syscall.Syscall
package main
import (
"syscall"
"unsafe"
)
func main() {
var bytes = [6]byte{'H','e','l','l','o','\n'}
syscall.Syscall(1, 1, uintptr(unsafe.Pointer(&bytes[0])), 6)
}
slice ã array ã«
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
import (
// "syscall"
// "unsafe"
)
func main()
//{
// var bytes = [6]byte{'H','e','l','l','o','\n'}
// syscall.Syscall(1, 1, uintptr(unsafe.Pointer(&bytes[0])), 6)
//}
ã¢ã»ã³ããªã§æ¸ããã (exit 0)
-- a.s --
TEXT main·main(SB),0,$0
MOVQ $1, AX // write
MOVQ $1, DI // stdout
LEAQ main·bytes(SB), SI // address
MOVQ $6, DX
SYSCALL
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
var bytes = [6]byte{'H','e','l','l','o','\n'}
func main()
ã¢ã»ã³ããªã§ Hello
-- a.s --
#define READONLY 8
DATA array+0(SB)/1, $'H'
DATA array+1(SB)/1, $'e'
DATA array+2(SB)/1, $'l'
DATA array+3(SB)/1, $'l'
DATA array+4(SB)/1, $'o'
DATA array+5(SB)/1, $'\n'
GLOBL array(SB),READONLY, $6
TEXT main·main(SB),0,$0
MOVQ $1, AX // write
MOVQ $1, DI // stdout
LEAQ array+0(SB), SI // address
MOVQ $6, DX // len
SYSCALL
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
ã¢ã»ã³ããªã§ Hello (é åãã¢ã»ã³ããª)
-- a.s --
#define READONLY 8
DATA array+0(SB)/1, $0x48
DATA array+1(SB)/1, $0x65
DATA array+2(SB)/1, $0x6c
DATA array+3(SB)/1, $0x6c
DATA array+4(SB)/1, $0x6f
DATA array+5(SB)/1, $0x0a
GLOBL array(SB),READONLY, $6
TEXT main·main(SB),0,$0
MOVQ $1, AX // write
MOVQ $1, DI // stdout
LEAQ array+0(SB), SI // address
MOVQ $6, DX // len
SYSCALL
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
ã¢ã»ã³ããªã§ Hello (æåããã¤ããªã§)
èªåã§Hello world
-- a.s --
#define READONLY 8
DATA array+0(SB)/1, $0x48
DATA array+1(SB)/1, $0x65
DATA array+2(SB)/1, $0x6c
DATA array+3(SB)/1, $0x6c
DATA array+4(SB)/1, $0x6f
DATA array+5(SB)/1, $0x0a
GLOBL array(SB),READONLY, $6
TEXT main·main(SB),0,$0
MOVQ $1, AX // write
MOVQ $1, DI // stdout
LEAQ array+0(SB), SI // address
MOVQ $6, DX //
SYSCALL
MOVQ $231, AX
MOVQ $0, DI
SYSCALL
-- main.go --
package main
func main()
èªåã§ãã¤ãåãã¡ã¢ãªã«ä¸¦ã¹
èªåã§ syscall write
èªåã§ exit 0
ã¾ã¨ã
ä½ã¬ã¤ã¤ã¯ãã®ãã
仿¥ã®å 容ãåç¾ã§ããç°å¢
åè
ãæ¸ è´
ãããã¨ããããã¾ãã