Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84993e3b8d |
@ -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
|
||||
|
||||
76
src/io/io.asm
Normal file
76
src/io/io.asm
Normal file
@ -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
|
||||
249
src/main.asm
249
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"
|
||||
150
src/ui/ui.asm
Normal file
150
src/ui/ui.asm
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user