21 Commits

Author SHA1 Message Date
PoliEcho 719bc17fcd Update README.md
build_test / build (push) Successful in 2m16s
2025-07-13 21:36:34 +00:00
PoliEcho 5c91ace69b change statusbar text
build_test / build (push) Successful in 3m11s
2025-07-13 22:35:22 +02:00
PoliEcho 872c842e7c revert input.asm 2025-07-13 21:07:48 +02:00
PoliEcho a6a7debf2e break tty while trining to fix tty 2025-07-13 20:23:19 +02:00
PoliEcho 57987228b0 add simulation speed
build_test / build (push) Successful in 2m58s
2025-07-13 14:27:46 +02:00
PoliEcho 83d3f3ac5a Update README.md
build_test / build (push) Successful in 1m55s
2025-07-12 20:02:03 +00:00
PoliEcho 45c6d0eb83 Update README.md
build_test / build (push) Successful in 2m3s
2025-07-12 19:54:03 +00:00
PoliEcho 670a6a2602 Add README.md
build_test / build (push) Has been cancelled
2025-07-12 19:53:40 +00:00
PoliEcho e70b9ac765 Update .gitea/workflows/build_test.yaml
build_test / build (push) Successful in 1m57s
2025-07-12 19:47:20 +00:00
PoliEcho 6112537e9b Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 2m22s
2025-07-12 19:42:41 +00:00
PoliEcho 3e59f36d4e Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 23s
2025-07-12 19:41:46 +00:00
PoliEcho f26553e7c7 Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 14s
2025-07-12 19:40:32 +00:00
PoliEcho db00e98b4c Update .gitea/workflows/build_test.yaml 2025-07-12 19:39:08 +00:00
PoliEcho b449c66a66 Update .gitea/workflows/build_test.yaml 2025-07-12 19:38:24 +00:00
PoliEcho 7dc5237c3e Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 13s
2025-07-12 19:37:10 +00:00
PoliEcho 7fd699ea38 Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 34s
2025-07-12 19:34:56 +00:00
PoliEcho b5c539a3a2 Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 18s
2025-07-12 19:33:30 +00:00
PoliEcho ce343ff9db Update .gitea/workflows/build_test.yaml
build_test / build (push) Failing after 57s
fix build test
2025-07-12 18:59:23 +00:00
PoliEcho d6ee106682 add build test
build_test / build (push) Failing after 1m9s
2025-07-12 20:56:47 +02:00
PoliEcho 5b56f6bcb6 fix some rendering issues 2025-07-12 20:11:22 +02:00
PoliEcho 4a8db75bef make multipurpuse_buf biger to avoid out of bounds writes 2025-07-12 17:12:25 +02:00
7 changed files with 262 additions and 48 deletions
+17
View File
@@ -0,0 +1,17 @@
name: build_test
on: [push]
jobs:
build:
runs-on: arch
steps:
- name: fix package cache
run: rm -fr /var/cache/pacman/pkg/* && pacman -Syy archlinux-keyring --needed --noconfirm && pacman-key --init && pacman-key --populate archlinux
- name: get dependencies
run: pacman -Sy nodejs make nasm binutils --needed --noconfirm
- name: Checkout code
uses: actions/checkout@v4
- name: Build
run: make -j$(nproc)
+19
View File
@@ -0,0 +1,19 @@
<img src="https://git.pupes.org/repo-avatars/e4ede9d30f070c9e191eace5a88dcaa40434b9cadf60204122fab5a83aec9a9f" alt="logo of ParaDocs" width="196"></img>
[![build test](https://git.pupes.org/PoliEcho/asm-game-of-life/actions/workflows/build_test.yaml/badge.svg)](https://git.pupes.org/PoliEcho/asm-game-of-life/actions?workflow=build_test.yaml)
# AMD64 Assembly Game of life
## Dependencies
> AMD64 Linux Kernel
### Build only
> nasm
> ld
> make
## Download
#### TODO: add releases link
## Build
```shell
make
```
+36 -2
View File
@@ -14,17 +14,21 @@ section .bss
simulation_running: RESB 1 simulation_running: RESB 1
next_frame_ptr: RESQ 1 next_frame_ptr: RESQ 1
section .data
extern simulation_speed
section .rodata section .rodata
clear: db ESC_CHAR, "[2J", 0 clear: db ESC_CHAR, "[2J", 0
global reset
reset: db ESC_CHAR, "[0m", 0 reset: db ESC_CHAR, "[0m", 0
resetLen: equ $-reset-1 resetLen: equ $-reset-1
global resetLen global resetLen
home_cursor: db ESC_CHAR, "[H", 0 home_cursor: db ESC_CHAR, "[H", 0
statusbar: db ESC_CHAR, "[32;100m", "Use arrow keys to move cursor, enter to invert cell j/k to change simulation speed, p to simulation", 0 statusbar: db ESC_CHAR, "[32;100m", "Use arrow keys to move cursor, enter to invert cell j/k to change simulation speed, p to simulation. Frame Delay multiplier:", 0
START_STOP_pos: equ $-statusbar-17 statusbarLen: equ $-statusbar
START_STOP_pos: equ statusbarLen-42
start_str: db "START", 0 start_str: db "START", 0
@@ -48,6 +52,7 @@ extern string_copy
extern memory_set extern memory_set
extern memory_copy extern memory_copy
extern alloc extern alloc
extern unsigned_int_to_ascii
global init_gameboard global init_gameboard
init_gameboard: init_gameboard:
@@ -94,6 +99,7 @@ print_game_ui:
push rdi push rdi
add rdi, [gameboard_size] add rdi, [gameboard_size]
sub di, [term_cols] sub di, [term_cols]
push rdi
add rdi, START_STOP_pos add rdi, START_STOP_pos
mov cl, [simulation_running] mov cl, [simulation_running]
@@ -106,6 +112,34 @@ print_game_ui:
.end_simulation_running_check: .end_simulation_running_check:
call string_copy call string_copy
pop rdi
add rdi, statusbarLen
movss xmm0, [simulation_speed]
cvttss2si rsi, xmm0
push rsi
push rdi
call unsigned_int_to_ascii
pop rdi
add rdi, rax
mov byte [rdi], '.'
inc rdi
pop rax
cvtsi2ss xmm1, rax
subss xmm0, xmm1; get only value after decimal point
mov rax, 10
cvtsi2ss xmm1, rax
mulss xmm0, xmm1
cvttss2si rsi, xmm0; get first decimal point as int
call unsigned_int_to_ascii; rdi already set
pop rdi pop rdi
call print_str call print_str
+129 -39
View File
@@ -15,14 +15,21 @@ section .bss
section .data section .data
cursor_rows: dw 1 cursor_rows: dw 1
cursor_cols: dw 1 cursor_cols: dw 1
global simulation_speed
simulation_speed dd 1.0
section .rodata section .rodata
extern reset
cursor_up: db ESC_CHAR, "[1A", 0 cursor_up: db ESC_CHAR, "[1A", 0
cursor_down: db ESC_CHAR, "[1B", 0 cursor_down: db ESC_CHAR, "[1B", 0
cursor_right: db ESC_CHAR, "[1C", 0 cursor_right: db ESC_CHAR, "[1C", 0
cursor_left: db ESC_CHAR, "[1D", 0 cursor_left: db ESC_CHAR, "[1D", 0
cursor_color: db ESC_CHAR, "[45m", 0
speed_multiplier dd 50.0
arrow_switch_statement: arrow_switch_statement:
dq handle_user_input.arrow_up dq handle_user_input.arrow_up
@@ -36,38 +43,21 @@ extern print_str
extern step_simulation extern step_simulation
extern unsigned_int_to_ascii extern unsigned_int_to_ascii
extern print_game_ui extern print_game_ui
extern string_copy
global handle_user_input global handle_user_input
handle_user_input:; main loop of the program handle_user_input:; main loop of the program
push r12 push r12
push r13
lea r12, [multipurpuse_buf] lea r12, [multipurpuse_buf]
.main_loop: .main_loop:
xor r13, r13
; put the cursor where it should be ; put the cursor where it should be
mov rdi, r12; multipurpuse_buf pointer is in r12 call print_cursor
mov word [rdi], 0x5B1B; will store ESC_CHAR, '[' they have to be in reverse order here due to little endian
add rdi, 2
push rdi
xor rsi, rsi
mov si, [cursor_rows]
call unsigned_int_to_ascii
pop rdi
add rdi, rax; add lenght of string to pointer
mov byte [rdi], ';'
inc rdi
push rdi
mov si, [cursor_cols]
call unsigned_int_to_ascii
pop rdi
add rdi, rax
mov byte [rdi], 'H'
inc rdi
mov byte [rdi], 0; null terminate
mov rdi, r12; multipurpuse_buf pointer is in r12
call print_str
@@ -79,7 +69,10 @@ handle_user_input:; main loop of the program
mov word [r12+4], POLLIN mov word [r12+4], POLLIN
mov rdi, r12 mov rdi, r12
mov rsi, 1; only one file descriptor is provided mov rsi, 1; only one file descriptor is provided
mov rdx, 500; no timeout. maybe use this for final sleep but run if user inputs something TODO movss xmm0, [speed_multiplier]
movss xmm1, [simulation_speed]
mulss xmm0, xmm1; callculate sleep lenght
cvttss2si rdx, xmm0; truncate and copy to rdx
syscall syscall
test rax, rax; SYS_POLL returns 0 when no change happens within timeout test rax, rax; SYS_POLL returns 0 when no change happens within timeout
@@ -119,41 +112,41 @@ handle_user_input:; main loop of the program
dec word [cursor_rows] dec word [cursor_rows]
jnz .move_cursor_up jnz .move_cursor_up
inc word [cursor_rows] inc word [cursor_rows]
jmp .no_input jmp .end_input_handling
.move_cursor_up: .move_cursor_up:
lea rdi, [cursor_up] lea rdi, [cursor_up]
call print_str call print_str
jmp .no_input jmp .end_input_handling
.arrow_down: .arrow_down:
mov r8w, [cursor_rows] mov r8w, [cursor_rows]
inc r8w inc r8w
cmp word r8w, r9w cmp word r8w, r9w
ja .no_input ja .end_input_handling
mov word [cursor_rows], r8w mov word [cursor_rows], r8w
lea rdi, [cursor_down] lea rdi, [cursor_down]
call print_str call print_str
jmp .no_input jmp .end_input_handling
.arrow_right: .arrow_right:
mov r8w, [cursor_cols] mov r8w, [cursor_cols]
inc r8w inc r8w
cmp word r8w, r10w cmp word r8w, r10w
ja .no_input ja .end_input_handling
mov word [cursor_cols], r8w mov word [cursor_cols], r8w
lea rdi, [cursor_right] lea rdi, [cursor_right]
call print_str call print_str
jmp .no_input jmp .end_input_handling
.arrow_left: .arrow_left:
dec word [cursor_cols] dec word [cursor_cols]
jnz .move_cursor_left jnz .move_cursor_left
inc word [cursor_cols] inc word [cursor_cols]
jmp .no_input jmp .end_input_handling
.move_cursor_left: .move_cursor_left:
lea rdi, [cursor_left] lea rdi, [cursor_left]
call print_str call print_str
jmp .no_input jmp .end_input_handling
.handle_single_byte_chars: .handle_single_byte_chars:
@@ -176,12 +169,12 @@ handle_user_input:; main loop of the program
je .hashtag_present je .hashtag_present
mov byte [rdi], '#' mov byte [rdi], '#'
jmp .no_input jmp .end_input_handling
.hashtag_present: .hashtag_present:
mov byte [rdi], ' ' mov byte [rdi], ' '
jmp .no_input jmp .end_input_handling
.check_p: .check_p:
cmp al, 'p' cmp al, 'p'
@@ -189,38 +182,62 @@ handle_user_input:; main loop of the program
xor byte [simulation_running], 0x01; switch simulation on or off xor byte [simulation_running], 0x01; switch simulation on or off
jmp .no_input jmp .end_input_handling
.check_j: .check_j:
cmp al, 'j' cmp al, 'j'
jne .check_k jne .check_k
; TODO implement simulation speed movss xmm0, [simulation_speed]
mov eax, 0x3DCCCCCD; 0.1f
vmovd xmm1, eax
jmp .no_input addss xmm0, xmm1
; wont check for overflows since the user would need be crazy to reach that number
movss [simulation_speed], xmm0
jmp .end_input_handling
.check_k: .check_k:
cmp al, 'k' cmp al, 'k'
jne .check_q jne .check_q
; TODO implement simulation speed movss xmm0, [simulation_speed]
mov eax, 0x3DCCCCCD; 0.1f
vmovd xmm1, eax
subss xmm0, xmm1
ucomiss xmm0, xmm1; check if number is smaller than 0.1
jb .end_input_handling
movss [simulation_speed], xmm0
jmp .end_input_handling
.check_q: .check_q:
cmp al, 'q' cmp al, 'q'
jne .no_input jne .end_input_handling
pop r12 jmp .function_exit
ret; exit if q pressed ret; exit if q pressed
.end_input_handling:
mov r13b, 1
.no_input: .no_input:
mov al, [simulation_running] mov al, [simulation_running]
test al, al test al, al
jz .dont_step jz .dont_step
call step_simulation call step_simulation
mov r13b, 1
.dont_step: .dont_step:
test r13b, r13b
jz .main_loop
call print_game_ui call print_game_ui
jmp .main_loop jmp .main_loop
.function_exit:
pop r13
pop r12 pop r12
ret ret
@@ -289,4 +306,77 @@ reset_terminal:
syscall syscall
ret ret
print_cursor:
push r12
push r13
lea r12, [multipurpuse_buf]
mov rdi, r12
mov word [rdi], 0x5B1B; will store ESC_CHAR, '[' they have to be in reverse order here due to little endian
add rdi, 2
push rdi
xor rsi, rsi
mov si, [cursor_rows]
call unsigned_int_to_ascii
pop rdi
add rdi, rax; add lenght of string to pointer
mov byte [rdi], ';'
inc rdi
push rdi
mov si, [cursor_cols]
call unsigned_int_to_ascii
pop rdi
add rdi, rax
mov byte [rdi], 'H'
inc rdi
mov byte [rdi], 0; null terminate
mov rdi, r12
call print_str
; write there real cursor
xor r13, r13
mov rdi, r12
lea rsi, [cursor_color]
call string_copy
mov rdi, r12
add r13, rax
add rdi, r13
xor rax, rax
mov ax, [cursor_rows]
dec ax
mul word [term_cols]; get index of character
add ax, [cursor_cols]
dec ax
xor rsi, rsi
add rax, [gameboard_ptr]
mov sil, [rax]; now we got the character in si
mov byte [rdi], sil
inc rdi
inc r13
lea rsi, [reset]
call string_copy
mov rdi, r12
add r13, rax
add rdi, r13
lea rsi, [cursor_left]
call string_copy
mov rdi, r12
add r13, rax
add rdi, r13
inc rdi
mov byte [rdi], 0; null terminate
mov rdi, r12
call print_str
pop r13
pop r12
ret
+56 -3
View File
@@ -4,7 +4,7 @@
section .bss section .bss
global multipurpuse_buf global multipurpuse_buf
multipurpuse_buf: RESB 8 multipurpuse_buf: RESB 16
global term_rows global term_rows
term_rows: RESW 1 term_rows: RESW 1
@@ -20,10 +20,17 @@ section .bss
extern cursor_rows extern cursor_rows
extern cursor_cols extern cursor_cols
global running_in_tty
running_in_tty: RESB 1
section .rodata section .rodata
extern resetLen extern resetLen
hide_cursor: db ESC_CHAR, "[?25l", 0
show_cursor: db ESC_CHAR, "[?25h", 0
help_text: db "asm-game-of-life [args]",0xA,"-h display this help menu",0xA,"Controls:",0xA,"use arrow keys to move around",0xA,"ENTER to invert cell",0xA,"p to START/STOP simulation",0xA,"k to increase simulation speed",0xA,"j to decrese simulation speed",0xA, 0
section .text section .text
extern print_str extern print_str
extern unsigned_int_to_ascii extern unsigned_int_to_ascii
@@ -55,11 +62,50 @@ _start:
; handle args ; handle args
pop rcx; get argc (number of arguments) pop rcx; get argc (number of arguments)
pop rax; get rid of program name arugument
cmp rcx, 1 cmp rcx, 1
jle .no_arguments_provided jle .no_arguments_provided
; TODO hanndle arguments dec rcx
.handle_arg:
pop rax
mov word di, [rax]
cmp di, 0x682D; check if -h was passed
jne .next_arg
lea rdi, [help_text]
call print_str
jmp .exit_program
.next_arg:
dec rcx
test rcx, rcx
jnz .handle_arg
.no_arguments_provided: .no_arguments_provided:
pop rax; get rid of null termination of argv
; handle enviroment vars
.handle_env:
pop rax
test rax, rax; test if we reached end of envs
jz .no_envs
mov dword edi, [rax]
cmp edi, 0x4D524554; check for "TERM" inverted becose endiannes
jne .handle_env
mov qword rdi, [rax+5]; remove the TERM= part this should never segfault since there sould allwas be other data behind enviroment vars and i dont mind garbage
mov rsi, 0xffffffffff
and rdi, rsi
mov rsi, 0x78756e696c
cmp rdi, rsi; check for "linux"
jne .no_envs
mov byte [running_in_tty], 1
.no_envs:
call init_alloc call init_alloc
xor rax, rax xor rax, rax
@@ -85,16 +131,23 @@ _start:
mov rdx, O_NONBLOCK mov rdx, O_NONBLOCK
syscall syscall
lea rdi, [hide_cursor]
call print_str
call print_game_ui call print_game_ui
call disable_canonical_mode_and_echo call disable_canonical_mode_and_echo
call print_game_ui
call handle_user_input call handle_user_input
call reset_terminal call reset_terminal
lea rdi, [show_cursor]
call print_str
.exit_program:
mov rax, SYS_EXIT mov rax, SYS_EXIT
mov rdi, 0 ; return code mov rdi, 0 ; return code
syscall syscall
+1 -1
View File
@@ -61,7 +61,7 @@ unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi D
ret ret
global string_copy global string_copy
string_copy:; takes pointer to destination in rdi and pointer to source in rsi string_copy:; takes pointer to destination in rdi and pointer to source in rsi and return lenght in rax
xor rax, rax xor rax, rax
xor rcx, rcx xor rcx, rcx
+1
View File
@@ -5,6 +5,7 @@ SYS_WRITE equ 1
SYS_BRK equ 12 SYS_BRK equ 12
SYS_FCNTL equ 72 SYS_FCNTL equ 72
SYS_POLL equ 7 SYS_POLL equ 7
SYS_NANOSLEEP equ 35
STDIN equ 0 STDIN equ 0
STDOUT equ 1 STDOUT equ 1