From bb1d68b5519d0f30db927a0d388af69c9220a1f8 Mon Sep 17 00:00:00 2001 From: hopehook Date: Sat, 1 Jan 2022 11:45:16 +0800 Subject: [PATCH 1/4] fix: unrecognized instruction "NO_LOCAL_POINTERS" --- ch3-asm/ch3-06-func-again.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ch3-asm/ch3-06-func-again.md b/ch3-asm/ch3-06-func-again.md index 7cf5a85..7c3d633 100644 --- a/ch3-asm/ch3-06-func-again.md +++ b/ch3-asm/ch3-06-func-again.md @@ -289,6 +289,8 @@ L_END: Go语言的编译器在生成函数的机器代码时,会在开头插入一小段代码。因为sum函数也需要深度递归调用,因此我们删除了NOSPLIT标志,让汇编器为我们自动生成一个栈扩容的代码: ``` +#include "funcdata.h" + // func sum(n int) int TEXT ·sum(SB), $16-16 NO_LOCAL_POINTERS From a5be4d7bd6aa2c61eca9f0fa03da359937831b9d Mon Sep 17 00:00:00 2001 From: hopehook Date: Sat, 1 Jan 2022 13:39:34 +0800 Subject: [PATCH 2/4] fix typo --- ch3-asm/ch3-07-hack-asm.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch3-asm/ch3-07-hack-asm.md b/ch3-asm/ch3-07-hack-asm.md index 05f1aa7..fab1685 100644 --- a/ch3-asm/ch3-07-hack-asm.md +++ b/ch3-asm/ch3-07-hack-asm.md @@ -4,9 +4,9 @@ ## 3.7.1 系统调用 -系统调用是操作系统为外提供的公共接口。因为操作系统彻底接管了各种底层硬件设备,因此操作系统提供的系统调用成了实现某些操作的唯一方法。从另一个角度看,系统调用更像是一个RPC远程过程调用,不过信道是寄存器和内存。在系统调用时,我们向操作系统发送调用的编号和对应的参数,然后阻塞等待系统调用地返回。因为涉及到阻塞等待,因此系统调用期间的CPU利用率一般是可以忽略的。另一个和RPC地远程调用类似的地方是,操作系统内核处理系统调用时不会依赖用户的栈空间,一般不会导致爆栈发生。因此系统调用是最简单安全的一种调用了。 +系统调用是操作系统对外提供的公共接口。因为操作系统彻底接管了各种底层硬件设备,因此操作系统提供的系统调用成了实现某些操作的唯一方法。从另一个角度看,系统调用更像是一个RPC远程过程调用,不过信道是寄存器和内存。在系统调用时,我们向操作系统发送调用的编号和对应的参数,然后阻塞等待系统调用地返回。因为涉及到阻塞等待,因此系统调用期间的CPU利用率一般是可以忽略的。另一个和RPC地远程调用类似的地方是,操作系统内核处理系统调用时不会依赖用户的栈空间,一般不会导致爆栈发生。因此系统调用是最简单安全的一种调用了。 -系统调用虽然简单,但是它是操作系统对外的接口,因此不同的操作系统调用规范可能有很大地差异。我们先看看Linux在AMD64架构上的系统调用规范,在`syscall/asm_linux_amd64.s`文件中有注释说明: +系统调用虽然简单,但是它是操作系统对外的接口,因此不同的操作系统调用规范可能有很大的差异。我们先看看Linux在AMD64架构上的系统调用规范,在`syscall/asm_linux_amd64.s`文件中有注释说明: ```go // From 0e4b674b0f0a213786af4cab88c8dbeb07b4d4f0 Mon Sep 17 00:00:00 2001 From: hopehook Date: Sat, 1 Jan 2022 23:07:37 +0800 Subject: [PATCH 3/4] fix typo --- ch3-asm/ch3-02-arch.md | 2 +- ch3-asm/ch3-03-const-and-var.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ch3-asm/ch3-02-arch.md b/ch3-asm/ch3-02-arch.md index 0089dda..8a86b8a 100644 --- a/ch3-asm/ch3-02-arch.md +++ b/ch3-asm/ch3-02-arch.md @@ -61,7 +61,7 @@ - 算术相关(ADD/SUB/BUMP+/BUMP-) - 跳转指令: 如果是条件跳转,寄存器中必须要有数据 -主流的处理器也有类似的指令。除了基本的算术和逻辑预算指令外,再配合有条件跳转指令就可以实现分支、循环等常见控制流结构了。 +主流的处理器也有类似的指令。除了基本的算术和逻辑运算指令外,再配合有条件跳转指令就可以实现分支、循环等常见控制流结构了。 下图是某一层的任务:将输入数据的0剔除,非0的数据依次输出,右边部分是解决方案。 diff --git a/ch3-asm/ch3-03-const-and-var.md b/ch3-asm/ch3-03-const-and-var.md index 4760450..b2472dd 100644 --- a/ch3-asm/ch3-03-const-and-var.md +++ b/ch3-asm/ch3-03-const-and-var.md @@ -44,7 +44,7 @@ DATA ·Name+8(SB)/8,$6 ## 3.3.2 全局变量 -在Go语言中,变量根据作用域和生命周期有全局变量和局部变量之分。全局变量是包一级的变量,全局变量一般有着较为固定的内存地址,声明周期跨越整个程序运行时间。而局部变量一般是函数内定义的的变量,只有在函数被执行的时间才被在栈上创建,当函数调用完成后将回收(暂时不考虑闭包对局部变量捕获的问题)。 +在Go语言中,变量根据作用域和生命周期有全局变量和局部变量之分。全局变量是包一级的变量,全局变量一般有着较为固定的内存地址,生命周期跨越整个程序运行时间。而局部变量一般是函数内定义的的变量,只有在函数被执行的时间才被在栈上创建,当函数调用完成后将回收(暂时不考虑闭包对局部变量捕获的问题)。 从Go汇编语言角度来看,全局变量和局部变量有着非常大的差异。在Go汇编中全局变量和全局函数更为相似,都是通过一个人为定义的符号来引用对应的内存,区别只是内存中存放是数据还是要执行的指令。因为在冯诺伊曼系统结构的计算机中指令也是数据,而且指令和数据存放在统一编址的内存中。因为指令和数据并没有本质的差别,因此我们甚至可以像操作数据那样动态生成指令(这是所有JIT技术的原理)。而局部变量则需在了解了汇编函数之后,才能通过SP栈空间来隐式定义。 From 00b2182f45c714a8fe82aecafa9b732c797c910c Mon Sep 17 00:00:00 2001 From: hopehook Date: Sat, 1 Jan 2022 23:41:59 +0800 Subject: [PATCH 4/4] =?UTF-8?q?Feat:=20=E6=B1=87=E7=BC=96=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E9=83=BD=E6=B2=A1=E6=9C=89=E8=BF=99=E4=B8=AA=20s=20?= =?UTF-8?q?=E5=A4=B4=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch3-asm/ch3-06-func-again.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch3-asm/ch3-06-func-again.md b/ch3-asm/ch3-06-func-again.md index 7c3d633..9c4f265 100644 --- a/ch3-asm/ch3-06-func-again.md +++ b/ch3-asm/ch3-06-func-again.md @@ -361,7 +361,7 @@ func asmFunTwiceClosureBody() int 然后用Go汇编语言实现以上三个辅助函数: -```s +``` #include "textflag.h" TEXT ·ptrToFunc(SB), NOSPLIT, $0-16