女主宣言

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

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

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

1

循环汇编

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

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

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

0x0041 00065 (main.go:4)   XORL   AX, AX
0x0043 00067 (main.go:4)   XORL   CX, CX0x0045 00069 (main.go:7)   JMP    82
0x0047 00071 (main.go:7)   MOVQ   ""..autotmp_5+16(SP)(AX*8), DX
0x004c 00076 (main.go:7)   INCQ   AX
0x004f 00079 (main.go:8)   ADDQ   DX, CX
0x0052 00082 (main.go:7)   CMPQ   AX, $5
0x0056 00086 (main.go:7)   JLT    71
0x0058 00088 (main.go:11)  MOVQ   CX, "".t+8(SP)

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

0x0041 00065 (main.go:4)   XORL   AX, AX
0x0043 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 end
start:?
end:if i < 5 {goto start}println(t)

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

0x0047 00071 (main.go:7)   MOVQ   ""..autotmp_5+16(SP)(AX*8), DX
0x004c 00076 (main.go:7)   INCQ   AX
0x004f 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 := 0i := 0var tmp intgoto end
start:tmp = l[i]i++t += tmp
end:if i < 5 {goto start}println(t)
}

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

2

改进

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

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

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

360云计算

由360云平台团队打造的技术分享公众号,内容涉及数据库、大数据、微服务、容器、AIOps、IoT等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

汇编分析golang循环相关推荐

  1. MIPS架构之start.s汇编分析

    一.mips架构通用寄存器命名 二.mips汇编指令操作 1.指令集 2.实例: #example .data array1: .space 12 # declare 12 bytes of stor ...

  2. v-for和v-if同时使用(案例分析:循环最新的前14条数据显示) - 踩坑篇

    Vue官方文档:永远不要把 v-if 和 v-for 同时用在同一个元素上. 官方文档: 避免 v-if 和 v-for 用在一起 阅读上述文档:说明vue不支持二者放到同一个标签中使用 否则真的会失 ...

  3. php循环 跳转语句,golang循环跳转语句

    golang循环跳转语句 跳转语句 goto break continue 三个语法都可以配合标签使用 标签名区分大小写,若不使用会造成编译错误 break与continue配合标签可用于多层循环的跳 ...

  4. R语言|clusterprofile超几何分布富集分析 GO,KEGG富集分析,循环Fisher‘s test

    超几何分布富集分析 GO,KEGG富集分析,循环Fisher's test ID转换 GO KEGG 把KEGG里的geneid转回名称(readable table) 超几何分布以及生成data f ...

  5. 使用dlv分析golang进程cpu占用高问题

    c++通过dbg分析内存和cpu,可能大家都会.本篇主要分析通过delve分析golang程序cpu占用高的问题. delve是golang推荐的专门go语言调试工具,用来替代gdb.golang组织 ...

  6. vc怎么查看c源码的汇编语言,VC++代码的汇编分析(一)

    VC++代码是最接近汇编指令的高级语言,为了更加准确和深刻理解VC++编码中所涉及的很多技术概念和编译器参数的含义,从汇编指令层面进行剖析和解读,有助于开发者更加准确.直观.深刻理解高级语言中很多概念 ...

  7. 定义派生类和继承类(从汇编分析)

    下面我来分析几段继承的类跟大家总结一下前面所说的一些理论知识,这里解释了前面 提供默认构造函数的第二点哦,仔细看 仔细观察地址401090,这里先调用了子类的构造函数,但是原来子类里面并没有构造函数, ...

  8. 汇编语言-008(条件跳转应用 、loopnz 条件循环指令使用 、loopz 条件循环指令使用 、 if语句编写汇编时 、while语句编写汇编时 、循环内的if语句嵌套)

    1: 条件跳转应用,三个数中最小数 .386 .model flat,stdcall.stack 4096 ExitProcess PROTO,dwExitCode:DWORD.data V1 WOR ...

  9. golang java耗内存_分析golang内存占用情况

    性能优化是个永恒的话题,而很多时候我们在作性能优化的时候,往往基于代码上面的直觉,把所有能想到的优化都优化了一遍,不错过任何小的优化点,结果整个代码的逻辑变得极其复杂,而性能上面并没有太大的提升.事实 ...

最新文章

  1. Re:从零开始的机器学习 - Machine Learning(一) 线性回归
  2. 怎样将html转换do,html代码格式化 Reddo的教程
  3. 4 计算机组成原理第三章 存储系统 高速缓冲存储器 虚拟存储器
  4. 10亿!北大获最大一笔校友捐赠
  5. 《剑指Offer》 从上往下打印出二叉树
  6. ajax提交数据被截断的问题
  7. Linux下批量添加用户
  8. esxi时区设置 +8_ESXI安装OpenWRT amp; LEDE软路由部署指南(附镜像下载)
  9. 网站发布后验证码不显示
  10. (实例篇)php 使用redis锁限制并发访问类示例
  11. paip.截屏功能流程说明
  12. 西门子plc电源开关如何选型
  13. Linux串口驱动分析及移植
  14. python云计算有哪些岗位_云计算就业前景怎么样,包括哪些岗位,各岗位主要工作是什么?...
  15. SECS\GEM RMS系统OEE定义
  16. [编程实例]360漏洞修复(绿色版)制作器 v1.0
  17. 华硕bios更改固态硬盘启动_华硕bios怎么设置固态硬盘为第一启动项
  18. 《勇者名录》11.19正式上线链游玩家|休闲养肝、探索大陆
  19. 连接到另外计算机要用户名,连接局域网电脑需要用户名密码
  20. C++题目:海伦公式

热门文章

  1. 求两等长升序序列的中位数
  2. wake on lan
  3. MyBatis由浅入深学习总结之一:MyBatis入门案例
  4. mysql批量用trim限定_mybatis中批量更新sql语句,trim、foreach标签,varchar定义理解
  5. mos管电路_三极管和MOS管原来这样用,混用代价高,电路设计中需谨慎
  6. python安装扩展常用的工具是_Python 安装扩展库常用的是 _______ 工具_学小易找答案...
  7. vue.set的用法
  8. 20165231 2017-2018-2 《Java程序设计》第8周学习总结
  9. 关于Mysql的错误:No query specified
  10. OSChina 周二乱弹 ——胸大的烦恼!