Эта серия постов представляет собой краткое описание необычной формы языка ассемблера, используемого компилятором gc Go.
Ассемблер основан на стиле ввода ассемблеров Plan 9.
Самое важное, что нужно знать об ассемблере Go, - это то, что он не является прямым представлением базовой машины. Некоторые детали точно соответствуют машине, а некоторые нет. Это связано с тем, что пакет компилятора не требует передачи ассемблера в обычном конвейере. Вместо этого компилятор работает с полуабстрактным набором инструкций, и выбор инструкций происходит частично после генерации кода. Ассемблер работает с полуабстрактной формой, поэтому, когда вы видите такую инструкцию, как MOV, то, что фактически генерирует инструментальная цепочка для этой операции, может быть вовсе не инструкцией перемещения, возможно, очисткой или загрузкой. Или он может точно соответствовать машинной инструкции с таким именем. В общем, машинно-зависимые операции имеют тенденцию появляться сами по себе, в то время как более общие концепции, такие как перемещение памяти, вызов и возврат подпрограмм, являются более абстрактными. Детали меняются в зависимости от архитектуры, и возможны неточности; ситуация не совсем ясна.
Программа на ассемблере - это способ проанализировать описание этого полуабстрактного набора инструкций и превратить его в инструкции для ввода компоновщику (linker). Если вы хотите увидеть, как выглядят инструкции в сборке для данной архитектуры, скажем amd64, есть много примеров в исходных кодах стандартной библиотеки, в таких пакетах, как runtime и math/big. Вы также можете проверить, что компилятор испускает как ассемблерный код (фактический результат может отличаться от того, что вы видите здесь):
$ cat x.go
package main
func main() {
println(3)
}
$ GOOS=linux GOARCH=amd64 go tool compile -S x.go # or: go build -gcflags -S x.go
"".main STEXT size=74 args=0x0 locals=0x10
0x0000 00000 (x.go:3) TEXT "".main(SB), $16-0
0x0000 00000 (x.go:3) MOVQ (TLS), CX
0x0009 00009 (x.go:3) CMPQ SP, 16(CX)
0x000d 00013 (x.go:3) JLS 67
0x000f 00015 (x.go:3) SUBQ $16, SP
0x0013 00019 (x.go:3) MOVQ BP, 8(SP)
0x0018 00024 (x.go:3) LEAQ 8(SP), BP
0x001d 00029 (x.go:3) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (x.go:3) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (x.go:3) FUNCDATA $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (x.go:4) PCDATA $0, $0
0x001d 00029 (x.go:4) PCDATA $1, $0
0x001d 00029 (x.go:4) CALL runtime.printlock(SB)
0x0022 00034 (x.go:4) MOVQ $3, (SP)
0x002a 00042 (x.go:4) CALL runtime.printint(SB)
0x002f 00047 (x.go:4) CALL runtime.printnl(SB)
0x0034 00052 (x.go:4) CALL runtime.printunlock(SB)
0x0039 00057 (x.go:5) MOVQ 8(SP), BP
0x003e 00062 (x.go:5) ADDQ $16, SP
0x0042 00066 (x.go:5) RET
0x0043 00067 (x.go:5) NOP
0x0043 00067 (x.go:3) PCDATA $1, $-1
0x0043 00067 (x.go:3) PCDATA $0, $-1
0x0043 00067 (x.go:3) CALL runtime.morestack_noctxt(SB)
0x0048 00072 (x.go:3) JMP 0
...
Директивы FUNCDATA и PCDATA содержат информацию для использования сборщиком мусора; они вводятся компилятором.
Чтобы увидеть, что помещается в двоичный файл после компоновки, используйте go tool objdump:
$ go build -o x.exe x.go
$ go tool objdump -s main.main x.exe
TEXT main.main(SB) /tmp/x.go
x.go:3 0x10501c0 65488b0c2530000000 MOVQ GS:0x30, CX
x.go:3 0x10501c9 483b6110 CMPQ 0x10(CX), SP
x.go:3 0x10501cd 7634 JBE 0x1050203
x.go:3 0x10501cf 4883ec10 SUBQ $0x10, SP
x.go:3 0x10501d3 48896c2408 MOVQ BP, 0x8(SP)
x.go:3 0x10501d8 488d6c2408 LEAQ 0x8(SP), BP
x.go:4 0x10501dd e86e45fdff CALL runtime.printlock(SB)
x.go:4 0x10501e2 48c7042403000000 MOVQ $0x3, 0(SP)
x.go:4 0x10501ea e8e14cfdff CALL runtime.printint(SB)
x.go:4 0x10501ef e8ec47fdff CALL runtime.printnl(SB)
x.go:4 0x10501f4 e8d745fdff CALL runtime.printunlock(SB)
x.go:5 0x10501f9 488b6c2408 MOVQ 0x8(SP), BP
x.go:5 0x10501fe 4883c410 ADDQ $0x10, SP
x.go:5 0x1050202 c3 RET
x.go:3 0x1050203 e83882ffff CALL runtime.morestack_noctxt(SB)
x.go:3 0x1050208 ebb6 JMP main.main(SB)
Читайте также:
- Клиент Go для Elasticsearch: конфигурация и кастомизация
- Клиент Go для Elasticsearch: кодирование и декодирование полезной нагрузки JSON
- Клиент Go для Elasticsearch: массовая индексация
Комментариев нет:
Отправить комментарий