Brainfuck compiler to x86_64 on linux by C and python

Brainfuckのコンパイラです。C版とPython版があります。x86_64のアセンブリコードに落とします。

### C

```bfs.c
#include    <stdio.h>
#include    <stdlib.h>
static int loopstack[1000];
static int lsp=0;

void lsout() {
    for (int i=0;i<lsp;i++)
        printf("%d_",loopstack[i]);
}

void main(int argc,char *argv[]) {
    FILE *fp;
    int  c,lf;
    if (argc!=2) {
        fprintf(stderr,"Usage: bfs <file>\n");
        exit(1);
    }
    fp=fopen(argv[1],"rt");
    if (fp==NULL) {
        fprintf(stderr,"File open error.\n");
        exit(1);
    }

	printf("\t.section .text\n");
	printf("\t.globl _start\n");
    printf("_start:\n");
    printf("\tmovabs $_my_data,%%rsi\n");
    printf("\tmov\t$1,%%edx\n");

    lsp=0;
    lf='[';
    while((c=fgetc(fp))!=EOF) {
        switch (c) {
            case '>':
                printf("\tinc\t%%rsi\n");
                break;
            case '<':
                printf("\tdec\t%%rsi\n");
                break;
            case '+':
				printf("\tincb\t(%%rsi)\n");
                break;
            case '-':
				printf("\tdecb\t(%%rsi)\n");
                break;
            case '.':
				printf("\tmov\t%%edx,%%eax\n");
				printf("\tmov\t%%edx,%%ebx\n");
				printf("\tsyscall\n");
                break;
            case ',':
				printf("\txor\t%%eax, %%eax\n");
				printf("\txor\t%%ebx, %%ebx\n");
				printf("\tsyscall\n");
                break;
            case '[':
                if (lf==']')
                    loopstack[(lsp-1)]++;
                else
                    loopstack[lsp++]=1;
                lf='[';
                printf("\tjmp LE"); lsout(); printf("\n");
                printf("LB"); lsout(); printf(":\n");
                break;
            case ']':
                if (lf==']')
                    lsp--;
                lf=']';
                printf("LE"); lsout(); printf(":\n");
	            printf("\tcmp\t%%dh,(%%rsi)\n");
                printf("\tjne\tLB"); lsout(); printf("\n");
                break;
            default:
            }
    }
    fclose(fp);
    printf("\tmov\t$1,%%eax\n");
    printf("\txor\t%%ebx,%%ebx\n");
    printf("\tint $0x80\n");
    printf(".section .bss\n");
    printf("_my_data: .zero 65536\n");
    exit(0);
}
```
コンパイル:`cc bfs.c -o bfs`
brainfuckコードのコンパイル:`./bfs file.bf >file.s`
アセンブル:`as file.s -o file.o`
リンク:`ld file.o -o file.exe`
実行:`./file.exe`

### Python版

```bfs.py
#!/usr/bin/python3
import sys

def lsout(loopstack):
    return str(loopstack).replace(', ','_').replace('[','').replace(']','')

def main():
    if len(sys.argv)!=2:
        print(f"Usage: {sys.argv[0]} <file>")
        return
    print("    .section .text")
    print("    .globl _start")
    print("_start:")
    print("    movabs $_my_data,%rsi")
    print("    mov    $1,%edx")

    f=open(sys.argv[1],"rt")
    loopstack=[]
    lf='['
    for s in f:
        for c in s:
            if c=='>':
                print("    inc     %rsi")
            elif c=='<':
                print("    dec     %rsi")
            elif c=='+':
                print("    incb     (%rsi)")
            elif c=='-':
                print("    decb     (%rsi)")
            elif c=='.':
                print("    mov     %edx,%eax")
                print("    mov     %edx,%ebx")
                print("    syscall")
            elif c==',':
                print("    xor     %eax,%eax")
                print("    xor     %ebx,%ebx")
                print("    syscall")
            elif c=='[':
                if lf==']':
                    loopstack[len(loopstack)-1]+=1
                else:
                    loopstack.append(1)
                lf='['
                print(f"    jmp     LE{lsout(loopstack)}")
                print(f"LB{lsout(loopstack)}:")
            elif c==']':
                if lf==']':
                    loopstack.pop()
                lf=']'
                print(f"LE{lsout(loopstack)}:")
                print("    cmp     %dh,(%rsi)")
                print(f"    jne     LB{lsout(loopstack)}")
    f.close()
    print("    mov     $1,%eax")
    print("    xor     %ebx,%ebx")
    print("    int $0x80")
    print(".section .bss")
    print("_my_data: .zero 65536")

if __name__=='__main__':
    main()
    exit(0)

```

実行権の付与:`chmod +x bfs.py`
brainfuckコードのコンパイル:`./bfs.py file.bf >file.s`
アセンブル:`as file.s -o file.o`
リンク:`ld file.o -o file.exe`
実行:`./file.exe`