GO 汇编学习笔记(三)

GO 汇编学习笔记(三) —— 基本语法

​​ GO 汇编学习笔记(一)

GO 汇编学习笔记(二)

GO 汇编学习笔记(三)

GO 汇编学习笔记(四)

GO 汇编学习笔记(五)

  1. 函数概念

    ​ 因为Go汇编语言中,可以也建议通过Go语言来定义全局变量,那么剩下的也就是函数了。只有掌握了汇编函数的基本用法,才能真正算是Go汇编语言入门。本章将简单讨论Go汇编中函数的定义和用法。

  2. 基本语法

    1. 函数标识符通过TEXT汇编指令定义,表示该函数存储在TEXT内存段,TEXT语句后的指令对应函数的实现。

    2. TEXT 本身不关心后面十分有指令,因此TEXT和LABEL定义的符号是类似的,区别只是LABEL是用于跳转标号,但是本质上他们都是通过标识符映射一个内存地址。

    3. 函数的定义的语法如下:TEXT symbol(SB), [flags,] $framesize[-argsize]

      ​ 函数的定义部分由5个部分组成:TEXT指令、函数名、可选的flags标志、函数帧大小和可选的函数参数大小。

      ​ 其中TEXT用于定义函数符号,函数名中当前包的路径可以省略。函数的名字后面是(SB),表示是函数名符号相对于SB伪寄存器的偏移量,二者组合在一起最终是绝对地址。作为全局的标识符的全局变量和全局函数的名字一般都是基于SB伪寄存器的相对地址。标志部分用于指示函数的一些特殊行为,标志在textlags.h文件中定义,常见的NOSPLIT主要用于指示叶子函数不进行栈分裂,framesize部分表示函数的局部变量需要多少栈空间,其中包含调用其它函数时准备调用参数的隐式栈空间。最后是可以省略的参数大小,之所以可以省略是因为编译器可以从Go语言的函数声明中推导出函数参数的大小。

      需要注意的是函数也没有类型,上面定义的Swap函数签名可以下面任意一种格式:

      func Swap(a, b, c int) int
      func Swap(a, b, c, d int)
      func Swap() (a, b, c, d int)
      func Swap() (a []int, d int)
      

      ​ 目前可能遇到的函数标志有NOSPLIT、WRAPPER和NEEDCTXT几个。

      ​ NOSPLIT:不会生成或包含栈分裂代码,这一般用于没有任何其它函数调用的叶子函数,这样可以适当提高性能。

      ​ WRAPPER: 表示这个是一个包装函数,在 panicruntime.caller 等某些处理函数帧的地方不会增加函数帧计数。

      ​ NEEDCTXT: 表示需要一个上下文参数,一般用于闭包函数。

  3. 函数参数和返回值

    ​ 对于函数来说,最重要的是函数对外提供的API约定,包含函数的名称、参数和返回值。当这些都确定之后,如何精确计算参数和返回值的大小是第一个需要解决的问题。

    func Swap(a, b int) (ret0, ret1 int) 对于这个函数,我们可以轻易看出它需要4个int类型的空间,参数和返回值的大小也就是32个字节:TEXT ·Swap(SB), $0-32

    ​ Go汇编中引入了一个FP伪寄存器,表示函数当前帧的地址,也就是第一个参数的地址。因此我们以通过+0(FP)+8(FP)+16(FP)+24(FP)来分别引用a、b、ret0和ret1四个参数。

    ​ 但是在汇编代码中,我们并不能直接以+0(FP)的方式来使用参数。为了编写易于维护的汇编代码,Go汇编语言要求,任何通过FP伪寄存器访问的变量必和一个临时标识符前缀组合后才能有效,一般使用参数对应的变量名作为前缀。

    TEXT ·Swap(SB),NOSPLIT,$0-32
        MOVQ a+0(FP), AX
        MOVQ b+8(FP), BX
        MOVQ BX, ret0+16(FP)
        MOVQ AX, ret0+24(FP)
        RET
    

    img

    //test.go
    func Foo(a bool, b int16) (c []byte)
    //test_amd64.s
    TEXT ·Foo(SB),$0
    	MOVQ a+0(FP),AX
        MOVQ b+2(FQ),BX
        MOVQ c_data+8*1,CX
        MOVQ c_data+8*2,DX
        MOVQ c_data+8*3,DI
        RET
    

    ​ 其中a和b参数之间出现了一个字节的空洞,b和c之间出现了4个字节的空洞。出现空洞的原因是要保证每个参数变量地址都要对齐到相应的倍数。

    img

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值