diff --git a/bin/main b/bin/main index a2765ae..e5520ef 100755 Binary files a/bin/main and b/bin/main differ diff --git a/compile.sh b/compile.sh index e8fd549..37cc859 100755 --- a/compile.sh +++ b/compile.sh @@ -1,5 +1,5 @@ echo ">>> Compiling ASM code..." -nasm -f macho64 -o ./bin/obj/main.o ./src/main.asm +nasm -f macho64 -g -o ./bin/obj/main.o ./src/main.asm if [ $? -ne 0 ]; then echo " >> Error: Assembly failed." exit 1 diff --git a/src/io/io.asm b/src/io/io.asm new file mode 100644 index 0000000..7c0b871 --- /dev/null +++ b/src/io/io.asm @@ -0,0 +1,76 @@ +; returns the user input in r15 +; 0x01 = up +; 0x02 = left +; 0x03 = down +; 0x04 = right +; 0xDEAD = no valid key pressed +read_user_input: + ; Read user input for the game + ; Read AWSD keys (basically, read a single byte) + + ; Ensure symmetric register saving + push rax ; added missing push for symmetry + push rbx + push rcx + push rdx + + push rsi + push rdi + + xor r15, r15 ; Clear r15 to indicate no valid key pressed + + ; changed: use read syscall number 0x2000003 + mov rax, 0x2000003 + mov rdi, 0 + lea rsi, [rsp] ; Read into stack + mov rdx, 1 + syscall + + ; Check for W key + cmp byte [rsp], 0x77 + je up_key + ; Check for A key + cmp byte [rsp], 0x61 + je left_key + ; Check for S key + cmp byte [rsp], 0x73 + je down_key + ; Check for D key + cmp byte [rsp], 0x64 + je right_key + + ; Check for e key + cmp byte [rsp], 0x65 + je unburry_key + + mov r15, 0xDEAD ; Debug: no valid key pressed + jmp exit_user_with_no_input + +up_key: + mov r15, 0x01 ; Debug: up key pressed + jmp exit_user_with_no_input + +left_key: + mov r15, 0x02 ; Debug: left key pressed + jmp exit_user_with_no_input + +down_key: + mov r15, 0x03 ; Debug: down key pressed + jmp exit_user_with_no_input + +right_key: + mov r15, 0x04 ; Debug: right key pressed + jmp exit_user_with_no_input + +unburry_key: + mov r15, 0x05 ; Debug: unburry key pressed + +exit_user_with_no_input: + ; Restore registers + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + ret \ No newline at end of file diff --git a/src/main.asm b/src/main.asm index 01f2526..e231274 100644 --- a/src/main.asm +++ b/src/main.asm @@ -14,42 +14,37 @@ section .data user_input times 3 db 0 user_input_len equ $ - user_input - newline db 0xA, 0 newline_len equ $ - newline digit_buffer db 0 + first_move db 0 + section .bss board resb 100 + ; termios resb 20 ; Reserve space for termios structure section .text global _main _main: - ; Fill the board with 0s and 1s - xor r10, r10 ; Counter - lea r11, [rel board] ; Load address of board + ; Initialize the board with mines and empty tiles + xor rax, rax - mov rcx, 100 ; Loop 100 times -fill_loop: - rdrand rax - and rax, 15 ; Reduce probability of mine (1 in 16 chance) - cmp rax, 1 - sete al ; Set al to 1 if rax == 1, otherwise 0 - mov [r11 + r10], al ; Store at board[r10] - inc r10 - loop fill_loop + ; Set up user location + mov byte [rel user_location_pos], 0 ; Print the board - xor r10, r10 ; Reset counter - + xor r10, r10 ; Reset counter before refill + print_loop: xor rcx , rcx ; Reset mine count lea r11, [rel board] - movzx rax, byte [r11 + r10] ; Load board[r10] + movzx rax, byte [r11 + r10] ; Load board[r10] - ; Print user location - cmp r10, [rel user_location_pos] + ; Print user location (load byte with zero-extension) + movzx rbx, byte [rel user_location_pos] + cmp r10, rbx jne not_user_location lea r8, [rel user_location] mov r9, tile_len @@ -112,115 +107,119 @@ no_newline: cmp r10, 100 jb print_loop - ; Read arrow keys + ; Small bracket to be able to distinguish between first move and refill + lea r8, [rel newline] + mov r9, newline_len + call print_String + call print_String + + xor r15, r15 + ; Read user input + call read_user_input + + cmp byte [rel first_move], 0 ; Compare memory content of first_move + je not_first_move + ; Instead of resetting and jumping to fill_loop, call fill_board from ui.asm + call fill_board + jmp print_loop + +not_first_move: + + ; Check if user pressed a valid key + cmp r15, 0xDEAD + je invalid_key + + cmp r15, 0x01 + je move_up + + cmp r15, 0x02 + je move_left + + cmp r15, 0x03 + je move_down + + cmp r15, 0x04 + je move_right + + cmp r15, 0x05 + je unburry + + jmp invalid_key +move_up: + ; Move up + lea r8, [rel user_location] + mov r9, tile_len + call print_String + + ; Update user location safely (read one byte) + movzx rax, byte [rel user_location_pos] + sub rax, 10 + mov [rel user_location_pos], al + + ; Print the board again + + xor r10, r10 ; Reset counter before refill + jmp print_loop +move_left: + ; Move left + lea r8, [rel user_location] + mov r9, tile_len + call print_String + + ; Update user location safely (read one byte) + movzx rax, byte [rel user_location_pos] + sub rax, 1 + mov [rel user_location_pos], al + + ; Print the board again + + xor r10, r10 ; Reset counter before refill + jmp print_loop + +move_down: + ; Move down + lea r8, [rel user_location] + mov r9, tile_len + call print_String + + ; Update user location safely (read one byte) + movzx rax, byte [rel user_location_pos] + add rax, 10 + mov [rel user_location_pos], al + + ; Print the board again + + xor r10, r10 ; Reset counter before refill + jmp print_loop +move_right: + ; Move right + lea r8, [rel user_location] + mov r9, tile_len + call print_String + + ; Update user location safely (read one byte) + movzx rax, byte [rel user_location_pos] + add rax, 1 + mov [rel user_location_pos], al + + ; Print the board again + + xor r10, r10 ; Reset counter before refill + jmp print_loop + +unburry: + ; Unburry the tile: set first move flag and refill board + mov byte [rel first_move], 1 + call fill_board + jmp print_loop + +; Invalid key pressed +invalid_key: + ; Exit mov rax, 0x2000001 xor rdi, rdi syscall -; r8 = string -; r9 = length -print_String: - mov rax, 0x2000004 - mov rdi, 1 - mov rsi, r8 - mov rdx, r9 - syscall - ret - -; r10 = current tile index -; r11 = board -; rdx = mine count -; r8 = offset -count_adjacent_mines: - xor rdx, rdx - mov r8, 0 - - ; Check top left - mov rax, r10 - sub rax, 11 - cmp rax, 0 - jl .skip_top_left - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_top_left: - - ; Check top - mov rax, r10 - sub rax, 10 - cmp rax, 0 - jl .skip_top - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_top: - - ; Check top right - mov rax, r10 - sub rax, 9 - cmp rax, 0 - jl .skip_top_right - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_top_right: - - ; Check left - mov rax, r10 - sub rax, 1 - cmp rax, 0 - jl .skip_left - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_left: - - ; Check right - mov rax, r10 - add rax, 1 - cmp rax, 100 - jge .skip_right - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_right: - - ; Check bottom left - mov rax, r10 - add rax, 9 - cmp rax, 100 - jge .skip_bottom_left - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_bottom_left: - - ; Check bottom - mov rax, r10 - add rax, 10 - cmp rax, 100 - jge .skip_bottom - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_bottom: - - ; Check bottom right - mov rax, r10 - add rax, 11 - cmp rax, 100 - jge .skip_bottom_right - movzx rax, byte [r11 + rax] - cmp rax, 1 - sete al - add dl, al -.skip_bottom_right: - ret +%include "./src/io/io.asm" +%include "./src/ui/ui.asm" \ No newline at end of file diff --git a/src/ui/ui.asm b/src/ui/ui.asm new file mode 100644 index 0000000..244dd5e --- /dev/null +++ b/src/ui/ui.asm @@ -0,0 +1,150 @@ +; r8 = string +; r9 = length +print_String: + mov rax, 0x2000004 + mov rdi, 1 + mov rsi, r8 + mov rdx, r9 + syscall + ret + +; r10 = current tile index +; r11 = board +; rdx = mine count +; r8 = offset +count_adjacent_mines: + ; Compute current column: r12 = r10 mod 10 + mov rax, r10 + xor rdx, rdx + mov rcx, 10 + div rcx + mov r12, rdx ; r12 holds the column index (0-9) + + xor rdx, rdx ; rdx will accumulate the mine count + + ; Check top-left: valid if r10 >= 11 and column != 0 + cmp r10, 11 + jb .skip_top_left + cmp r12, 0 + je .skip_top_left + mov rax, r10 + sub rax, 11 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_top_left: + + ; Check top: valid if r10 >= 10 + cmp r10, 10 + jb .skip_top + mov rax, r10 + sub rax, 10 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_top: + + ; Check top-right: valid if r10 >= 9 and column != 9 + cmp r10, 9 + jb .skip_top_right + cmp r12, 9 + je .skip_top_right + mov rax, r10 + sub rax, 9 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_top_right: + + ; Check left: valid if column != 0 + cmp r12, 0 + je .skip_left + mov rax, r10 + sub rax, 1 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_left: + + ; Check right: valid if column != 9 + cmp r12, 9 + je .skip_right + mov rax, r10 + add rax, 1 + cmp rax, 100 + jge .skip_right + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_right: + + ; Check bottom-left: valid if r10 < 90 and column != 0 + cmp r10, 90 + jae .skip_bottom_left + cmp r12, 0 + je .skip_bottom_left + mov rax, r10 + add rax, 9 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_bottom_left: + + ; Check bottom: valid if r10 < 90 + cmp r10, 90 + jae .skip_bottom + mov rax, r10 + add rax, 10 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_bottom: + + ; Check bottom-right: valid if r10 < 90 and column != 9 + cmp r10, 90 + jae .skip_bottom_right + cmp r12, 9 + je .skip_bottom_right + mov rax, r10 + add rax, 11 + movzx rax, byte [r11 + rax] + cmp rax, 1 + sete al + add dl, al +.skip_bottom_right: + ret + +; Print the board +; r10 = current tile index +; r11 = board +; r12 = column index +; rdx = mine count +; r8 = offset +fill_board: + xor r10, r10 ; Counter for filling the board + push rbp + mov rbp, rsp + push rcx + xor r10, r10 ; Counter + lea r11, [rel board] ; Load address of board + +fill_loop: + rdrand rax + and rax, 15 ; Reduce probability of mine (1 in 16 chance) + cmp rax, 1 + sete al ; Set al to 1 if rax == 1, otherwise 0 + mov [r11 + r10], al ; Store at board[r10] + inc r10 + cmp r10, 100 ; Check if we've filled 100 tiles + jb fill_loop + + pop rcx + pop rbp + ret \ No newline at end of file