.intel_syntax noprefix .global _start .data welcome: .ascii "Welcome to Brainfuck by cat, written in ASM(GNU)!\nMax char: 65536(incl LF)!\nAllocating memory...\n\0" msg2: .ascii "Clearing buffer...\n\0" msg3: .ascii "Reading code...\n\0" msg4: .ascii "Interpreting...\n\0" error_msg_no_path: .ascii "You must specify a path as first argument!!\nAborting!\n\0" .text _start: mov rdi, 1 mov rsi, offset welcome call write # Is file specified? cmp qword ptr [rsp], 1 jle error_no_path mov rdi, [rsp+16] # rsp is argc, rsp+8 is argv[0] call open_fd mov rbx, rax # FD # Allocate memory mov rdi, code_max_size call brk_alloc mov r12, rax # Code heap mov rdi, max_size call brk_alloc mov r13, rax # Text buffer mov rdi, max_size call brk_alloc mov r14, rax # Cells mov rdi, 1 mov rsi, offset msg2 call write # Clear the space mov rdi, r12 mov rsi, code_max_size call clear_heap_block mov rdi, r13 mov rsi, max_size call clear_heap_block mov rdi, r14 mov rsi, max_size call clear_heap_block mov rdi, 1 mov rsi, offset msg3 call write # Read from file mov rdi, rbx mov rsi, r12 mov rdx, code_max_size call read mov rdi, 1 mov rsi, offset msg4 call write # Execution call process_commands # Writing result mov rdi, 1 mov rsi, r13 call write # Exiting procedures mov rdi, rbx call close_fd xor rdi, rdi call exit error_no_path: mov rdi, 1 mov rsi, offset error_msg_no_path call write mov rdi, 1 call exit # r10 text pointer # r11 code pointer # r12 code # r13 text # r14 cell # r15 cell pointer process_commands: xor r11, r11 xor r15, r15 mov r10, r13 process_loop: mov r8b, [r12+r11] # Get char call process_symbol inc r11 cmp r8b, 0 jne process_loop ret # r8b = char process_symbol: cmp r8b, 43 # + je process_inc cmp r8b, 45 # - je process_dec cmp r8b, 60 # < je process_back cmp r8b, 62 # > je process_forw cmp r8b, 46 # . je process_prnt cmp r8b, 44 # , je process_inpt cmp r8b, 91 # [ je process_loop_start cmp r8b, 93 # ] je process_loop_end ret # Ret's here return to process_loop not process_symbol due to Jcc process_inc: inc byte ptr [r14+r15] ret process_dec: dec byte ptr [r14+r15] ret # you can't go below or above allocated memory process_forw: cmp r15, max_size je 1f inc r15 1: ret process_back: cmp r15, 0 je 1f dec r15 1: ret process_prnt: mov r9b, [r14+r15] mov byte ptr [r10], r9b inc r10 ret process_inpt: mov rdi, r14 add rdi, r15 mov rsi, rdi # char* xor rdi, rdi # fd mov rdx, 1 # size call read ret # In stack it is # A = Address to loop back # C = Cell to check # AC AC AC AC AC AC AC <- pop here process_loop_start: pop rdi push r11 # Address to loopback push r15 # Cell to check push rdi ret process_loop_end: # Gotta get ret value pop rsi pop rdi # Cell pop rax # Address # if cell is 0 we are done with loop cmp byte ptr [r14+rdi], 0 je 1f mov r11, rax # Make sure stack isn't caught on fire push rax push rdi push rsi ret 1: push rsi ret # Discard