• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go 汇编随笔

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Go 汇编小记

  • 学习了 Go 汇编,在内存分布和底层函数调用有了一定理解,对常用概念做个小结

    本文结构

  • 介绍内存、寄存器及相关指令

  • 变量、函数 申明

  • 函数帧内存分布图

  1. 程序代码是通过 CPU 执行相关汇编指令
    运行的。计算机内部布局划分为三个部分,内存寄存器
    指令。本篇内容主要是通过这三个部分介绍 Go 汇编,作为学习总结

  2. Go 内存组成:heap、stack、frame、local、data(read、roread)、text

    • frame: 一个函数对应一个 frame
    • stack: 一个 stack 中至少有一个 frame,管理每个函数(frame)被调用时相关的数据
    • local: 局部变量,一般在函数内定义,只有在函数被执行才会在 stack 上被创建,
      当函数调用完后被回收(进阶:闭包中对局部变量捕获问题)
    • data: 数据段,一般用于存放全局数据,roread 只读数据数据段
    • text: 代码段,用于存储要执行的指令数据,一般是只读
  3. Go 几个常见寄存器:SB、FP、SP、PC

    • SB: Staic Base Pointer,静态内存 的开始地址

    • FP: Frame Pointer,对应函数的帧指针,一般用来访问函数的参数和返回值

    • SP: Stack Pointer,分伪SP真SP

      • 伪 SP:位于当前栈帧(frame)底部,用于定位局部变量 ,形如 tmp-2(SP),即相对与真 SP 地址偏移量
      • 真 SP:位于当前栈帧(frame)顶部,用于定位调用其他函数的 参数 和 返回值
  4. 常见指令:CALL、RET、LEA、PUSH、POP

类别 指令名称 解释
控制流 CMP 比较指令
JMP / JMP-if-x 跳转指令
CALL 调用函数
RET 函数返回
其他 LEA 取地址,将内存地址加载到寄存器
PUSH 压栈
POP 出栈
  • 注意

    • 调用函数时, 被调用函数(callee)的参数和返回值的内存空间必须由调用者(caller)提供
      ,因此函数的局部变量和为调用其他函数准备的栈空间总和就确定了函数帧的大小(暂不考虑栈分裂扩容)
      调用其他函数前,调用方(caller)要选择保存相关寄存器到栈中,并在调用函数返回后选择要恢复的寄存器进行保存

    • 函数的第一个参数和第一个返回值会分别进行一次地址对齐

  1. Go 汇编常见指令
  • 注意:

    • 在汇编中,没有函数类型,GO 自动回收会报错,所以在引用汇编定义的内容前,需要在 go 文件前指定
      变量或函数的类型
    • Go 语言函数的调用参数和返回值均是通过栈传输
  • 变量定义

// symbol: 对应汇编的变量名
// width,该符号对应内存大小,内存宽度必须是 2 的指数倍,单位是字节(byte)
GLOBL symbol(SB), width

  • 变量初始化
// symbol: 对应汇编的变量名,offset(SB),符号开始地址的偏移量
// width:要初始化的内存宽度大小,初始化始必须是 1,2,4,8几个宽度之一,即对应到机器的整数倍,单位是字节(byte)
// value: 变量初始化值,可以是具体值,也可以是一个已经声明变量(symbol)
DATA symbol+offset(SB) /width,value

  • 函数定义
//TEXT 用于定义函数符号
// symbol: 函数名,是包含包路径的,可省略包路径
/** flags:用于指示函数的一些特殊行为,
			NOSPLIT 函数不进行栈分裂,一般用于没有其他调用的叶子函数
			WRAPPER包装函数 ,在panic 或 runtime.caller等某些处理函数帧的地方不会增加函数帧计数
			NEEDCTXT 表示需要一个上下文参数,一般用于闭包函数
*/
//$framesize 表示函数的局部变量需要多大的栈空间,其中包含调用其他函数时准备调用参数的隐式栈空间

TEXT symbol(SB), [flags] $framesize[-argsize]

  1. 函数帧
func main() {
	printsum(a,b)
}

func printsum(a,b int){
	var ret = sum(a,b)
	fmt.Println(ret)
}

func sum(a,b int)int{
	return a + b
}


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Go语言入门(一)特性、安装、环境搭建、第一个程序等发布时间:2022-07-10
下一篇:
【go语言】beego框架基础学习记录发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap