Go字符串及字符串拼接的反汇编代码解读

Go字符串及字符串拼接的反汇编代码解读

源代码

package main

func main() {
    s := "hello world"
    s += " go\n"
    print(s)
}

Go版本

jagitch@34c4dd4d4a3e:str-demo$ go version
go version go1.22.2 linux/amd64

运行

jagitch@34c4dd4d4a3e:str-demo$ go run main.go
hello world go

编译

jagitch@34c4dd4d4a3e:str-demo$ go build main.go

反汇编

jagitch@34c4dd4d4a3e:str-demo$ go tool objdump -S -s '^main.main' main
TEXT main.main(SB) /home/coder/workspace/own/jagitch-code/gitee/go-study/go-asm/str-demo/main.go
func main() {
  0x45d120              493b6610                CMPQ SP, 0x10(R14)
  0x45d124              7650                    JBE 0x45d176
  0x45d126              55                      PUSHQ BP
  0x45d127              4889e5                  MOVQ SP, BP
  0x45d12a              4883ec38                SUBQ $0x38, SP
        s += " go\n"
  0x45d12e              31c0                    XORL AX, AX
  0x45d130              488d1d15140100          LEAQ 0x11415(IP), BX
  0x45d137              b90b000000              MOVL $0xb, CX
  0x45d13c              488d3da70a0100          LEAQ 0x10aa7(IP), DI
  0x45d143              be04000000              MOVL $0x4, SI
  0x45d148              e813c7feff              CALL runtime.concatstring2(SB)
  0x45d14d              4889442430              MOVQ AX, 0x30(SP)
  0x45d152              48895c2428              MOVQ BX, 0x28(SP)
        print(s)
  0x45d157              e8e436fdff              CALL runtime.printlock(SB)
  0x45d15c              488b442430              MOVQ 0x30(SP), AX
  0x45d161              488b5c2428              MOVQ 0x28(SP), BX
  0x45d166              e8553ffdff              CALL runtime.printstring(SB)
  0x45d16b              e83037fdff              CALL runtime.printunlock(SB)
}
  0x45d170              4883c438                ADDQ $0x38, SP
  0x45d174              5d                      POPQ BP
  0x45d175              c3                      RET
func main() {
  0x45d176              e885cdffff              CALL runtime.morestack_noctxt.abi0(SB)
  0x45d17b              eba3                    JMP main.main(SB)

解析

  1. CMPQ SP, 0x10(R14) SP减去0x10(R14)的值
  2. JBE 0x45d176 如果上一步的结果小于等于,则跳转到0x45d176处
  3. PUSHQ BP 压入上一个函数的栈帧基址
  4. MOVQ SP, BP 将当前栈顶保存到BP寄存器
  5. SUBQ $0x38, SP SP减去0x38,分配0x38个字节的栈空间
  6. XORL AX, AX 清空AX
  7. LEAQ 0x11415(IP), BX 将"hello world"字符串常量的地址加载到BX
  8. MOVL $0xb, CX 将"hello world"字符串的长度加载到CX
  9. LEAQ 0x10aa7(IP), DI 将" go\n"字符串的地址加载到DI
  10. MOVL $0x4, SI 将" go\n"的长度加载到SI
  11. CALL runtime.concatstring2(SB) 调用concatstring2函数拼接字符串
  12. MOVQ AX, 0x30(SP) AX是concatstring2的第一个返回值,是拼接后的字符串的地址,将其保存到0x30(SP)
  13. MOVQ BX, 0x28(SP) BX是第二个返回值,是拼接后的字符串的长度,保存到0x28(SP)
  14. CALL runtime.printlock(SB) 打印加锁
  15. MOVQ 0x30(SP), AX 将字符串的地址加载到AX
  16. MOVQ 0x28(SP), BX 将字符串的长度加载到BX
  17. CALL runtime.printstring(SB) 打印字符串
  18. CALL runtime.printunlock(SB) 解锁打印
  19. ADDQ $0x38, SP SP加上0x38,回收之前分配的栈空间
  20. POPQ BP 弹出上个函数的BP
  21. RET 返回
  22. CALL runtime.morestack_noctxt.abi0(SB) 增加栈空间
  23. JMP main.main(SB) 跳转到main包的main函数

结论

  1. 字符串常量会保存到一块内存中,使用0x11415(IP)等方式可以找到它的地址

  2. 字符串拼接会调用runtime.concatstring2函数进行拼接

推荐阅读

1. 使用VS Code调试Go程序
2. 使用树梅派搭建Golang、Python、NodeJs的开发服务器
3. Go语言中局部变量的逃逸分析(从汇编的角度)

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gopyer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值