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