diff --git a/ch3-asm/ch3-03-const-and-var.md b/ch3-asm/ch3-03-const-and-var.md index f2f19cd..7026c30 100644 --- a/ch3-asm/ch3-03-const-and-var.md +++ b/ch3-asm/ch3-03-const-and-var.md @@ -1,6 +1,6 @@ # 3.3. 常量和全局变量 -程序中的一切变量的初始值都直接或间接地依赖常量或常量表达式生成。在Go语言中很多变量是默认零值初始化的,但是Go汇编中定义的变量最好还是手工通过常量初始化。有了常量之后,就可以定义全局变量,并使用常量组成的表达式初始化全部变量。本节将简单讨论Go汇编语言中常量和全局变量的用法。 +程序中的一切变量的初始值都直接或间接地依赖常量或常量表达式生成。在Go语言中很多变量是默认零值初始化的,但是Go汇编中定义的变量最好还是手工通过常量初始化。有了常量之后,就可以衍生定义全局变量,并使用常量组成的表达式初始化其它各种变量。本节将简单讨论Go汇编语言中常量和全局变量的用法。 ## 常量 @@ -26,12 +26,27 @@ $(3&1)<<2 // == $4 其中常量表达式中运算符的优先级和Go语言保持一致。 +Go汇编语言中的常量其实不仅仅只有编译时常量,还包含运行时常量。比如包中全局的变量和全局函数在运行时地址也是固定不变的,这里地址不会变量的包变量和函数的地址也是一种汇编常量。 + +下面是本章第一节用汇编定义的字符串代码: + +``` +GLOBL ·NameData(SB),$8 +DATA ·NameData(SB)/8,$"gopher" + +GLOBL ·Name(SB),$16 +DATA ·Name+0(SB)/8,$·NameData(SB) +DATA ·Name+8(SB)/8,$6 +``` + +其中`$·NameData(SB)`也是以$美元符号为前缀,因此也可以将它看作是一个常量,它对应的是NameData包变量的地址。在汇编指令中,我们也可以通过LEA指令来获取NameData变量的地址。 + ## 全局变量 -在Go语言中,变量根据作用域和生命周期有全局变量和局部变量之分。全局变量是包一级的变量,全局变量一般有着较为固定的内存地址,声明周期跨越整个程序运行时间。而局部变量一般是函数内定义的的变量,只有在函数被执行的时间才能被创建,当函数完成时将回收(暂时不考虑闭包对局部变量捕获的问题)。 +在Go语言中,变量根据作用域和生命周期有全局变量和局部变量之分。全局变量是包一级的变量,全局变量一般有着较为固定的内存地址,声明周期跨越整个程序运行时间。而局部变量一般是函数内定义的的变量,只有在函数被执行的时间才被在栈上创建,当函数调用完成后将回收(暂时不考虑闭包对局部变量捕获的问题)。 -从Go汇编语言角度来看,全局变量和局部变量也有大的差异。在Go汇编中全局变量和全局函数更为相似,都是通过一个人为定义的符号来引用对应的内存,区别只是内存中存放是数据还是要执行的指令。因为在冯诺伊曼系统结构的计算机中指令也是数据,而且指令和数据存放在统一编址的内存中,因此指令和数据并没有本质的差别——我们甚至可以像操作数据那样动态生成指令。而局部变量则需了解了汇编函数之后,通过SP栈空间来隐式定义。 +从Go汇编语言角度来看,全局变量和局部变量有着非常大的差异。在Go汇编中全局变量和全局函数更为相似,都是通过一个人为定义的符号来引用对应的内存,区别只是内存中存放是数据还是要执行的指令。因为在冯诺伊曼系统结构的计算机中指令也是数据,而且指令和数据存放在统一编址的内存中。因为指令和数据并没有本质的差别,因此我们甚至可以像操作数据那样动态生成指令(这是所有JIT技术的原理)。而局部变量则需在了解了汇编函数之后,才能通过SP栈空间来隐式定义。 ![](../images/ch3-pkg-var-decl-01.ditaa.png)