Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

高版本的Go编译器,为什么在使用原生go代码是使用寄存器传参,但是在汇编实现中却使用栈传参?有可能改变这种行为吗? #647

Open
qshuai opened this issue Jul 16, 2024 · 2 comments

Comments

@qshuai
Copy link

qshuai commented Jul 16, 2024

Go version:

go version go1.22.1 linux/amd64
  • 使用go代码实现:
package main

//go:noinline
func add(a, b uint64) uint64 {
	return a + b
}

func main() {
	_ = add(2, 3)
}

指令:使用了寄存器传参(命令: go build add_native.gogo tool objdump -s '^main.' add_native):

TEXT main.add(SB) /root/project/go/src/github.com/qshuai/test/asm/add_native.go
  add_native.go:5	0x45d140		4801d8			ADDQ BX, AX     // 使用寄存器处理参数和返回值
  add_native.go:5	0x45d143		c3			RET

TEXT main.main(SB) /root/project/go/src/github.com/qshuai/test/asm/add_native.go
  add_native.go:8	0x45d160		493b6610		CMPQ SP, 0x10(R14)
  add_native.go:8	0x45d164		761d			JBE 0x45d183
  add_native.go:8	0x45d166		55			PUSHQ BP
  add_native.go:8	0x45d167		4889e5			MOVQ SP, BP
  add_native.go:8	0x45d16a		4883ec10		SUBQ $0x10, SP
  add_native.go:9	0x45d16e		b802000000		MOVL $0x2, AX
  add_native.go:9	0x45d173		bb03000000		MOVL $0x3, BX
  add_native.go:9	0x45d178		e8c3ffffff		CALL main.add(SB)
  add_native.go:10	0x45d17d		4883c410		ADDQ $0x10, SP
  add_native.go:10	0x45d181		5d			POPQ BP
  add_native.go:10	0x45d182		c3			RET
  add_native.go:8	0x45d183		e898cdffff		CALL runtime.morestack_noctxt.abi0(SB)
  add_native.go:8	0x45d188		ebd6			JMP main.main(SB)
  • 使用汇编实现add函数
// go code
package main

//go:noinline
func add(a, b uint64) uint64

func main() {
	_ = add(2, 3)
}

// asm
TEXT ·add(SB), $0-0
  ADDQ BX, AX
  RET

指令:使用栈传参(命令:go buildgo tool objdump -s '^main.' xxx):

TEXT main.main(SB) /root/project/go/src/github.com/qshuai/test/asm/add.go
  add.go:6		0x45d140		493b6610		CMPQ SP, 0x10(R14)
  add.go:6		0x45d144		7632			JBE 0x45d178
  add.go:6		0x45d146		55			PUSHQ BP
  add.go:6		0x45d147		4889e5			MOVQ SP, BP
  add.go:6		0x45d14a		4883ec18		SUBQ $0x18, SP
  add.go:7		0x45d14e		48c7042402000000	MOVQ $0x2, 0(SP)    // 使用栈传参:2
  add.go:7		0x45d156		48c744240803000000	MOVQ $0x3, 0x8(SP)  // 使用栈传参:3
  add.go:7		0x45d15f		90			NOPL
  add.go:7		0x45d160		e81b000000		CALL main.add.abi0(SB)
  add.go:7		0x45d165		450f57ff		XORPS X15, X15
  add.go:7		0x45d169		644c8b3425f8ffffff	MOVQ FS:0xfffffff8, R14
  add.go:8		0x45d172		4883c418		ADDQ $0x18, SP
  add.go:8		0x45d176		5d			POPQ BP
  add.go:8		0x45d177		c3			RET
  add.go:6		0x45d178		e8a3cdffff		CALL runtime.morestack_noctxt.abi0(SB)
  add.go:6		0x45d17d		ebc1			JMP main.main(SB)

TEXT main.add.abi0(SB) /root/project/go/src/github.com/qshuai/test/asm/add_amd64.s
  add_amd64.s:2		0x45d180		4801d8			ADDQ BX, AX  // 这个逻辑就错误了
  add_amd64.s:3		0x45d183		c3			RET
@suqingfa
Copy link

@qshuai 汇编代码和go代码使用的不同的ABI,Go internal ABI specification。汇编代码使用的是ABI0,使用栈传递参数。go代码使用 ABIInternal,怎样传递参数是由编译器决定的,现在的版本使用寄存器传递参数。runtime 的汇编可以使用 ABI Selector 选择汇编代码使用的 ABI,其它的汇编不能够选择 ABI。例如 runtime.mcall 汇编就是使用 ABI0,runtime·mcall

// func mcall(fn func(*g))
TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT, $0-8
	MOVQ	AX, DX	// DX = fn
	...

@changkaiyan
Copy link

changkaiyan commented Nov 24, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants