Подтвердить что ты не робот

Можно ли включить встроенную сборку в код Google Go?

Можно ли включить встроенную сборку в код Google Go?

4b9b3361

Ответ 1

Нет поддержки встроенной сборки, но вы можете ссылаться на код, написанный в сборке через C, компиляцию с помощью cgo и использование import "C", как в gmp.go. Вы можете в качестве альтернативы писать в стиле сборки, который напрямую совместим с Go, как в asm_linux_amd64.s, который требует, чтобы имена функций начинались с "·".

Или, вы можете использовать nasm и gccgo, мой любимый способ до сих пор. (Обратите внимание, что Nasm, похоже, не поддерживает функции, начинающиеся с "·" ).

Здесь приведен рабочий пример "привет мир":

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()
}

И удобный 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

Я вызываю hello() дважды в main.go, просто чтобы проверить, правильно ли hello() возвращается.

Обратите внимание, что вызов прерывания 80h напрямую не считается хорошим стилем в Linux, а вызывающие функции, написанные, являются C более "будущим доказательством". Также обратите внимание, что это сборка специально для 64-битного Linux и не имеет никакой зависимости от платформы, формы или формы.

Я знаю, что это не прямой ответ на ваш вопрос, но это самый простой маршрут, который я знаю для использования сборки с Go, при отсутствии инкрустирования. Если вам действительно нужна инкрустация, можно написать script, который извлекает встроенную сборку из исходных файлов и подготавливает ее таким образом, который следует за шаблоном выше. Достаточно близко?:)

Быстрый пример для Go, C и Nasm: gonasm.tgz

Обновление:. В более поздних версиях gccgo нужен флаг -g, а вместо "go.main.hello" требуется только "main.hello". Вот обновленный пример для Go, C и Yasm: goyasm.tgz

Ответ 2

В языке программирования Go нет возможности поддерживать встроенный код языка ассемблера, и нет никаких планов сделать это. Go поддерживает привязку к подпрограммам, написанным в ассемблере и C. Существует экспериментальная функция, которая добавляет поддержку SWIG для перехода.

Ответ 4

Нет, вы не можете, но легко обеспечить реализацию сборки только одной функции с помощью компилятора go. Нет необходимости использовать "Импорт C" для использования сборки.

Взгляните на пример из математической библиотеки:

http://golang.org/src/pkg/math/abs.go: функция Abs объявлена ​​в этом файле go. (Существует также реализация abs в go в этом файле, но это не экспортируется, так как имеет имя в нижнем регистре.)

package math

// Abs returns the absolute value of x.
//
// Special cases are:
//  Abs(±Inf) = +Inf
//  Abs(NaN) = NaN
func Abs(x float64) float64

Затем в http://golang.org/src/pkg/math/abs_amd64.s Abs реализован для 64-разрядного файла в этом файле:

// func Abs(x float64) float64
TEXT ·Abs(SB),NOSPLIT,$0
    MOVQ   $(1<<63), BX
    MOVQ   BX, X0 // movsd $(-0.0), x0
    MOVSD  x+0(FP), X1
    ANDNPD X1, X0
    MOVSD  X0, ret+8(FP)
    RET

Ответ 5

Пропуск оптимизации в стандартном компиляторе Go (то есть: 8g + 8l, а не gccgo) в основном работает с необработанными инструкциями в двоичной форме. В настоящее время нет способа (он не реализован) для компилятора, чтобы отличать сборку, сгенерированную компилятором, из встроенного в сборку кода сборки - this - основная причина, по которой компилятор Go не разрешает встроенную сборка. Другими словами, компилятор не поддерживает встроенную сборку из-за архитектуры компилятора.

Конечно, в самом языке Go нет ничего, что могло бы помешать другим реализациям языка Go (то есть: другим компиляторам Go) поддерживать поддержку встроенной сборки. Встроенная сборка - это решение, специфичное для компилятора - оно мало связано с самим языком Go.

В любом случае встроенная сборка небезопасна, потому что она не может быть проверена на корректность с помощью системы типа Go. Кажется, что лучше реализовать любую функцию, которая требует использования встроенной сборки на языке C, и вызвать функцию C из Go.