AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

汇编分析 golang 循环

  • 2020-02-26
  • 本文字数:1737 字

    阅读完需:约 6 分钟

汇编分析golang循环

今天小编为大家分享一篇关于 Golang 循环汇编分析的文章,文章中介绍了 golang 循环的汇编层面的处理,通过分析,我们可以更了解循环的实现。希望能对大家有所帮助。

循环是编程中很强大的一个概念,而且非常容易处理。但是,必须将其翻译成机器可理解的基本指令。它的编译方式也可能影响标准库中的其他组件。让我们开始分析一下范围循环。

循环汇编

范围循环可以迭代数组,切片或通道。下面函数展示了,对分片进行循环并将数字相加:


func main() {   l := []int{9, 45, 23, 67, 78}   t := 0
for _, v := range l { t += v }
println(t)}
复制代码


执行 go tool compile -S main.go 可以转储生成汇编代码,下面为范围循环的相关代码。


0x0041 00065 (main.go:4)   XORL   AX, AX0x0043 00067 (main.go:4)   XORL   CX, CX
0x0045 00069 (main.go:7) JMP 820x0047 00071 (main.go:7) MOVQ ""..autotmp_5+16(SP)(AX*8), DX0x004c 00076 (main.go:7) INCQ AX0x004f 00079 (main.go:8) ADDQ DX, CX0x0052 00082 (main.go:7) CMPQ AX, $50x0056 00086 (main.go:7) JLT 710x0058 00088 (main.go:11) MOVQ CX, "".t+8(SP)
复制代码


我们把指令分为两部分:初始化及循环本身。最开始两行指令用来初始化两个寄存器为 0。


0x0041 00065 (main.go:4)   XORL   AX, AX0x0043 00067 (main.go:4)   XORL   CX, CX
复制代码


寄存器 AX 包含循环中的当前位置,而 CX 包含变量 t 的值。下面是带有指令和通用寄存器的直观表示:



该循环指令 JMP 82 开始,表示跳转到指令 82。可以通过第二列来标识此目标指令:



下一条指令 CMPQ AX, $5 表示“比较寄存器 AX 和数值 5”。它实际上是从 AX 中减去寄存器 DX 的值,并将结果存储到另一个寄存器中。现在,可以在下一条指令 JLT 71 中使用该值,该指令表示“如果小于 0,则跳转到指令 71。”下面是更新后的图:



如果条件不满足,则程序将不会跳转执行循环后面的下一条指令。


因此,我们现在有了循环的结构。下面是转换回 Go 的循环:


goto endstart:   ?end:   if i < 5 {      goto start   }
println(t)
复制代码


该循环的主体是缺失的,下面是指令:


0x0047 00071 (main.go:7)   MOVQ   ""..autotmp_5+16(SP)(AX*8), DX0x004c 00076 (main.go:7)   INCQ   AX0x004f 00079 (main.go:8)   ADDQ   DX, CX
复制代码


第一个指令 MOVQ “”…autotmp_5+16(SP)(AX*8), DX 表示“将内存从源移动到目标”。由以下内容组成:


片段 “”…autotmp_5+16(SP) 其中 SP 是堆栈指针(我们当前的内存栈帧),而 autotmp_* 是自动生成的变量名称。


偏移量 8(在 64 位架构上,int 为 8 位)乘以寄存器 AX 的值,即循环中的当前位置。


由寄存器 DX 表示的,目标现在包含循环的当前值。


然后,INCQ 代表“递增”,并将递增循环的当前位置:


循环体的最后一条指令是 ADDQ DX, CX 表示“将 DX 添加到 CX”。之前我们已经看到 DX 包含循环的当前值,而 CX 是包含变量 t 内容的寄存器:



它将一直循环直到循环计数器到达 5。然后,循环之后的指令显示寄存器 CX 将其值移至 t :


0x0058 00088 (main.go:11) MOVQ CX, “”.t+8(SP)


这是处于最终状态的图:



我们还可以在 Go 中完成循环的翻译:


func main() {   l := []int{9, 45, 23, 67, 78}   t := 0   i := 0
var tmp int
goto endstart: tmp = l[i] i++ t += tmpend: if i < 5 { goto start }
println(t)}
复制代码


为这个新程序生成汇编代码,将提供完全相同的输出。

改进

内部转换循环的方式可能会对其他功能(例如 Go 调度程序)产生影响。在 Go 1.10 之前,编译的循环类似于以下代码:


func main() {   l := []int{9, 45, 23, 67, 78}   t := 0   i := 0
var tmp int p := uintptr(unsafe.Pointer(&l[0]))
if i >= 5 { goto end }body: tmp = *(*int)(unsafe.Pointer(p)) p += unsafe.Sizeof(l[0]) i++ t += tmp if i < 5 { goto body }end: println(t)}
复制代码


这种实现方式的问题是,当达到 5 时,指针 p 超过了分配的末尾。这个问题使循环不容易被抢占,因为它的主体不安全。循环编译的优化确保它不会创建任何过去的指针。为准备 Go 调度程序中的非合作式抢占而进行了此改进。


本文转载自 360 云计算公众号。


原文链接:https://mp.weixin.qq.com/s/J37BmlWhEEeuwVnPck0rIA


2020-02-26 23:001056

评论

发布
暂无评论
发现更多内容

做共享电动车找哪家工厂生产电动车?

共享电单车厂家

共享电动车厂家 共享电单车生产 工厂生产电动车 共享电动车找哪家工厂 本铯共享电动车厂家

NFTScan: 蓝筹 NFT 跌幅严重,如何保持竞争力?

NFT Research

文盘Rust -- rust连接oss

TiDB 社区干货传送门

开发语言

简单学习一下 MyBatis 动态SQL使用及原理

做梦都在改BUG

Java mybatis

不服不行!Github爆火的「高并发秒杀顶级教程」,先睹为快

做梦都在改BUG

Java 高并发 秒杀系统

windows下docker的安装与镜像的制作提交

北桥苏

Docker Docker 镜像

小心白蛇!PyPI仓库被持续投放White Snake后门组件

墨菲安全

pypi 开源软件供应链安全

设计原则 — D 依赖反转原则

Lemoon Can

依赖反转原则 设计原则 依赖反转

重磅来袭!微服务的里程碑SpringCloudAlibaba

做梦都在改BUG

Java 架构 微服务 Spring Cloud spring cloud alibaba

OSS云文件列举分页

北桥苏

php OSS 分页 上传 thinkphp

膜拜!阿里内部都在强推的K8S(kubernetes)学习指南,不能再详细了

做梦都在改BUG

Java Kubernetes k8s

PCB如何设计防静电?华秋一文告诉你

华秋电子

2023年报业网络安全等级保护定级流程

行云管家

网络安全 等级保护 报业

phpstorm开发项目中5种常用的使用方法

北桥苏

php PHPStorm

快速地找到任何文件或文件夹:Find Any File Mac版

真大的脸盆

Mac Mac 软件 文件搜索 搜索文件 文件查找工具

ZeroErr 零误框架

西风逍遥游

这套Github上40K+star面试笔记,可以帮你搞定95%以上的Java面试

做梦都在改BUG

Java java面试 Java八股文 Java面试题 Java面试八股文

PHP快速使用RabbitMQ实现项目中部分业务的解耦

北桥苏

php RabbitMQ thinkphp

Avive World算力挖矿系统开发技术

薇電13242772558

算力

从 MySQL 到 Oracle 再到全面 TiDB ,云盛海宏的数据库架构实践

TiDB 社区干货传送门

短信验证 创建应用

MobTech袤博科技

不到1分钟,帮你剪完旅行vlog,火山引擎全新 AI「神器」真的这么绝?

字节跳动技术范儿

字节跳动 算法 计算机视觉 云服务 火山引擎

袋鼠云产品功能更新报告05期|应有尽“优”,数栈一大波功能优化升级!

袋鼠云数栈

大数据 hadoop 数据中台

英特尔 x 波士顿咨询:打造嵌入式安全技术GenAI解决方案,满足企业实际需求

科技之家

方案精讲丨TiDB 在社交场景的解决方案实践

TiDB 社区干货传送门

并发编程-ReentrantLook底层设计

做梦都在改BUG

Java 并发编程 ReentrantLook

PHP高并发高负载下的3种实战场景解决方法

北桥苏

php 高并发优化 thinkphp

汇编分析golang循环_文化 & 方法_360云计算_InfoQ精选文章