I have written a program in x86 assembly (Intel syntax/MASM) that interprets brainfuck code that is fed to it via an interactive console and prints the final stack to stdout. Note that it does not include an implementation for the `,` command, but everything else has been implemented. The idea is that it presents the user with a prompt where they can enter their code; when the user hits `Enter`, it evaluates it and then dumps the resultant cell state to the console. While the cell state is maintained between prompt entries, the pointer position is not.

It looks like this:

```
$++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
Hello World!

0 0 72 100 87 33 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
--------------------------------------------------
$>>[.>]
HdW!

0 0 72 100 87 33 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
--------------------------------------------------
$++++++++[>++++++++<-]>+.
A
0 65 72 100 87 33 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
--------------------------------------------------

```

This is my first major foray into assembly, so I'm mainly looking for general tips, such as:

* Which registers I should be using in particular cases
* When I should be using RAM and when I should be using registers
* Ways that the code could be simplified

```none
.386
.model flat,stdcall
.stack 4096

include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib

ExitProcess proto,dwExitCode:dword

.data
bfsrc BYTE 200 dup(0) ; buffer to store source code
bfcells BYTE 100 dup(0) ; 100-byte data array size for now
loopStack DD 5 dup(0) ; stores the position of the first instruction in the current loop. Maximum of 5 nested loops.
charBuf BYTE 5 dup(0) ; buffer for when we are dumping numbers
newline BYTE 10,0 ; ASCII 10 is \n
prompt BYTE "$",0 ; input prompt string
hr BYTE 50 dup('-'),0 ; fake horizontal rule
space BYTE ' ',0

.code

EvalBf proc
    start:
    ; print the prompt and then read input into the source array
    invoke StdOut, addr prompt
    invoke StdIn, addr bfsrc,200

    ; exit if input is empty
    cmp bfsrc,0
    je exit

    mov eax,0 ; eax is BF data pointer
    mov ebx,0 ; ebx is BF source pointer
    mov ecx,0 ; ecx is loop depth

    processInstruction:

    ; jump according to current source char
    cmp BYTE PTR bfsrc[ebx], '+'
    je plus

    cmp BYTE PTR bfsrc[ebx], '-'
    je minus

    cmp BYTE PTR bfsrc[ebx], '>'
    je fwd

    cmp BYTE PTR bfsrc[ebx], '<'
    je back

    cmp BYTE PTR bfsrc[ebx], '['
    je open

    cmp BYTE PTR bfsrc[ebx], ']'
    je close

    cmp BYTE PTR bfsrc[ebx], '.'
    je dot

    ; By default, skip instruction if we haven't caught it
    jmp processNextInstruction

    plus:
    inc BYTE PTR bfcells[eax]
    jmp processNextInstruction

    minus:
    dec BYTE PTR bfcells[eax]
    jmp processNextInstruction

    fwd:
    inc eax
    jmp processNextInstruction

    back:
    dec eax
    jmp processNextInstruction

    open:
    ; push the current source position
    ; onto the loop stack
    mov loopStack[ecx*4],ebx
    inc ecx
    jmp processNextInstruction

    close:
    dec ecx
    cmp BYTE PTR bfcells[eax], 0
    ; break out of loop if data cell is 0
    je processNextInstruction
    ; pop the innermost loop position and
    ; set it as the next instruction
    mov ebx,loopStack[ecx*4]
    inc ecx
    jmp processNextInstruction

    dot:
    ; transfer current cell value into char buffer through dl
    mov dl, BYTE PTR bfcells[eax]
    mov BYTE PTR charBuf[0], dl
    ; follow the character with null to terminate the string
    mov BYTE PTR charBuf[1],0
    ; save the registers we need to maintain so that stdout doesn't break anything
    push eax
    push ecx
    ; print generated string
    invoke StdOut, addr charBuf
    pop ecx
    pop eax
    jmp processNextInstruction

    processNextInstruction:
    inc ebx
    ; we're finished if we have hit the end of the input
    cmp BYTE PTR bfsrc[ebx], 0
    je done
    jmp processInstruction

    done:
    ; loop through every value in the BF data array and print it
    invoke StdOut, addr newline
    mov eax, 0
    printNext:
    ; the data array is 100 cells long, so stop looping when we hit cell 100
    cmp eax, 100
    jge reset

    ; save value in eax onto the stack
    push eax

    ; convert cell value to string and store it in the character buffer
    invoke dwtoa, BYTE PTR bfcells[eax], addr charBuf

    ; print the buffer, followed by a space
    invoke StdOut, addr charBuf
    invoke StdOut, addr space

    ; restore and increment value of eax
    pop eax
    inc eax
    jmp printNext

    ; when processing is complete, go back to the beginning and take new input
    reset:
    invoke StdOut, addr newline
    invoke StdOut, addr hr
    invoke StdOut, addr newline
    jmp start

    exit:
    invoke ExitProcess,0
EvalBf endp
end EvalBf

```