42 Commits

Author SHA1 Message Date
PoliEcho 82e55b3e1e Merge branch 'master' of https://git.pupes.org/PoliEcho/asm-game-of-life
build_test / build (push) Successful in 2m11s
2025-07-14 20:57:01 +02:00
PoliEcho 6d3279f850 add tty workaround 2025-07-14 20:55:41 +02:00
PoliEcho 1820d4fdf8 Update README.md
build_test / build (push) Successful in 1m58s
2025-07-13 22:18:00 +00:00
PoliEcho 81367baa99 Update README.md
build_test / build (push) Successful in 1m48s
2025-07-13 22:16:01 +00:00
PoliEcho 33b6a82a42 Update README.md
build_test / build (push) Successful in 2m2s
2025-07-13 22:12:02 +00:00
PoliEcho 755f9b9f06 Update README.md
build_test / build (push) Successful in 1m54s
2025-07-13 22:03:09 +00:00
PoliEcho c3563fcda1 Update README.md
build_test / build (push) Successful in 2m18s
2025-07-13 21:57:45 +00:00
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
PoliEcho fa7b4c70b8 IT WORKS 2025-07-12 16:09:39 +02:00
PoliEcho a46f907ff6 fixing segfault and such 2025-07-12 11:47:57 +02:00
PoliEcho 63ded22bfd more work on actual game logic 2025-07-10 22:55:18 +02:00
PoliEcho 00cc777183 add warning flags 2025-07-10 20:59:32 +02:00
PoliEcho b94ebe30c8 add user input handling 2025-07-10 18:27:52 +02:00
PoliEcho c5e404f1dd FINALY fix inicializing gameboard 2025-07-09 21:33:36 +02:00
PoliEcho 564a6b88c1 fix aligment 2025-07-09 20:34:24 +02:00
PoliEcho d6613ac341 fix memory_set number 2 2025-07-09 20:34:09 +02:00
PoliEcho 2b8236ee91 fix memory_set function 2025-07-09 19:23:13 +02:00
PoliEcho c0bd3fcbc3 fix pointer aritmetic 2025-07-09 13:26:06 +02:00
PoliEcho 76093db3c9 YES IT DOES NOT SEGFAULT 2025-07-08 22:50:46 +02:00
PoliEcho 9092d1276a added memory_set'function 2025-07-08 15:04:23 +02:00
PoliEcho 35a6894d9f fix allocator 2025-07-08 10:00:24 +02:00
PoliEcho a2a5b4c972 added some gameboard initialization 2025-07-07 23:15:54 +02:00
9 changed files with 973 additions and 17 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)
+11 -1
View File
@@ -1,12 +1,22 @@
NASM = nasm
LD = ld
NASM_FLAGS := -felf64 -Isrc
NASM_FLAGS := -felf64 -Isrc -Ox -Ov -w+all -w-reloc-abs-dword -w-reloc-rel-dword
LD_FLAGS := --strip-all
DEBUG_LD_FLAGS := -g
DEBUG_NASM_FLAGS := -g -F dwarf
# check for avx2 support
ifeq ($(shell grep -o 'avx2[^ ]*' /proc/cpuinfo | head -n 1),avx512)
NASM_FLAGS += -DAVX2
endif
# check for avx512 support
ifeq ($(shell grep -o 'avx512[^ ]*' /proc/cpuinfo | head -n 1),avx512)
NASM_FLAGS += -DAVX512
endif
SRC_PATH := src
OBJ_PATH := build/obj
+35
View File
@@ -0,0 +1,35 @@
<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
[releases](https://git.pupes.org/PoliEcho/asm-game-of-life/releases)
## Build
```shell
make
```
## Controls
| key | action |
|--------|-------------------------|
| arrows | move cursor |
| ENTER | invert cell |
| j/k | change simulation speed |
| p | start/stop simulation |
| q | quit |
## Warning
delays in TTY may be broken
## Notes
if screen does not clear properly after loading just move the cursor around a bit
+5 -3
View File
@@ -7,7 +7,7 @@ section .text
global init_alloc
init_alloc:; initialize allocator, optionaly return brk pointer in rax
mov rax, SYS_BRK
mov rdi, 0
xor rdi, rdi
syscall
mov [brk_pointer], rax
ret
@@ -15,9 +15,11 @@ init_alloc:; initialize allocator, optionaly return brk pointer in rax
global alloc
alloc:; Takes lenght of data in rdi and returns pointer in rax
mov rax, SYS_BRK
mov rcx, [brk_pointer]
mov qword rcx, [brk_pointer]
push rcx
syscall; size already in rdi
add rdi, rcx; calculate new BRK address
syscall
mov [brk_pointer], rax
pop rax
ret
+256
View File
@@ -0,0 +1,256 @@
%include "symbols.asm"
section .bss
extern gameboard_ptr
extern term_rows
extern term_cols
extern gameboard_size
global simulation_running
simulation_running: RESB 1
next_frame_ptr: RESQ 1
section .data
extern simulation_speed
section .rodata
clear: db ESC_CHAR, "[2J", 0
global reset
reset: db ESC_CHAR, "[0m", 0
resetLen: equ $-reset-1
global resetLen
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. Frame Delay multiplier:", 0
statusbarLen: equ $-statusbar
START_STOP_pos: equ statusbarLen-42
start_str: db "START", 0
stop_str: db "STOP ", 0
alive_switch_statement:
dq step_simulation.die; 0
dq step_simulation.die; 1
dq step_simulation.live; 2
dq step_simulation.live; 3
dq step_simulation.die; 4
dq step_simulation.die; 5
dq step_simulation.die; 6
dq step_simulation.die; 7
dq step_simulation.die; 8
section .text
extern print_str
extern string_copy
extern memory_set
extern memory_copy
extern alloc
extern unsigned_int_to_ascii
global init_gameboard
init_gameboard:
xor rax, rax
xor rcx, rcx
mov rdi, [gameboard_ptr]
push rdi
mov rsi, 0x20; set rsi to SPACE character
mov rdx, [gameboard_size]
push rdx
add rdx, ESC_chars_compensation_Len; I dont know how this work but it works so i wont touch it
call memory_set
pop rdx
pop rdi
add rdi, rdx; get pointer to last char on screen
push rdx
push rdi
add rdi, ESC_chars_compensation_Len
lea rsi, [reset]
call string_copy
pop rdi
xor rax, rax
mov ax, [term_cols]
sub rdi, rax
lea rsi, [statusbar]
call string_copy
pop rdi
call alloc
mov [next_frame_ptr], rax
ret
global print_game_ui
print_game_ui:
lea rdi, [home_cursor]
call print_str
mov qword rdi, [gameboard_ptr]
push rdi
add rdi, [gameboard_size]
sub di, [term_cols]
push rdi
add rdi, START_STOP_pos
mov cl, [simulation_running]
test cl,cl; test if simulation is running
jz .simulation_not_running
lea rsi, [stop_str]
jmp .end_simulation_running_check
.simulation_not_running:
lea rsi, [start_str]
.end_simulation_running_check:
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
call print_str
ret
%macro check_if_hashtag 2
cmp %1, r8
jl .no_count_%2
cmp %1, r9
ja .no_count_%2
mov r11b, [%1]
cmp r11b, '#'
jne .no_count_%2
inc dl
.no_count_%2:
%endmacro
global step_simulation:
step_simulation:
mov rdi, [next_frame_ptr]; destination
mov rsi, [gameboard_ptr]; source
mov rcx, [gameboard_size]; number of iterations
mov r8, rsi; store lowest address posible so we are not checking out of bounds
mov r9, rsi
add r9, rcx; store higest address posible so we are not checking out of bounds
xor r10, r10
mov r10w, [term_cols]
;mov r11, [term_rows] this register has been confiscated since i cannot use ah because of error: cannot use high byte register in rex instruction
sub rcx, r10; remove status bar
xor rax, rax; this shouldn't be needed but just to be sure
xor r11, r11
xor rdx, rdx; we will use dl as # counter
.for_every_column_on_gameboard:
xor dl, dl
mov al, [rsi]; NOTE to self if i need extra register i can shift this to ah and free up r11
inc rsi
check_if_hashtag rsi, 1; check column to the to the right
dec rsi
dec rsi
check_if_hashtag rsi, 2; check the one to the left
inc rsi
add rsi, r10
check_if_hashtag rsi, 3; check the one to the down
inc rsi
check_if_hashtag rsi, 4; check the one to the down-right
dec rsi
dec rsi
check_if_hashtag rsi, 5; check the one to the down-left
inc rsi
sub rsi, r10
sub rsi, r10
check_if_hashtag rsi, 6; check the one to the up
inc rsi
check_if_hashtag rsi, 7; check the one to the up-right
dec rsi
dec rsi
check_if_hashtag rsi, 8; check the one to the up-left
inc rsi
add rsi, r10
cmp al, '#'
jne .dead_cell
jmp [alive_switch_statement+(rdx*8)]
.die:
mov byte [rdi], 0x20; SPACE
jmp .end_check
.live:
mov byte [rdi], '#'
jmp .end_check
.dead_cell:
cmp dl, 3
jne .fill_space_there
mov byte [rdi], '#'
jmp .end_check
.fill_space_there:
mov byte [rdi], 0x20; SPACE
.end_check:
dec rcx
inc rdi
inc rsi
test rcx, rcx
jnz .for_every_column_on_gameboard
mov rsi, [next_frame_ptr]; source
mov rdi, [gameboard_ptr]; destination
mov rdx, [gameboard_size]; number of iterations
sub rdx, r10; remove statusbar
call memory_copy
ret
+410
View File
@@ -0,0 +1,410 @@
%include "symbols.asm"
section .bss
alignb 16
termios: RESZ 1; 60 bytes is needed i use 64 for alligment and it is easier to work with
extern multipurpuse_buf
extern term_rows
extern term_cols
extern gameboard_ptr
extern simulation_running
extern running_in_tty
section .data
cursor_rows: dw 1
cursor_cols: dw 1
global simulation_speed
simulation_speed dd 1.0
section .rodata
extern reset
cursor_up: db ESC_CHAR, "[1A", 0
cursor_down: db ESC_CHAR, "[1B", 0
cursor_right: db ESC_CHAR, "[1C", 0
cursor_left: db ESC_CHAR, "[1D", 0
cursor_color: db ESC_CHAR, "[45m", 0
speed_multiplier dd 50.0
arrow_switch_statement:
dq handle_user_input.arrow_up
dq handle_user_input.arrow_down
dq handle_user_input.arrow_right
dq handle_user_input.arrow_left
section .text
extern print_str
extern step_simulation
extern unsigned_int_to_ascii
extern print_game_ui
extern string_copy
global handle_user_input
handle_user_input:; main loop of the program
push r12
push r13
push r14
lea r12, [multipurpuse_buf]
.main_loop:
xor r13, r13
; put the cursor where it should be
call print_cursor
xor rax, rax
mov qword [r12], rax; zeroout the buffer
mov rax, SYS_POLL
mov dword [r12], STDIN; create pollfd struct
mov word [r12+4], POLLIN
mov rdi, r12
mov rsi, 1; only one file descriptor is provided
movss xmm0, [speed_multiplier]
movss xmm1, [simulation_speed]
mulss xmm0, xmm1; callculate sleep lenght
cvttss2si rdx, xmm0; truncate and copy to rdx
mov r14, rdx
syscall
mov sil, [running_in_tty]
test sil, sil
jz .skip_tty_mul
push rax
mov rax, 2500; magic number
xor rdx,rdx
mul r14
mov r14, rax
pop rax
.skip_tty_mul:
test rax, rax; SYS_POLL returns 0 when no change happens within timeout
jz .no_input
.repeat_read:
xor rax, rax
mov qword [r12], rax; zeroout the buffer
mov rax, SYS_READ
mov rdi, STDIN
lea rsi, [r12]
mov rdx, 8; size of multipurpuse buffer
syscall; read user input
cmp rax, EAGAIN
jne .handle_input
mov al, [running_in_tty]
test al, al
jz .no_input
; this runs only if running in tty
test r14, r14
jz .no_input; timeout
dec r14
jmp .repeat_read
.handle_input:
mov rax, [r12]
cmp eax, 0x00415B1B; check if input is more than left arrow
jl .handle_single_byte_chars
bswap eax
sub eax, 0x1B5B4100
shr eax, 8
cmp al, 3
ja .no_input
mov r9w, [term_rows]
dec r9w
mov r10w, [term_cols]
jmp [arrow_switch_statement+(rax*8)]; lets hope this works
.arrow_up:
dec word [cursor_rows]
jnz .move_cursor_up
inc word [cursor_rows]
jmp .end_input_handling
.move_cursor_up:
lea rdi, [cursor_up]
call print_str
jmp .end_input_handling
.arrow_down:
mov r8w, [cursor_rows]
inc r8w
cmp word r8w, r9w
ja .end_input_handling
mov word [cursor_rows], r8w
lea rdi, [cursor_down]
call print_str
jmp .end_input_handling
.arrow_right:
mov r8w, [cursor_cols]
inc r8w
cmp word r8w, r10w
ja .end_input_handling
mov word [cursor_cols], r8w
lea rdi, [cursor_right]
call print_str
jmp .end_input_handling
.arrow_left:
dec word [cursor_cols]
jnz .move_cursor_left
inc word [cursor_cols]
jmp .end_input_handling
.move_cursor_left:
lea rdi, [cursor_left]
call print_str
jmp .end_input_handling
.handle_single_byte_chars:
cmp al, 0xa; NEWLINE (enter key)
jne .check_p
xor rax, rax; zeroout rax
mov ax, [cursor_rows]
dec ax
mul word [term_cols]
mov cx, [cursor_cols]
dec cx
add ax, cx
mov rdi, [gameboard_ptr]
add rdi, rax
mov cl, [rdi]
cmp cl, '#'
je .hashtag_present
mov byte [rdi], '#'
jmp .end_input_handling
.hashtag_present:
mov byte [rdi], ' '
jmp .end_input_handling
.check_p:
cmp al, 'p'
jne .check_j
xor byte [simulation_running], 0x01; switch simulation on or off
jmp .end_input_handling
.check_j:
cmp al, 'j'
jne .check_k
movss xmm0, [simulation_speed]
mov eax, 0x3DCCCCCD; 0.1f
vmovd xmm1, eax
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:
cmp al, 'k'
jne .check_q
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:
cmp al, 'q'
jne .end_input_handling
jmp .function_exit
ret; exit if q pressed
.end_input_handling:
mov r13b, 1
.no_input:
mov al, [simulation_running]
test al, al
jz .dont_step
call step_simulation
mov r13b, 1
.dont_step:
test r13b, r13b
jz .main_loop
call print_game_ui
jmp .main_loop
.function_exit:
pop r14
pop r13
pop r12
ret
global disable_canonical_mode_and_echo
disable_canonical_mode_and_echo:
mov rax, SYS_IOCTL
mov rdi, STDIN
mov rsi, TCGETS
lea rdx, [termios]
syscall
; save original termios struct
%ifdef AVX2
%ifdef AVX512
vmovdqa64 zmm0, [termios]
%else
vmovdqa ymm0, [termios]
vmovdqa ymm1, [termios+32]
%endif
%else
vmovdqa xmm0, [termios]
vmovdqa xmm1, [termios+16]
vmovdqa xmm2, [termios+32]
vmovdqa xmm3, [termios+64]
%endif
mov eax, [termios+12]; get c_lflag
and eax, NOT_ECHO; disable ECHO
and eax, NOT_ICANON; disable ICANON
mov [termios+12], eax
mov rax, SYS_IOCTL
mov rdi, STDIN
mov rsi, TCSETS
lea rdx, [termios]
syscall
; load original termios struct
%ifdef AVX2
%ifdef AVX512
vmovdqa64 [termios], zmm0
%else
vmovdqa [termios], ymm0
vmovdqa [termios+32], ymm1
%endif
%else
vmovdqa [termios], xmm0
vmovdqa [termios+16], xmm1
vmovdqa [termios+32], xmm2
vmovdqa [termios+64], xmm3
%endif
ret
global reset_terminal
reset_terminal:
mov rax, SYS_IOCTL
mov rdi, STDIN
mov rsi, TCSETS
lea rdx, [termios]
syscall
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
+106 -6
View File
@@ -1,12 +1,35 @@
%include "symbols.asm"
section .bss
multipurpuse_buf: RESB 8
section .bss
global multipurpuse_buf
multipurpuse_buf: RESB 16
global term_rows
term_rows: RESW 1
global term_cols
term_cols: RESW 1
section .data
global gameboard_ptr
gameboard_ptr: RESQ 1
global gameboard_size
gameboard_size: RESQ 1
extern cursor_rows
extern cursor_cols
global running_in_tty
running_in_tty: RESB 1
section .rodata
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
extern print_str
@@ -14,6 +37,14 @@ extern unsigned_int_to_ascii
extern init_alloc
extern alloc
extern init_gameboard
extern print_game_ui
extern handle_user_input
extern disable_canonical_mode_and_echo
extern reset_terminal
global _start
_start:
; get terminal dimensions
@@ -31,23 +62,92 @@ _start:
; handle args
pop rcx; get argc (number of arguments)
pop rax; get rid of program name arugument
cmp rcx, 1
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:
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
xor rax, rax
xor rcx, rcx
mov ax, [term_rows]
dec ax; one less than terminal size for statusbar
mov cx, [term_cols]
mul rcx
mov rdi, rax
mov qword [gameboard_size], rax
inc rdi; addition byte for NULL BYTE
lea rax, [resetLen]
add rdi, rax
add rdi, ESC_chars_compensation_Len
call alloc
mov r15, rax; stores pointer to gameboard array
mov [gameboard_ptr], rax; stores pointer to gameboard array
call init_gameboard
; make stdin non-blocking in case polling somehow fails, or am i stupid
mov rax, SYS_FCNTL
mov rdi, STDIN
mov rsi, F_SETFL
mov rdx, O_NONBLOCK
syscall
lea rdi, [hide_cursor]
call print_str
call print_game_ui
call disable_canonical_mode_and_echo
call print_game_ui
call handle_user_input
call reset_terminal
lea rdi, [show_cursor]
call print_str
.exit_program:
mov rax, SYS_EXIT
mov rdi, 0 ; return code
syscall
+111 -4
View File
@@ -7,7 +7,7 @@ print_str: ; takes pointer to string in rdi and retuns in rax
push rsi
push rdx
mov rsi, rdi
mov rdx, 0
xor rdx, rdx
.count_loop:
cmp byte [rsi+rdx], 0
@@ -24,8 +24,8 @@ print_str: ; takes pointer to string in rdi and retuns in rax
ret
global unsigned_int_to_ascii
unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi DOES NOT BOUNDS CHECK
mov r11, 0
unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi DOES NOT BOUNDS CHECK return len of string in rax
xor r11, r11
mov rcx, 10
mov rax, rsi
@@ -41,7 +41,7 @@ unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi D
.loop_count_exit:
push rax
mov rcx, 0
xor rcx, rcx
.store_loop: ; basicly for loop
cmp rcx, r11
@@ -60,3 +60,110 @@ unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi D
ret
global string_copy
string_copy:; takes pointer to destination in rdi and pointer to source in rsi and return lenght in rax
xor rax, rax
xor rcx, rcx
.copy_next_byte:
mov byte cl, [rsi+rax]
test cl, cl
jz .exit
mov [rdi+rax], cl
inc rax
jmp .copy_next_byte
.exit:
ret
global memory_set:
memory_set:; takes destination in rdi, byte in sil and lenght in rdx
; first check if value is 16 byte alligned
mov r9, rdi; move destination to r9
mov r11, 0x0101010101010101; to extend across whoule register
movzx rsi, sil
imul r11, rsi; to extend across whoule register
cmp rdx, 16
jnl .write_16_or_more_bytes
mov rcx, rdx
jmp .write_less_than_16_bytes
.write_16_or_more_bytes:
mov rax, rdi; move destination to rax
and rax, 0xF; offset is stored in rax
test al, al; check if resault is 0
jz .addr_is_16_Byte_alligned
mov cl, 16
sub cl, al; now offset to first higher 16 byte alligned address is stored in r8
movzx rcx, cl; remove ani posible garbage
.write_less_than_16_bytes:
mov rax, r11
sub rdx, rcx; we will write these bytes now
rep stosb
.addr_is_16_Byte_alligned:
mov r10, rdx
shr r10, 4; set it to how many 128bit(16Byte) chunk we need
test r10, r10; check if we need to write aditional 16 bytes at all
jz .function_exit
%ifdef AVX512
vpbroadcastq xmm8, r11
%else
movq xmm8, r11
shufpd xmm8, xmm8, 0x00
%endif
.move_16_bytes:
movdqa [rdi], xmm8
add rdi, 16
sub rdx, 16
cmp rdx, 16; test if rdx is less than 16
jge .move_16_bytes
.function_exit:
test rdx, rdx; test if rdx is 0
jz .true_function_exit
mov cl, dl
jmp .write_less_than_16_bytes
.true_function_exit:
mov rax, r9; return pointer to memory area same as memset in libc
ret
global memory_copy:
memory_copy:; takes destination in rdi, source in rsi and lenght in rdx
; first check if value is 16 byte alligned
mov r9, rdi
mov rcx, rdx
shr rcx, 3; calculate how many 8 byte chunks we need
and rdx, 0x7; calculate the reminder
rep movsq; move as many 8 byte chunks as posible
mov rcx, rdx
rep movsb; move the rest
mov rax, r9; return pointer to memory area same as memcpy in libc
ret
+19
View File
@@ -1,9 +1,28 @@
SYS_EXIT equ 60
SYS_IOCTL equ 16
SYS_READ equ 0
SYS_WRITE equ 1
SYS_BRK equ 12
SYS_FCNTL equ 72
SYS_POLL equ 7
SYS_NANOSLEEP equ 35
STDIN equ 0
STDOUT equ 1
TIOCGWINSZ equ 0x5413
TCGETS equ 0x5401
TCSETS equ 0x5402
F_SETFL equ 4
O_NONBLOCK equ 2048
POLLIN equ 0x0100; compensate for litle endian
NOT_ECHO equ -9
NOT_ICANON equ -3
EAGAIN equ -11
ASCII_ZERO equ 48
ESC_CHAR equ 27
ESC_chars_compensation_Len equ 9; i have to compensate for escape sequences that dont get printed why 11 exactly, I dont know