Closed kimpro82 closed 1 year ago
package main
// import "fmt"
func main() {
// fmt.Println("I love assembly")
println("I love assembly")
}
go tool compile -S assembler1.go
"".main STEXT size=86 args=0x0 locals=0x18 funcid=0x0
0x0000 00000 (assembler1.go:5) TEXT "".main(SB), ABIInternal, $24-0
0x0000 00000 (assembler1.go:5) MOVQ (TLS), CX
0x0009 00009 (assembler1.go:5) CMPQ SP, 16(CX)
0x000d 00013 (assembler1.go:5) PCDATA $0, $-2
0x000d 00013 (assembler1.go:5) JLS 79
0x000f 00015 (assembler1.go:5) PCDATA $0, $-1
0x000f 00015 (assembler1.go:5) SUBQ $24, SP
0x0013 00019 (assembler1.go:5) MOVQ BP, 16(SP)
0x0018 00024 (assembler1.go:5) LEAQ 16(SP), BP
0x001d 00029 (assembler1.go:5) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (assembler1.go:5) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (assembler1.go:7) PCDATA $1, $0
0x001d 00029 (assembler1.go:7) NOP
0x0020 00032 (assembler1.go:7) CALL runtime.printlock(SB)
0x0025 00037 (assembler1.go:7) LEAQ go.string."I love assembly\n"(SB), AX
0x002c 00044 (assembler1.go:7) MOVQ AX, (SP)
0x0030 00048 (assembler1.go:7) MOVQ $16, 8(SP)
0x0039 00057 (assembler1.go:7) CALL runtime.printstring(SB)
0x003e 00062 (assembler1.go:7) NOP
0x0040 00064 (assembler1.go:7) CALL runtime.printunlock(SB)
0x0045 00069 (assembler1.go:8) MOVQ 16(SP), BP
0x004a 00074 (assembler1.go:8) ADDQ $24, SP
0x004e 00078 (assembler1.go:8) RET
0x004f 00079 (assembler1.go:8) NOP
0x004f 00079 (assembler1.go:5) PCDATA $1, $-1
0x004f 00079 (assembler1.go:5) PCDATA $0, $-2
0x004f 00079 (assembler1.go:5) CALL runtime.morestack_noctxt(SB)
0x0054 00084 (assembler1.go:5) PCDATA $0, $-1
0x0054 00084 (assembler1.go:5) JMP 0
0x0000 64 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 40 48 dH..%....H;a.v@H
0x0010 83 ec 18 48 89 6c 24 10 48 8d 6c 24 10 0f 1f 00 ...H.l$.H.l$....
0x0020 e8 00 00 00 00 48 8d 05 00 00 00 00 48 89 04 24 .....H......H..$
0x0030 48 c7 44 24 08 10 00 00 00 e8 00 00 00 00 66 90 H.D$..........f.
0x0040 e8 00 00 00 00 48 8b 6c 24 10 48 83 c4 18 c3 e8 .....H.l$.H.....
0x0050 00 00 00 00 eb aa ......
rel 5+4 t=17 TLS+0
rel 33+4 t=8 runtime.printlock+0
rel 40+4 t=16 go.string."I love assembly\n"+0
rel 58+4 t=8 runtime.printstring+0
rel 65+4 t=8 runtime.printunlock+0
rel 80+4 t=8 runtime.morestack_noctxt+0
go.cuinfo.packagename. SDWARFCUINFO dupok size=0
0x0000 6d 61 69 6e 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 ........
go.string."I love assembly" SRODATA dupok size=15
0x0000 49 20 6c 6f 76 65 20 61 73 73 65 6d 62 6c 79 I love assembly
go.string."I love assembly\n" SRODATA dupok size=16
0x0000 49 20 6c 6f 76 65 20 61 73 73 65 6d 62 6c 79 0a I love assembly.
gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8
0x0000 01 00 00 00 00 00 00 00 ........
hmm
"".main STEXT size=86 args=0x0 locals=0x18 funcid=0x0
해당 행은 Go 언어 코드에서 함수 main
에 대한 정보를 나타내는 부분입니다. 이 행의 의미를 해석해보겠습니다:
"".main
: 이 부분은 함수 main
의 이름을 나타냅니다. Go 언어에서 함수 이름은 패키지 이름과 함수 이름을 합쳐서 표시될 수 있습니다.STEXT
: 이 부분은 이 함수가 텍스트(코드) 섹션에 속한다는 것을 나타냅니다. 함수의 코드가 여기에 저장됩니다.size=86
: 이 함수의 코드 크기가 86바이트라는 것을 나타냅니다. 이는 해당 함수가 컴파일된 후 생성된 어셈블리 코드의 크기입니다.args=0x0
: 이 함수에 전달되는 인자가 없음을 나타냅니다. 즉, 함수 main
은 인자를 받지 않습니다.locals=0x18
: 이 함수 내에서 사용되는 로컬 변수의 크기가 0x18바이트임을 나타냅니다.funcid=0x0
: 함수의 고유 식별자를 나타냅니다. 이 값은 일반적으로 0이며, 특별한 경우에만 사용됩니다.이 행은 함수 main
의 세부 정보를 표시하여 해당 함수의 특성과 구성을 알려줍니다.
0x0000 00000 (assembler1.go:5) TEXT "".main(SB), ABIInternal, $24-0
0x0000 00000 (assembler1.go:5) MOVQ (TLS), CX
0x0009 00009 (assembler1.go:5) CMPQ SP, 16(CX)
0x000d 00013 (assembler1.go:5) PCDATA $0, $-2
0x000d 00013 (assembler1.go:5) JLS 79
0x000f 00015 (assembler1.go:5) PCDATA $0, $-1
0x000f 00015 (assembler1.go:5) SUBQ $24, SP
0x0013 00019 (assembler1.go:5) MOVQ BP, 16(SP)
0x0018 00024 (assembler1.go:5) LEAQ 16(SP), BP
0x001d 00029 (assembler1.go:5) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (assembler1.go:5) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
이 부분은 Go 언어 코드에서 함수 main
의 어셈블리 코드 표현을 나타내는 부분입니다. 각 행은 다양한 어셈블리 명령어와 해당 명령어의 주석으로 구성되어 있습니다. 아래에 각 행의 의미를 설명해드리겠습니다:
TEXT "".main(SB), ABIInternal, $24-0
: 이 부분은 함수 main
의 시작을 나타내며, 함수의 이름과 매개변수, 로컬 변수 등의 정보를 포함합니다. ABIInternal
은 함수의 호출 규약을 의미하며, $24-0
은 스택에서 사용되는 공간의 크기를 나타냅니다.MOVQ (TLS), CX
: TLS(Thread-Local Storage)에서 값을 읽어와 레지스터 CX
에 저장하는 명령어입니다. TLS는 현재 스레드에 대한 데이터를 저장하는 영역입니다.CMPQ SP, 16(CX)
: 스택 포인터 SP
의 값을 레지스터 CX
에 있는 값과 비교하는 명령어입니다. 이는 스택 오버플로우를 검사하기 위한 것으로 보입니다.PCDATA $0, $-2
: PCDATA는 실행 정보를 나타내며, 이 행에서는 실행 상태 정보가 제공됩니다.JLS 79
: 만약 이전의 CMPQ 조건이 만족되지 않으면 상대 주소 79로 이동합니다. 즉, 조건에 따라 분기하는 명령어입니다.SUBQ $24, SP
: 스택 포인터 SP
를 24만큼 감소시키는 명령어로, 로컬 변수 공간을 할당하는 역할을 할 수 있습니다.MOVQ BP, 16(SP)
: 베이스 포인터 BP
의 값을 스택 포인터 SP
에서 16만큼 떨어진 위치에 저장하는 명령어로, 함수 프롤로그에서 실행됩니다.LEAQ 16(SP), BP
: 베이스 포인터 BP
에 스택 포인터 SP
에서 16만큼 떨어진 위치의 주소를 저장하는 명령어입니다.FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
: 함수에서 사용되는 로컬 변수에 대한 정보를 제공하는 명령어입니다.FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
: 또 다른 종류의 함수 로컬 변수 정보를 제공하는 명령어입니다.이 부분은 함수 main
의 어셈블리 코드로, 함수의 시작, 종료 및 로컬 변수 관리 등의 기본 동작을 나타내는 명령어들로 구성되어 있습니다.
0x001d 00029 (assembler1.go:7) PCDATA $1, $0
0x001d 00029 (assembler1.go:7) NOP
0x0020 00032 (assembler1.go:7) CALL runtime.printlock(SB)
0x0025 00037 (assembler1.go:7) LEAQ go.string."I love assembly\n"(SB), AX
0x002c 00044 (assembler1.go:7) MOVQ AX, (SP)
0x0030 00048 (assembler1.go:7) MOVQ $16, 8(SP)
0x0039 00057 (assembler1.go:7) CALL runtime.printstring(SB)
0x003e 00062 (assembler1.go:7) NOP
0x0040 00064 (assembler1.go:7) CALL runtime.printunlock(SB)
위의 내용은 Go 언어 코드에서 함수 main
내에서 실행되는 어셈블리 코드 표현입니다. 이 코드의 명령어들을 하나씩 설명해드리겠습니다:
PCDATA $1, $0
: PCDATA는 실행 정보를 나타내며, 이 행에서는 실행 상태 정보가 제공됩니다.NOP
: 아무 동작도 수행하지 않는 명령어입니다. 주로 코드의 흐름 제어나 최적화 관련 목적으로 사용됩니다.CALL runtime.printlock(SB)
: runtime.printlock
함수를 호출하는 명령어입니다. 이 함수는 락을 획득하여 다른 스레드와의 동기화를 수행하는 역할을 합니다.LEAQ go.string."I love assembly\n"(SB), AX
: 문자열 상수 "I love assembly\n"
의 주소를 레지스터 AX
에 저장하는 명령어입니다.MOVQ AX, (SP)
: 레지스터 AX
에 있는 값을 스택의 최상위에 저장하는 명령어입니다.MOVQ $16, 8(SP)
: 스택의 다음 위치에 16을 저장하는 명령어입니다.CALL runtime.printstring(SB)
: runtime.printstring
함수를 호출하여 문자열을 출력하는 명령어입니다.NOP
: 아무 동작도 수행하지 않는 명령어입니다.CALL runtime.printunlock(SB)
: runtime.printunlock
함수를 호출하여 락을 해제하는 명령어입니다.이 부분은 main
함수 내에서 문자열을 출력하는 과정을 나타내는 어셈블리 코드로, 함수 호출, 레지스터 조작, 스택 연산 등의 기본적인 어셈블리 명령어들로 구성되어 있습니다.
0x0045 00069 (assembler1.go:8) MOVQ 16(SP), BP
0x004a 00074 (assembler1.go:8) ADDQ $24, SP
0x004e 00078 (assembler1.go:8) RET
0x004f 00079 (assembler1.go:8) NOP
0x004f 00079 (assembler1.go:5) PCDATA $1, $-1
0x004f 00079 (assembler1.go:5) PCDATA $0, $-2
0x004f 00079 (assembler1.go:5) CALL runtime.morestack_noctxt(SB)
0x0054 00084 (assembler1.go:5) PCDATA $0, $-1
0x0054 00084 (assembler1.go:5) JMP 0
위의 내용은 Go 언어 코드에서 함수 main
의 종료 과정과, 함수 main
외부에서의 어셈블리 코드 표현입니다. 이 코드의 명령어들을 하나씩 설명해드리겠습니다:
MOVQ 16(SP), BP
: 스택 포인터 SP
에서 16만큼 떨어진 위치에 있는 값을 베이스 포인터 BP
에 저장하는 명령어입니다. 이는 함수 프롤로그에서 저장한 BP
값을 복구하는 과정입니다.ADDQ $24, SP
: 스택 포인터 SP
를 24만큼 증가시키는 명령어로, 로컬 변수 공간을 해제하는 역할을 할 수 있습니다.RET
: 함수 main
에서의 반환 명령어입니다. 이로써 main
함수의 실행이 종료됩니다.NOP
: 아무 동작도 수행하지 않는 명령어입니다.PCDATA $1, $-1
: PCDATA는 실행 정보를 나타내며, 이 행에서는 실행 상태 정보가 제공됩니다.PCDATA $0, $-2
: PCDATA는 실행 정보를 나타내며, 이 행에서는 실행 상태 정보가 제공됩니다.CALL runtime.morestack_noctxt(SB)
: 스택 오버플로우 발생 시 실행되는 runtime.morestack_noctxt
함수를 호출하는 명령어입니다. 스택을 확장하는 역할을 합니다.PCDATA $0, $-1
: PCDATA는 실행 정보를 나타내며, 이 행에서는 실행 상태 정보가 제공됩니다.JMP 0
: 상대 주소 0으로 분기하는 명령어로, 무한 루프를 형성하며 프로그램을 종료시키지 않고 계속 실행될 수 있게 합니다.이 부분은 함수 main
의 종료 및 프로그램의 무한 루프 관련된 어셈블리 코드로, 함수의 반환, 스택 조작 및 무한 루프 설정 등을 나타내는 명령어들로 구성되어 있습니다.
rel 5+4 t=17 TLS+0
rel 33+4 t=8 runtime.printlock+0
rel 40+4 t=16 go.string."I love assembly\n"+0
rel 58+4 t=8 runtime.printstring+0
rel 65+4 t=8 runtime.printunlock+0
rel 80+4 t=8 runtime.morestack_noctxt+0
위의 내용은 어셈블리 언어 코드에서 메모리 참조 및 상대 주소를 나타내는 정보입니다. 각 항목은 다른 위치에 있는 메모리를 참조하는 지시 사항을 의미합니다. 여기서 설명해 드리겠습니다:
rel 5+4 t=17 TLS+0
: TLS(Thread-Local Storage) 영역의 주소를 참조합니다. 상대 주소 5에서 4바이트 크기만큼 이동한 위치에 있는 TLS의 시작 주소를 의미합니다.rel 33+4 t=8 runtime.printlock+0
: runtime.printlock
함수의 주소를 상대 주소 33에서 4바이트 크기만큼 이동한 위치에서 참조합니다. 이는 해당 위치에서 runtime.printlock
함수를 호출하는 지시를 나타냅니다.rel 40+4 t=16 go.string."I love assembly\n"+0
: 문자열 상수 "I love assembly\n"
의 주소를 상대 주소 40에서 4바이트 크기만큼 이동한 위치에서 참조합니다.rel 58+4 t=8 runtime.printstring+0
: runtime.printstring
함수의 주소를 상대 주소 58에서 4바이트 크기만큼 이동한 위치에서 참조합니다.rel 65+4 t=8 runtime.printunlock+0
: runtime.printunlock
함수의 주소를 상대 주소 65에서 4바이트 크기만큼 이동한 위치에서 참조합니다.rel 80+4 t=8 runtime.morestack_noctxt+0
: runtime.morestack_noctxt
함수의 주소를 상대 주소 80에서 4바이트 크기만큼 이동한 위치에서 참조합니다.상대 주소와 함수 또는 상수 이름은 컴파일러가 어셈블리 언어 코드를 기계어로 변환하는 과정에서 사용하는 정보입니다. 이 정보들은 실행 시 실제 메모리 주소로 변환되어 프로그램이 올바르게 동작할 수 있도록 도와줍니다.
go.cuinfo.packagename. SDWARFCUINFO dupok size=0
0x0000 6d 61 69 6e 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 ........
go.string."I love assembly" SRODATA dupok size=15
0x0000 49 20 6c 6f 76 65 20 61 73 73 65 6d 62 6c 79 I love assembly
go.string."I love assembly\n" SRODATA dupok size=16
0x0000 49 20 6c 6f 76 65 20 61 73 73 65 6d 62 6c 79 0a I love assembly.
gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8
0x0000 01 00 00 00 00 00 00 00 ........
위의 내용은 Go 언어 코드의 컴파일된 바이너리에 포함된 데이터 섹션에 관한 내용입니다. 각 섹션의 의미를 설명해드리겠습니다:
go.cuinfo.packagename. SDWARFCUINFO dupok size=0
: DWARF 디버깅 정보에서 사용되는 컴파일 단위 정보(CUINFO)를 나타냅니다. 여기서는 패키지 이름을 나타내며, main
이라는 패키지 이름을 의미합니다.""..inittask SNOPTRDATA size=24
: 초기화 작업을 수행하는 데 사용되는 데이터를 나타냅니다. 초기화 작업에 대한 정보와 크기가 포함되어 있습니다.go.string."I love assembly" SRODATA dupok size=15
: 문자열 상수 "I love assembly"
의 정보를 나타냅니다. 상수의 크기와 내용이 표시됩니다.go.string."I love assembly\n" SRODATA dupok size=16
: 문자열 상수 "I love assembly\n"
의 정보를 나타냅니다. 상수의 크기와 내용이 표시됩니다.gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8
: 함수 내에서 사용되는 로컬 변수에 대한 정보를 나타냅니다. 해당 로컬 변수의 크기와 내용이 표시됩니다.이러한 섹션들은 Go 언어 코드의 컴파일된 바이너리에 포함되어, 디버깅, 문자열 상수, 로컬 변수 등의 정보를 저장하고 활용할 수 있도록 합니다.
0x0000 00000 (assembler1.go:5) TEXT "".main(SB), ABIInternal, $24-0
해당 줄은 Go 언어 코드의 어셈블리 코드 중에서 함수 main
에 대한 정보를 나타내는 부분입니다. 이 코드의 의미를 설명하겠습니다:
0x0000 00000
: 이 부분은 해당 어셈블리 코드의 주소를 나타냅니다. 여기서는 0번 주소 위치에서 시작한다는 것을 의미합니다.(assembler1.go:5)
: 이 부분은 해당 코드가 어떤 소스 파일(assembler1.go
)의 몇 번째 줄(5
)에서 생성되었는지를 나타냅니다.TEXT "".main(SB), ABIInternal, $24-0
: 이 부분은 함수 main
에 대한 정보를 제공합니다.
TEXT
: 함수 시작을 나타내는 키워드입니다."".main(SB)
: main
함수의 이름과 함수의 범위를 나타냅니다. Go 언어에서 함수의 이름은 패키지 이름과 함수 이름이 조합된 형태로 표현됩니다.ABIInternal
: 함수 호출 규약을 나타냅니다.$24-0
: 함수 스택 프레임의 크기를 나타냅니다. $24
는 24바이트의 로컬 변수 공간을 할당하며, -0
은 함수에서 사용하지 않는 공간이라는 뜻입니다.이 줄은 함수 main
의 시작을 정의하고, 해당 함수의 이름, 호출 규약, 스택 프레임 크기 등의 정보를 나타냅니다.
0x0000 00000 (assembler1.go:5) MOVQ (TLS), CX
해당 줄은 Go 언어 코드의 어셈블리 코드 중에서 TLS(Thread-Local Storage)에서 값을 읽어와 레지스터 CX
에 저장하는 명령어입니다. 이 코드의 의미를 설명하겠습니다:
0x0000 00000
: 이 부분은 해당 어셈블리 코드의 주소를 나타냅니다. 여기서는 0번 주소 위치에서 시작한다는 것을 의미합니다.(assembler1.go:5)
: 이 부분은 해당 코드가 어떤 소스 파일(assembler1.go
)의 몇 번째 줄(5
)에서 생성되었는지를 나타냅니다.MOVQ (TLS), CX
: 이 부분은 실제 어셈블리 코드입니다.
MOVQ
: 값을 복사하는 명령어입니다.(TLS)
: TLS(Thread-Local Storage)에서 값을 읽어옵니다. TLS는 현재 스레드에 대한 데이터를 저장하는 영역입니다.CX
: 값을 저장할 대상 레지스터입니다. 여기서는 CX
레지스터에 값을 저장합니다.이 명령어는 현재 스레드의 TLS에서 값을 읽어와 CX
레지스터에 저장하는 역할을 수행합니다. TLS는 각 스레드별로 독립적으로 유지되는 데이터를 저장하는 영역으로, 다중 스레드 환경에서 스레드 간의 동기화와 관련된 정보 등이 저장됩니다.