是否可以在Google Go代码中包含内联汇编? [英] Is it possible to include inline assembly in Google Go code?

查看:275
本文介绍了是否可以在Google Go代码中包含内联汇编?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在Google Go代码中包含内联汇编? 解决方案

不支持内联汇编,但是您可以通过C链接使用汇编编写的代码,使用cgo编译并使用导入C,如 gmp.go 。您也可以使用直接与Go兼容的装配样式编写代码,如 asm_linux_amd64.s ,它要求函数名以·开头。



或者,您可以使用我最喜欢的nasm和gccgo。 (请注意,Nasm似乎不支持以·开头的函数)。



以下是一个有效的hello world示例:

hello.asm:

 ;基于来自nasm的hello.asm 

SECTION .data;数据部分
msg:dbHello World,10;要打印的字符串,10 = cr
len:equ $ -msg; $表示这里
; len是一个值,而不是地址

SECTION .text;代码部分

全局go.main.hello;使标签可用于链接器(Go)
go.main.hello:

; ---设置堆栈帧
push rbp;保存旧的基本指针
mov rbp,rsp;使用堆栈指针作为新的基址指针

; ---打印消息
mov edx,len; arg3,要打印的字符串的长度
mov ecx,msg; arg2,指向字符串
的指针mov ebx,1; arg1,在哪写,屏幕
mov eax,4;将sysout命令写入int 80 hex
int 0x80;中断80十六进制,调用内核

; ---删除堆栈帧
mov rsp,rbp;使用基指针作为新的堆栈指​​针
pop rbp;获取旧的基本指针

; ---返回
mov rax,0;错误代码0,正常,没有错误
ret;返回

main.go:

  package main 

func hello();

func main(){
hello()
hello()
}

还有一个方便的Makefile:

  main:main.go hello.o 
gccgo hello.o main.go -o main

hello.o:hello.asm
nasm -f elf64 -o hello.o hello.asm

clean:
rm -rf _obj * .o *〜* .6 * .gch a.out main

我在main.go中调用 hello()两次,只是再次检查hello()是否正确返回。



请注意,在Linux上直接调用中断80h并不被认为是好风格,而写入的调用函数C更具将来证明的功能。还要注意,这是针对64位Linux的程序集,并且不以任何方式,形状或形式与平台无关。



我知道这不是直接回答你的问题,但这是我知道的使用Go的汇编最简单的路线,缺乏内联。如果您真的需要内联,可以编写一个脚本从源文件中提取内联汇编,并按照上述模式进行准备。足够近? :)



Go,C和Nasm的快速示例: gonasm.tgz



更新:更高版本的gccgo需要-g标志,并且只需要main.hello而不是go.main.hello。以下是Go,C和Yasm的更新示例: goyasm.tgz


Is it possible to include inline assembly in Google Go code?

解决方案

There is no support for inline assembly, but you can link with code written in assembly through C, compiling with cgo and using import "C", like in gmp.go. You could alternatively write in a style of assembly that is directly compatible with Go, like in asm_linux_amd64.s, that requires that function names start with "·".

Or, you can use nasm and gccgo, my favorite way so far. (Note that Nasm does not seem to support functions starting with "·").

Here's a working "hello world" example:

hello.asm:

; Based on hello.asm from nasm

    SECTION .data       ; data section
msg:    db "Hello World",10 ; the string to print, 10=cr
len:    equ $-msg       ; "$" means "here"
                ; len is a value, not an address

    SECTION .text       ; code section

global go.main.hello        ; make label available to linker (Go)
go.main.hello:

    ; --- setup stack frame
    push rbp            ; save old base pointer
    mov rbp,rsp   ; use stack pointer as new base pointer

    ; --- print message
    mov edx,len     ; arg3, length of string to print
    mov ecx,msg     ; arg2, pointer to string
    mov ebx,1       ; arg1, where to write, screen
    mov eax,4       ; write sysout command to int 80 hex
    int 0x80        ; interrupt 80 hex, call kernel

    ; --- takedown stack frame
    mov rsp,rbp  ; use base pointer as new stack pointer
    pop rbp      ; get the old base pointer

    ; --- return
    mov rax,0       ; error code 0, normal, no error
    ret         ; return

main.go:

package main

func hello();

func main() {
    hello()
    hello()
}

And a handy Makefile:

main: main.go hello.o
    gccgo hello.o main.go -o main

hello.o: hello.asm
    nasm -f elf64 -o hello.o hello.asm

clean:
    rm -rf _obj *.o *~ *.6 *.gch a.out main

I call hello() twice in main.go, just to double check that hello() returns properly.

Note that calling interrupt 80h directly is not considered good style on Linux, and calling functions written is C is more "future proof". Also note that this is assembly specifically for 64-bit Linux, and is not platform-independent in any way, shape or form.

I know it's not a direct answer to your question, but it's the easiest route I know for using assembly with Go, in lack of inlining. If you really need inlining, it's possible to write a script that extracts inline assembly from source files and prepares it in a way that follows the pattern above. Close enough? :)

Quick example for Go, C and Nasm: gonasm.tgz

Update: Later versions of gccgo needs the -g flag and only "main.hello" is needed instead of "go.main.hello". Here is an updated example for Go, C and Yasm: goyasm.tgz

这篇关于是否可以在Google Go代码中包含内联汇编?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆