Skip to content

Instantly share code, notes, and snippets.

@pasberth
Created September 3, 2012 15:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pasberth/3610144 to your computer and use it in GitHub Desktop.
Save pasberth/3610144 to your computer and use it in GitHub Desktop.
アセンブリで brainfuck 書いてみた

たぶん Mountain Lion でしか動きません。自分の環境でしかテストしてない

compile:

$ as -o brainfuck.o brainfuck.s && ld -o brainfuck -e main brainfuck.o

run:

$ ./brainfuck -e "+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+."

;; -f でファイルから読み取れるようにしようと思ったけど力つきた

/* *\
** __________ brainfuck.s **
** / -. \ __/ ____ Maybe running only on **
** / `-'_/ /_ / __/ Mac OS X Mountain Lion **
** / /_) ) __/__ __\ \ http://twitter.com/pasberth **
** /____ / / /_//____/ **
\* /__/ */
.comm memory, 30000
.text
.globl main
invalidOptionMsg: .ascii "invalid flag: "
main:
popq %rax // %rax = argc
cmp $1, %rax // if (argc == 1)
jz exit // goto exit;
cmp $2, %rax // else if (argc != 2)
jnz parseOption // goto parseOption;
jmp execProgram // else goto execProgram;
parseOption:
checkHyphen:
movq 8(%rsp), %rax // %rax = argv[1]
movb 0(%rax), %al // %al = *argv[1]
cmp $'-, %al // if (*argv[1] != '-')
jnz invalidOption // goto invalidOption;
extractOption:
movq 8(%rsp), %rax // %rax = argv[1]
movb 1(%rax), %al // %al = argv[1][1]
cmpb $'f, %al // from file
jz fromFile
cmpb $'e, %al // eval expr
jz evalExpr
jmp invalidOption
invalidOption:
/* for example, if the input is "./brainfuck -x a", *
* does print "invalid flag: x" and exit program. */
movq $0x2000004, %rax
movq $1, %rdi
leaq invalidOptionMsg(%rip), %rsi
movq $14, %rdx
syscall
movq 8(%rsp), %rbx // %rbx = argv[1]
leaq 1(%rbx), %rax // %rax = argv[1] + 1
movq %rax, %rsi
movq $0x2000004, %rax
movq $1, %rdi
movq $1, %rdx
syscall
jmp exit
fromFile:
jmp exit
evalExpr:
push %rax
movq 24(%rsp), %rax
call brainfuck
pop %rax
jmp exit
execProgram:
jmp exit
exit:
movq $0x2000001, %rax
movq $0, %rdi
syscall
ret
/*
* %rax: brainfuck program.
*/
brainfuck:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
movq %rax, %rbx
pushq %rax
movq %rbx, %rax
leaq memory(%rip), %rbx
pushq %rbx
pushq %rax
/*
* 16(%rsp) :
* 8(%rsp) : pointer to a memory
* 0(%rsp) : brainfuck program.
*/
eval:
movq (%rsp), %rax
cmp $0, %rax
jz done
movb (%rax), %al
cmpb $0, %al
jz done
cmpb $',, %al
jz getCh
cmpb $'., %al
jz putCh
cmpb $'+, %al
jz incrVal
cmpb $'-, %al
jz declVal
cmpb $'<, %al
jz decrPtr
cmpb $'>, %al
jz incrPtr
cmpb $'[, %al
jz begWhile
cmpb $'], %al
jz endWhile
jmp next
done:
popq %rax
popq %rbx
popq %rax
popq %rbx
leave
ret
next:
incb (%rsp)
jmp eval
getCh:
pushq %rbx
pushq %rax // input buffer
movq $0x2000003, %rax
movq $0, %rdi
movq %rsp, %rsi
movq $1, %rdx
syscall
movq (%rsp), %rax
movq 24(%rsp), %rbx
movq %rax, (%rbx)
popq %rax
popq %rbx
jmp next
putCh:
pushq %rbx
pushq %rax
movq 24(%rsp), %rbx
movq $0x2000004, %rax
movq $1, %rdi
movq %rbx, %rsi
movq $1, %rdx
syscall
popq %rax
popq %rbx
jmp next
incrVal:
movq 8(%rsp), %rbx
incb (%rbx)
jmp next
declVal:
movq 8(%rsp), %rbx
decb (%rbx)
jmp next
incrPtr:
incb 8(%rsp)
jmp next
decrPtr:
decb 8(%rsp)
jmp next
begWhile:
movq 8(%rsp), %rbx
movb (%rbx), %al
cmp $0, %al
jz begWhileSkip
jmp begWhileDo
begWhileSkip:
incb (%rsp)
movq (%rsp), %rax
movb (%rax), %al
cmpb $0, %al
jz done
cmpb $'], %al
jnz begWhileSkip
jmp next
begWhileDo:
jmp next
endWhile:
movq 8(%rsp), %rbx
movb (%rbx), %al
cmp $0, %al
jz endWhileBreak
jmp endWhileContinue
endWhileBreak:
jmp next
endWhileContinue:
movq $0, %rbx
endWhileContinue1:
decb (%rsp)
movq (%rsp), %rax
movb (%rax), %al
cmpb $0, %al
jz done
cmpb $'], %al
jz endWhileContinueNestBeg
cmpb $'[, %al
jnz endWhileContinue1
cmpq $0, %rbx
jnz endWhileContinueNestEnd
jmp next
endWhileContinueNestBeg:
inc %rbx
jmp endWhileContinue1
endWhileContinueNestEnd:
dec %rbx
jmp endWhileContinue1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment