Assembly 这就是Golang执行多重任务的方式吗?
不久前有人问Golang实际上是如何在语句中交换变量的,比如Assembly 这就是Golang执行多重任务的方式吗?,assembly,go,Assembly,Go,不久前有人问Golang实际上是如何在语句中交换变量的,比如A,b=b,A 为了回答这个问题,我拿出了我的Golang编译器,戴上我的思考帽,精心设计了这个问题。所以问题应该是独立的,为了简洁起见,我的答案是: 要了解编译器如何生成本机代码,我们需要了解 它生成的汇编代码,由 链接器 我写了一个小围棋程序来帮助解决这个问题: package main import "fmt" func main() { fmt.Println(myfunction()) } func myfunct
A,b=b,A
为了回答这个问题,我拿出了我的Golang编译器,戴上我的思考帽,精心设计了这个问题。所以问题应该是独立的,为了简洁起见,我的答案是:
要了解编译器如何生成本机代码,我们需要了解
它生成的汇编代码,由
链接器
我写了一个小围棋程序来帮助解决这个问题:
package main
import "fmt"
func main() { fmt.Println(myfunction()) }
func myfunction() []int {
a, b := 10, 5
b, a = a, b
return []int{a, b}
}
使用go-tool compile-S>swap.S
,我找到了这四行,它们对应于第一行
Go代码中的两行myfunction
(注意这是我的64位代码
机器;输出将在其他架构(如32位)上有所不同
看一下,我们可以看到汇编程序使用间接方式来处理这些值
当程序运行时,CPU足够智能,可以看到发生了什么
并使用寄存器避免覆盖现有值
我对(英特尔)x86汇编知之甚少,因此获得了6票,我的回答得到了接受和3票
Golang assembly的四条生产线实际上在做什么?我的回答正确吗
我问这个问题是因为我链接到的内容不是很详尽
a, b := 10, 5
b, a = a, b
0x0028 00040 (swap.go:10) MOVQ $10, CX ; CX = 10
0x002f 00047 (swap.go:10) MOVQ $5, AX ; AX = 5
0x0036 00054 (swap.go:11) MOVQ CX, "".b+16(SP) ; b = CX or *(SP+16) = CX
0x003b 00059 (swap.go:11) MOVQ AX, "".a+24(SP) ; a = AX or *(SP+24) = CX
CX
、AX
和SP
是寄存器a
和b
分别是SP+24和SP+16堆栈上的变量。它将常量10和5加载到CPU寄存器中,然后将寄存器存储到为变量a
和b
保留的堆栈位置
这相当于:
CX := 10
AX := 5
b := CX
a := AX
注意:半优化编译器应将其优化为直接将常量存储到堆栈位置的代码:
b := 10
a := 5
或者更好地完全消除变量:
return []int{5, 10}
我不知道那个奇怪的ass语法是什么意思,但在分解后它变成了
mov rcx,10\mov rax,5\mov[rsp+16],rcx\mov[rsp+24],rax
(这对于64位代码来说几乎是合理的,但它浪费了mov immediate上无用的REX.W前缀,只需要一个微小的立即数)@harold它是go-asm,而不是x86
return []int{5, 10}