因为只是玩一玩,所以走的路线是:用C写代码,把C编译成AT&T格式汇编,把AT&T格式转换成plan9格式,在golang中调用plan9汇编。
c代码
函数
在clib/c/add.c中:
int add(int a, int b){ //实现一个两个整形相加的简单函数
return a + b;
}
编译
用clang编译C代码。注意:一定要用clang,且一定要用x86的处理器,苹果的M1不行。
clang -mno-red-zone -fno-asynchronous-unwind-tables -fno-builtin -fno-exceptions \
-fno-rtti -fno-stack-protector -nostdlib -O3 -msse4 -mavx -mno-avx2 -DUSE_AVX=1 \
-DUSE_AVX2=0 -S add.c -o add.s
删除不必要的内容
add.s的内容为:
.text
.file "add.c"
.globl add # -- Begin function add
.p2align 4, 0x90
.type add,@function
add: # @add
# %bb.0:
# kill: def $esi killed $esi def $rsi
# kill: def $edi killed $edi def $rdi
leal (%rdi,%rsi), %eax
retq
.Lfunc_end0:
.size add, .Lfunc_end0-add
# -- End function
.ident "clang version 10.0.1"
.section ".note.GNU-stack","",@progbits
.addrsig
我们只需要add函数,因此删除add函数以外的代码:
add: # @add
# %bb.0:
# kill: def $esi killed $esi def $rsi
# kill: def $edi killed $edi def $rdi
leal (%rdi,%rsi), %eax
retq
转换为plan9汇编
安装工具
这个工具可以把AT&T汇编转换成plan9汇编:
- 要安装python3.8版本,低于这个版本无法使用
- 安装依赖的库:
pip install --upgrade git+https://github.com/Maratyszcza/PeachPy
- python脚本的使用方法为:python3 asm2asm.py 目的路径/add.s 源路径/add.s
准备go函数的定义文件
在 clib/add.go 中写入:
package clib
//go:nosplit
//go:noescape
//goland:noinspection GoUnusedParameter
func _add(a int, b int) (ret int)
为了便于导出这个函数,还可以增加导出的文件: clib/export.go
package clib
func AddInt(a int, b int) int {
return _add(a, b)
}
执行转换
cd clib/c
python3 asm2asm.py ../add.s add.s
然后在 clib 目录生成了文件:add.s add_subr.go
调用
在上层目录建立文件go.mod:
module github.com/ahfuzhang/example
go 1.18
入口文件:main.go
package main
import (
"fmt"
"github.com/ahfuzhang/example/clib"
)
func main() {
fmt.Println(clib.AddInt(1, 2))
}
整体目录结构为:
example
clib
add.s
add.go
add_subr.go
export.go
c
add.c
add.s
main.go
go.mod
运行:
go run main.go
结果为3,成功了!
have fun!