mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
commit
3ab24e5d9b
@ -121,7 +121,7 @@ bool类型的内存大小为1个字节。并且汇编中定义的变量需要手
|
||||
|
||||
## int型变量
|
||||
|
||||
所有的整数类型均有类似的定义的方式,比较大的差异是整数类型的内存大学和整数是否是有符号。下面是声明的int32和uint32类型变量:
|
||||
所有的整数类型均有类似的定义的方式,比较大的差异是整数类型的内存大小和整数是否是有符号。下面是声明的int32和uint32类型变量:
|
||||
|
||||
```go
|
||||
var int32Value int32
|
||||
@ -145,13 +145,13 @@ DATA ·uint32Value(SB)/4,$0x01020304 // 第1-4字节
|
||||
|
||||
## float型变量
|
||||
|
||||
Go汇编语言通用无法取区分变量是否是浮点数类型,之上相关的浮点数机器指令会将变量当作浮点数处理。Go语言的浮点数遵循IEEE754标准,有float32单精度浮点数和float64双精度浮点数之分。
|
||||
Go汇编语言通常无法取区分变量是否是浮点数类型,与之相关的浮点数机器指令会将变量当作浮点数处理。Go语言的浮点数遵循IEEE754标准,有float32单精度浮点数和float64双精度浮点数之分。
|
||||
|
||||
IEEE754标准中,最高位1bit为符号位,然后是指数位(指数为采用移码格式表示),然后是有效数部分(其中小数点左边的一个bit位被省略)。下图是IEEE754中float32类型浮点数的bit布局:
|
||||
|
||||

|
||||
|
||||
IEEE754浮点数还有一些奇妙的特性:比如有正负两个0;除了无穷大和无穷小还有inf非数;同时如果两个浮点数如果有序那么bit对应的整数也是有序的。
|
||||
IEEE754浮点数还有一些奇妙的特性:比如有正负两个0;除了无穷大和无穷小Inf还有非数NaN;同时如果两个浮点数有序那么bit对应的整数也是有序的。
|
||||
|
||||
下面是在Go语言中先声明两个浮点数(如果没有在汇编中定义变量,那么声明的同时也会定义变量)。
|
||||
|
||||
@ -171,7 +171,7 @@ GLOBL ·float64Value(SB),$8
|
||||
DATA ·float64Value(SB)/4,$0x01020304 // bit 方式初始化
|
||||
```
|
||||
|
||||
我们在上一节精简的算术指令中都是针对整数,如果要通过整数指令的处理浮点数加减法必须根据浮点数的运算规则进行:先对齐小数点,然后进行整数加减法,最后再对结果进行归一化并处理精度舍入问题。
|
||||
我们在上一节精简的算术指令中都是针对整数,如果要通过整数指令处理浮点数的加减法必须根据浮点数的运算规则进行:先对齐小数点,然后进行整数加减法,最后再对结果进行归一化并处理精度舍入问题。
|
||||
|
||||
## string类型变量
|
||||
|
||||
@ -184,7 +184,7 @@ type reflect.StringHeader struct {
|
||||
}
|
||||
```
|
||||
|
||||
在amd64环境中StringHeader有16个字节大写,因此我们先在Go代码声明字符串比阿里,然后在汇编中定义一个16字节大小的变量:
|
||||
在amd64环境中StringHeader有16个字节大小,因此我们先在Go代码声明字符串变量,然后在汇编中定义一个16字节大小的变量:
|
||||
|
||||
```go
|
||||
var helloworld string
|
||||
@ -262,7 +262,7 @@ GLOBL ·ch(SB),$8 // var ch chan int
|
||||
DATA ·ch+0(SB)/8,$0
|
||||
```
|
||||
|
||||
在runtime包其实为汇编提供了一些辅助函数。比如在汇编中可以通过runtime.makemap和runtime.makechan内部函数来创建map和chan变量。辅助函数的签名如下:
|
||||
其实在runtime包中为汇编提供了一些辅助函数。比如在汇编中可以通过runtime.makemap和runtime.makechan内部函数来创建map和chan变量。辅助函数的签名如下:
|
||||
|
||||
```go
|
||||
func makemap(mapType *byte, hint int, mapbuf *any) (hmap map[any]any)
|
||||
@ -276,7 +276,7 @@ func makechan(chanType *byte, size int) (hchan chan any)
|
||||
|
||||
Go语言的标识符可以由绝对的包路径加标识符本身定位,因此不同包中的标识符即使同名也不会有问题。Go汇编是通过特殊的符号来表示斜杠和点符号,因为这样可以简化汇编器词法扫描部分代码的编写,只要通过字符串替换就可以了。
|
||||
|
||||
下面是汇编中常见的几种标识符的使用方式(通用也适用于函数标识符):
|
||||
下面是汇编中常见的几种标识符的使用方式(通常也适用于函数标识符):
|
||||
|
||||
```
|
||||
GLOBL ·pkg_name1(SB),$1
|
||||
@ -284,7 +284,7 @@ GLOBL main·pkg_name2(SB),$1
|
||||
GLOBL my/pkg·pkg_name(SB),$1
|
||||
```
|
||||
|
||||
此外,Go汇编中可以可以定义仅当前文件可以访问的私有标识符(类似C语言中文件内static修饰的变量),以`<>`为后缀名:
|
||||
此外,Go汇编中可以定义仅当前文件可以访问的私有标识符(类似C语言中文件内static修饰的变量),以`<>`为后缀名:
|
||||
|
||||
```
|
||||
GLOBL file_private<>(SB),$1
|
||||
@ -292,7 +292,7 @@ GLOBL file_private<>(SB),$1
|
||||
|
||||
这样可以减少私有标识符对其它文件内标识符命名的干扰。
|
||||
|
||||
此外,Go汇编语言还在"textflag.h"文件定义了一些标志。其中用于变量的标志有个DUPOK、RODATA和NOPTR几个。DUPOK表示该变量对应的标识符可能有多个,在链接时只选择其中一个即可(一般用于合并相同的常量字符串,减少重复数据占用的空间)。RODATA标志表示将变量定义在只读内存段,因此后续任何对此变量的修改操作将导致异常(panic也无法捕获)。NOPTR则表示此变量的内部不含指针数据,让垃圾回收器忽略对该变量的扫描。如果变量已经在Go代码中声明过的话,Go编译器会自动分析出该变量是否包含指针,这种时候可以不用手写NOPTR标志。
|
||||
此外,Go汇编语言还在"textflag.h"文件定义了一些标志。其中用于变量的标志有DUPOK、RODATA和NOPTR几个。DUPOK表示该变量对应的标识符可能有多个,在链接时只选择其中一个即可(一般用于合并相同的常量字符串,减少重复数据占用的空间)。RODATA标志表示将变量定义在只读内存段,因此后续任何对此变量的修改操作将导致异常(panic也无法捕获)。NOPTR则表示此变量的内部不含指针数据,让垃圾回收器忽略对该变量的扫描。如果变量已经在Go代码中声明过的话,Go编译器会自动分析出该变量是否包含指针,这种时候可以不用手写NOPTR标志。
|
||||
|
||||
下面是通过汇编来定义一个只读的int类型的变量:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user