AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

汇编分析 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:001087

评论

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

MIT、OpenAI震撼力作!软件测试行业如何迎接未来挑战?

测试人

人工智能 软件测试

研发效能实践之打造高效能团队

思码逸研发效能

研发效能 效能度量 研发效能度量 高效能

鸿蒙保存图片到相册

龙儿筝

人形机器人赛道已挤满车企和自动驾驶行业精英

机器人头条

机器人 人形机器人 具身智能

CleanMyMac有必要买吗?达人深度体验后告诉你答案

阿拉灯神丁

软件包 苹果软件精选 mac系统维护 CleanMyMac X中文

百家号年度盛典:聚焦创作者成长,乘风计划再升级

极客天地

Zilliz落地垂直RAG:为什么说医疗场景中,LLM只是半成品?

Zilliz

LLM rag zilliz cloud

京东商品详情数据接口(H5、APP端)

tbapi

京东API接口 京东商品详情接口

Java Web学生自习管理系统

不在线第一只蜗牛

Java 前端

如何通过电商 API 接口实现智能客服与用户互动?

科普小能手

数据挖掘 数据分析 电商 API 接口 API 测试

焱融 AI 存储荣登 「2024 年度 AI 最佳技术服务商 TOP 10」榜单

焱融科技

AI 全闪存储

由 Mybatis 源码畅谈软件设计(五):ResultMap 的循环引用

京东科技开发者

由 Mybatis 源码畅谈软件设计(七):从根上理解 Mybatis 一级缓存

京东科技开发者

无限制!个人开发者发布Coze扣子智能体到微信小程序教程

Ceelog

研发效能度量的常见指标问题——看什么?不准怎么办?

思码逸研发效能

DevOps 研发效能 效能度量 研发效能度量 思码逸

自学记录鸿蒙API 13:Calendar Kit日历功能从学习到实践

李游Leo

HarmonyOS HarmonyOS NEXT

实力再获认可!焱融 AI 存储 F9000X 荣获中国 IDC 产业创新技术产品奖

焱融科技

人工智能 IDC 智算中心 全闪存储

深度学习的崛起:AI为何如此聪明?

天津汇柏科技有限公司

深度学习 AI 人工智能

设计模式之代理模式:武器附魔之道

京东科技开发者

区块链智能合约的开发流程

北京木奇移动技术有限公司

区块链开发 智能合约开发 软件外包公司

秒验审核流程

MobTech袤博科技

Web3项目开发流程

北京木奇移动技术有限公司

区块链技术 软件外包公司 web3开发

探析同济医院科研一体化平台建设(二):统筹科研项目,促进成果转化

ModelWhale

人工智能 大数据 同济大学

【连载 08】lock锁

FunTester

百剧计划:百度短剧创新引擎,赋能短剧新未来

极客天地

WebGIS开发的详细流程

北京木奇移动技术有限公司

软件外包公司 webgl开发 webGIS开发

四年匠心磨砺,快手系统软件技术创新与领域演进之路

快手技术

编译器 快手 系统软件技术 Java协程

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