Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to include inline assembly in Go code?

Is it possible to include inline assembly in Go code?

This blog post shows compiling Go to a separate .s file and editing it, but not inline asm as part of a Go function like many C compilers support.

like image 359
Ton van den Heuvel Avatar asked Jun 01 '10 15:06

Ton van den Heuvel


People also ask

What is inline assembly code?

In computer programming, an inline assembler is a feature of some compilers that allows low-level code written in assembly language to be embedded within a program, among code that otherwise has been compiled from a higher-level language such as C or Ada.

Is inline assembly useful?

Inline Assembly is useful for in-place optimizations, and access to CPU features not exposed by any libraries or the operating system. For example, some applications need strict tracking of timing.

Does GCC support inline assembly?

GCC provides two forms of inline asm statements. A basic asm statement is one with no operands (see Basic Asm), while an extended asm statement (see Extended Asm) includes one or more operands.

Does rust support inline assembly?

Rust provides support for inline assembly via the asm! macro. It can be used to embed handwritten assembly in the assembly output generated by the compiler.


2 Answers

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

like image 95
Alexander Avatar answered Sep 20 '22 09:09

Alexander


There is no facility in the Go programming language to support in-line assembler language code, and there are no plans to do so. Go does support linking to routines written in assembler and C. There is an experimental feature which adds SWIG support to Go.

like image 44
peterSO Avatar answered Sep 19 '22 09:09

peterSO