1
0
mirror of https://github.com/chai2010/advanced-go-programming-book.git synced 2025-05-30 17:37:31 +00:00

ch3-02: 增加图片

This commit is contained in:
chai2010 2018-06-15 14:09:43 +08:00
parent 97bfb64bb1
commit f6133016e5

View File

@ -86,6 +86,10 @@ X86其实是是80X86的简称后面三个字母包括Intel 8086、80286
很多汇编语言的教程都会强调汇编语言是不可移植的。严格来说很多汇编语言在不同的CPU类型、或不同的操作系统环境、或不同的汇编工具链下是不可移植的。而这种不可移植性正是汇编语言普及的一个极大的障碍。虽然CPU指令集的差异是导致不好移植的较大因素但是汇编语言的相关工具链对此也有不可推卸的责任。而源自Plan9的Go汇编语言对此做了一定的改进首先Go汇编语言在相同CPU架构上是完全一致的也就是屏蔽了操作系统的差异同时Go汇编语言将一些基础并且类似的指令抽象为相同名字的伪指令从而减少不同CPU架构下汇编代码的差异当然寄存器名字和数量的差异是一直存在的。本节的目的也是找出一个较小的精简指令集以简化Go汇编语言学习的目的。
下面是X86/AMD架构图
![](../images/ch3-arch-amd64-01.ditaa.png)
寄存器是CPU中最重要的资源每个要处理的内存数据原则上需要先放到寄存器中才能由CPU处理同时寄存器中处理完的结果需要再存入内存。X86中除了状态寄存器和指令指令两个特殊的寄存器外还有AX、BX、CX、DX、SI、DI、BP、SP几个通用寄存器。在X86-64中又增加了八个以R8-R15方式命名的通用寄存器。因为历史的原因R0-R7并不是通用寄存器它们只是X87开始引入的MMX指令专有的寄存器。在通用寄存器中BP和SP是两个比较特殊的寄存器其中BP用于记录当前函数帧的开始位置和函数调用相关的指令会隐式地影响SP的值SP则对应当前栈指针的位置和栈相关的指令会隐式地影响SP的值。
X86是一个极其复杂的系统有人统计x86-64中指令有将近一千个之多。不仅仅如此X86中的很多单个指令的功能也非常强大比如有论文证明了仅仅一个MOV指令就可以构成一个图灵完备的系统。以上这是两种极端情况太多的指令和太少的指令都不利于汇编程序的编写。通用的基础机器指令大概可以分为数据传输指令、算术运算和逻辑运算指令、控制流指令等几类。因此我们将尝试精简出一个X86-64指令集以便于Go汇编语言的学习。
@ -126,3 +130,13 @@ X86是一个极其复杂的系统有人统计x86-64中指令有将近一千
为了简单我们省略了位运算指令很多高级指令。完整的X86指令在 https://github.com/golang/arch/blob/master/x86/x86.csv 文件定义。同时Go汇编还正对一些指令定义了别名具体可以参考这里 https://golang.org/src/cmd/internal/obj/x86/anames.go 。
## Go汇编中的伪寄存器
Go汇编为了简化汇编代码的编写引入了PC、FP、SP、SB四个伪寄存器。四个伪寄存器和X86/AMD64的内存和寄存器的相互关系如下图
![](../images/ch3-arch-amd64-02.ditaa.png)
在AMD64环境伪PC寄存器其实是IP指令计数器寄存器的别名。伪FP寄存器对应的是函数的帧指针一般用来访问函数的参数和返回值。伪SP栈指针对应的是当前函数栈帧的底部不保护参数和返回值部分一般用于定位局部变量。伪SP是一个比较特殊的寄存器因为还存在一个同名的SP真寄存器。真SP寄存器对应的是栈的顶部一般用于定位调用其它函数的参数和返回值。
当需要区分伪寄存器和真寄存器的时候只需要记住一点:伪寄存器一般需要一个标识符和偏移量为前缀,如果没有标识符前缀则是真寄存器。比如`(SP)``+8(SP)`没有标识符前缀为真SP寄存器`a(SP)``b+8(SP)`有标识符为前缀表示伪寄存器。