前言
下班忘把没读完的 inside the c++ object model 带回去
还好包里有本备用的 go, 简单看了一下前面基础部分
感觉就是, 很”新颖 + 轻巧”, 有很多新的概念和工具, 抛弃了一些沉重的”包袱”
试了一下用例, 看了一下汇编
1 2 3 4 5 6 7
| 1 package main 2 3 import "fmt" 4 5 func main() { 6 fmt.Printf("hello, world\n") 7 }
|
汇编:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 1 # command-line-arguments 2 "".main STEXT size=88 args=0x0 locals=0x48 3 0x0000 00000 (/test/go/t.go:5) TEXT "".main(SB), $72-0 // 非常友好地给我加上了对应的源码信息 4 0x0000 00000 (/test/go/t.go:5) MOVQ (TLS), CX 5 0x0009 00009 (/test/go/t.go:5) CMPQ SP, 16(CX) 6 0x000d 00013 (/test/go/t.go:5) JLS 81 7 0x000f 00015 (/test/go/t.go:5) SUBQ $72, SP // 这里应该是在开辟栈帧 8 0x0013 00019 (/test/go/t.go:5) MOVQ BP, 64(SP) // 栈顶保存了 bp 指针 9 0x0018 00024 (/test/go/t.go:5) LEAQ 64(SP), BP // 重置 bp 10 0x001d 00029 (/test/go/t.go:5) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) // gc ? garbage collection? 11 0x001d 00029 (/test/go/t.go:5) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) 12 0x001d 00029 (/test/go/t.go:5) FUNCDATA $3, gclocals·9fb7f0986f647f17cb53dda1484e0f7a(SB) // 看不懂 = = 13 0x001d 00029 (/test/go/t.go:6) PCDATA $2, $1 14 0x001d 00029 (/test/go/t.go:6) PCDATA $0, $0 // 还是看不懂 = = 15 0x001d 00029 (/test/go/t.go:6) LEAQ go.string."hello, world\n"(SB), AX // 加载字符串文本, 者很方便, 我直接可以看到字符串 16 0x0024 00036 (/test/go/t.go:6) PCDATA $2, $0 17 0x0024 00036 (/test/go/t.go:6) MOVQ AX, (SP) 18 0x0028 00040 (/test/go/t.go:6) MOVQ $13, 8(SP) // 应该是指字符串长度 19 0x0031 00049 (/test/go/t.go:6) MOVQ $0, 16(SP) // 后续参数数量? 20 0x003a 00058 (/test/go/t.go:6) XORPS X0, X0 // 单精度异或? 21 0x003d 00061 (/test/go/t.go:6) MOVUPS X0, 24(SP) // 代码中没有用到单精度浮点数, 为什么会有这个指令? 22 0x0042 00066 (/test/go/t.go:6) CALL fmt.Printf(SB) // 调用 // 这样的格式很清晰 23 0x0047 00071 (/test/go/t.go:7) MOVQ 64(SP), BP // 返还 bp 24 0x004c 00076 (/test/go/t.go:7) ADDQ $72, SP // 重置栈顶 25 0x0050 00080 (/test/go/t.go:7) RET // 结束 26 0x0051 00081 (/test/go/t.go:7) NOP 27 0x0051 00081 (/test/go/t.go:5) PCDATA $0, $-1 28 0x0051 00081 (/test/go/t.go:5) PCDATA $2, $-1 29 0x0051 00081 (/test/go/t.go:5) CALL runtime.morestack_noctxt(SB) // 运行时的什么? 30 0x0056 00086 (/test/go/t.go:5) JMP 0
|
FUNCDATA 我怀疑和垃圾回收有关, PCDATA 意义不明 (网上查了一下, 都和垃圾回收有关)
我尝试过添加一个参数, 以用作 fmt.Println(), 但是我并未在代码中找到任何有关参数的信息
仅仅只有一句看起来和那个参数有关
1 2 3
| LEAQ ""..autotmp_0+64(SP), AX // 就是这句话 PCDATA $2, $0 MOVQ AX, 16(SP)
|
而且我差点忽略的一点是, 这里参数的传递是用栈
顺便, 我在文件的末尾找到了这些信息, 看起来像是某种标记
1 2 3 4 5 6 7 8
| 213 gclocals·69c1753bd5f81501d95132d08af04464 SRODATA dupok size=8 214 0x0000 02 00 00 00 00 00 00 00 ........ 215 gclocals·568470801006e5c0dc3947ea998fe279 SRODATA dupok size=10 216 0x0000 02 00 00 00 02 00 00 00 00 02 .......... 217 gclocals·9fb7f0986f647f17cb53dda1484e0f7a SRODATA dupok size=10 218 0x0000 02 00 00 00 01 00 00 00 00 01 .......... 219 gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8 220 0x0000 01 00 00 00 00 00 00 00 ........
|
我再次使用了变量存储值的形式, 然后我的数字能够正常看见了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 0x0034 00052 (/test/go/t.go:7) MOVQ $100, 8(SP) // 我的数字在这里 0x003d 00061 (/test/go/t.go:7) CALL runtime.convT2E64(SB) 0x0042 00066 (/test/go/t.go:7) MOVQ 16(SP), AX 0x0047 00071 (/test/go/t.go:7) PCDATA $2, $2 0x0047 00071 (/test/go/t.go:7) MOVQ 24(SP), CX 0x004c 00076 (/test/go/t.go:7) MOVQ AX, ""..autotmp_1+64(SP) 0x0051 00081 (/test/go/t.go:7) PCDATA $2, $0 0x0051 00081 (/test/go/t.go:7) MOVQ CX, ""..autotmp_1+72(SP) 0x0056 00086 (/test/go/t.go:7) PCDATA $2, $1 0x0056 00086 (/test/go/t.go:7) LEAQ go.string."hello, world\n%d"(SB), AX 0x005d 00093 (/test/go/t.go:7) PCDATA $2, $0 0x005d 00093 (/test/go/t.go:7) MOVQ AX, (SP) 0x0061 00097 (/test/go/t.go:7) MOVQ $15, 8(SP) 0x006a 00106 (/test/go/t.go:7) PCDATA $2, $1 0x006a 00106 (/test/go/t.go:7) LEAQ ""..autotmp_1+64(SP), AX 0x006f 00111 (/test/go/t.go:7) PCDATA $2, $0 0x006f 00111 (/test/go/t.go:7) MOVQ AX, 16(SP) 0x0074 00116 (/test/go/t.go:7) MOVQ $1, 24(SP) 0x007d 00125 (/test/go/t.go:7) MOVQ $1, 32(SP) 0x0086 00134 (/test/go/t.go:7) CALL fmt.Printf(SB) // 但是在调用之前, 我并没看到我的数字被加载了, 为什么? // 我唯一比较怀疑的是那个 CALL runtime.convT2E64(SB)
|
好吧, 我的数据再度丢失了, 我甚至不知道它是如何被传过去的…
summary
go的汇编基于 plan 9(一个新的操作系统), 感觉到了新的技术和观点
并且它也更加友好, 我明显觉得看它的汇编会更轻松一些
(除了那个 PCDATA, FUNCDATA, 和那个已经被我跟丢的变量)
emmm… 很不错, 觉得自己听了别人的建议, 去学新的语言
而不学现在看起来很强大, 但是已经很老了的 java 是一个正确的决定