当我在五月天假期里还可以的家时,我找到了一个宝藏网站。该门户网站可以在线生成多种语言的汇编代码。有了这个好事,您必须进行一次实验。
很久以前,我写了一个港口转移门,汇编了更多的返回值。在那个时候,我写的时候相对较早。后来,当函数调用GO 1.17时,修改了传递参数。简而言之,在GO1.17之前,该功能参数通过堆栈空间传递。该更改是在GO1.17。在某些平台(AMD64)中进行的,可以使用寄存器传输参数和函数,例如C,C ++。为什么会更改?原因是寄存器更快。尽管内存已经很快,但仍无法与寄存器进行比较。为什么以前没有寄存器,堆栈空间很简单,不考虑不同的平台,架构没有差异。
只需总结两种方法
GO组装基本知识将总结GO组装的基本知识。现在回顾一下以前并不全面的计划9汇编,这并不全面。这与AT&T的汇编有所不同。四个寄存器,只要理解四个寄存器,大会就会被一半理解
汇编的几个术语:
一些登记册
通过堆栈框架的图了解这些寄存器
一般的堆栈框架在图中。图中标记的寄存器基于Callee函数
从数字可以看出,如果Callee函数中没有局部变量,SP硬寄存器和SP伪寄存器指向同一地点
伪-FP寄存器对应于呼叫者函数的帧指针,该指针通常用于访问Callee函数的参数和返回值。PSEUDO-SP堆栈指针对应于当前Callee函数堆栈框架的底部(不包括不包括参数和返回值零件),通常用于定位局部变量。PSEUDO-SP是一个相对特殊的寄存器,因为还有一个带有同名的SP硬件寄存器,并且硬件SP寄存器对应于堆栈的顶部。
在编写Go组装时,您只需要记住区分伪注册和真实注册:伪寄存器通常需要标识符和偏移到前缀。如果没有标识符前缀,它是一个真实的寄存器。例如,(sp),+8(sp)没有标识符前缀为真实的SP寄存器,A(sp)和B+8(sp)具有标识符作为指示伪注册的前缀。
另一点
如果Callee的堆栈空间为0,则呼叫者BP不会被压碎到堆栈中。此时,SP硬件寄存器和伪-FP寄存器指向同一位置。
在组装中,功能的定义
是一个特殊指示,定义功能
是功能的名称
编译器表明,不应插入堆栈切片以检查需要扩展的指示前指令
这两个参数为0是此功能所需的堆栈空间的大小。一般而言,这是本地变量所需的空间。该单元是数字。24是传递参数和函数返回值所需的堆栈空间的大小,并且单元也是位置。
在生成组装和理解这些基本概念后,先前的代码,以查看如何通过组装来传递参数的函数的不同版本
首先通过简单代码查看差异
这是为了告诉编译器不要与此函数的内部连接。这个东西称为GO编译说明。GO还有许多其他说明。它不会在这里扩展。C ++明确指定为内联合。Go是告诉编译器不要进行内部联盟。
首先查看1.16下的装配代码
有很多代码,只注意下图中的标签
众所周知,该函数可以通过SP寄存器的偏移完成传递参数。在这里应注意,此写作看起来像是使用伪-SP寄存器。实际上,使用了硬件SP寄存器。
同样,在函数调用之前,该值将放置在堆栈的指定位置中。
看看最新的1.18
在1.18汇编代码中,参数未通过堆栈空间传递。相反,操作是直接通过寄存器完成的,并且返回值直接放置在寄存器中。
寄存器的数量具有上限。如果传递的参数数量超过了寄存器的上限,它将处理什么?
相应的组件
可以通过汇编可以看到寄存器将首先使用。如果寄存器不够,则将使用堆栈空间。
手写组件通过手写代码验证每个寄存器的位置。我使用的GO版本是1.14.13,因此参数编号使用堆栈空间。在main.go文件中
将主要函数定义为整个程序的入口,并声明功能。添加功能的具体实现是编写编写的。在main.go的主目录中创建add_amd64.s的文件。
使用硬BP寄存器
使用Go Run。命令查看程序执行的结果。
此时的堆栈框架显示在图中
因为添加功能堆栈空间为0,所以伪-SP寄存器不会压碎到堆栈中。伪-SP寄存器和硬件SP寄存器指向同一位置。
使用伪-SP寄存器
为了区分比较,请在此时将添加功能的堆栈空间设置为16,然后使用伪-SP寄存器获取值。执行结果如下:
此时的堆栈空间显示在图中
使用FP寄存器代码如下:
结果:
描述仍然正确。目前,堆栈空间尚未更改,与上面相同。
此时,您应该能够理解每个寄存器的相对位置:当Callee堆栈空间不是0时
当Callee堆栈空间为0时
可以通过上面的代码找到对组件的简单分析,并且手写组件的代码和代码有些不同。在函数的前面,该功能的前面将有一个段落。实际上,这是由编译器自动插入的函数。该指令将一次调用此功能的特定角色。空间可以动态扩展,因此在调用函数之前检查当前的堆栈空间。其他功能是检查当前的coroutine需要抓住当前的coroutine。模式。如何判断是否需要扣押Coroutine?背景Coroutine将定期扫描当前操作的当前操作。如果发现Coroutine长时间运行,它将被标记为主要状态。此扫描的时间点在功能调用期间完成。
不同类型的参数传输结构
只需发布关键装配代码
通过结构时,仅传递结构的内容。
传递结构指针
汇编
可以看出,通过指针,结构的第一个元素的地址已传递。
如果是一个空的结构
汇编
可以看出,当通过空气结构通过时,相当于不过。由于空气结构的空间为0,因此编译器被忽略。
终于暂时思考了很多,首先写这些,然后再想一想