👌

golangでのbrainfuckソースをx86_64アセンブリに落とすコンパイラ[FreeBSD版]

に公開

LinuxとFreeBSDは、システムコールの仕方が違うので、修正しました。

標準出力にアセンブリファイルが出力されるので、
go run bfs.go <file.bf> >out.sとして実行して下さい。

out.sはasでアセンブルできるので、
as out.s -o out.oとして、アセンブリファイルをアセンブル、

ld out.o -o outでリンク。

./out で実行して下さい。

package main

import (
    "fmt"
    "os"
    "io"
)

var (
    lf int ='['
    loopstack=[]int{}
)

func lsout(loopstack [] int) {
    for i:=0;i<len(loopstack);i++ {
        fmt.Printf("%d_",loopstack[i])
    }
}

func main() {
    if len(os.Args)!=2 {
        fmt.Println("Usage: go run bfs.go file.bf >out.s")
        return
    }
    fmt.Println("\t.section .text");
    fmt.Println("\t.globl _start");
    fmt.Println("_start:");
    fmt.Println("\tmovabs\t$_my_data,%rsi");


    file,err := os.Open(os.Args[1])
    byteData,err:=io.ReadAll(file)
    _ =err

    for idx:=0;idx<len(byteData);idx++ {
        switch byteData[idx] {
        case '>':
            fmt.Println("\tinc\t%rsi")
        case '<':
            fmt.Println("\tdec\t%rsi")
        case '+':
            fmt.Println("\tincb\t(%rsi)")
        case '-':
            fmt.Println("\tdecb\t(%rsi)")
        case '.':
	    fmt.Println("\tmov\t$4,%rax")
     	    fmt.Println("\tmov\t$1,%rdi")
	    fmt.Println("\tmov\t$1,%rdx")
	    fmt.Println("\tsyscall")
        case ',':
            fmt.Println("\tmov\t$3,%rax")
	    fmt.Println("\tmov\t$1,%rdi")
	    fmt.Println("\tmov\t$1,%rdx")
	    fmt.Println("\tsyscall\n")
        case '[':
            if lf==']' {
                loopstack[len(loopstack)-1]+=1
            } else {
                loopstack = append(loopstack,1)
            }
            lf='['
            fmt.Print("LB")
            lsout(loopstack)
            fmt.Println(":")
	    fmt.Println("\tcmpb\t$0,(%rsi)")
            fmt.Print("\tje     LE")
            lsout(loopstack)
            fmt.Println("")
        case ']':
            if lf==']' {
                loopstack=loopstack[:len(loopstack)-1]
            }
            lf=']'
            fmt.Print("\tjmp\tLB")
            lsout(loopstack)
            fmt.Println("")
            fmt.Print("LE")
            lsout(loopstack)
            fmt.Println(":")
        default:
        }
    }

    fmt.Println("\tmov\t$1,%rax")
    fmt.Println("\txor\t%rdi,%rdi")
    fmt.Println("\tsyscall")
    fmt.Println(".section .bss")
    fmt.Println("_my_data: .zero 65536")
}

Discussion