38 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
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
PoliEcho 51ffd98872 added basic allocator 2025-07-07 20:39:13 +02:00
PoliEcho c1a55fa3ff created some basic string helper functions 2025-07-07 13:42:53 +02:00
PoliEcho aa86683b35 inital-commit 2025-07-07 11:37:59 +02:00
10 changed files with 1057 additions and 100 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)
+2
View File
@@ -1 +1,3 @@
.asm-lsp.toml
build build
src/*.o
+24 -6
View File
@@ -1,31 +1,49 @@
NASM = nasm NASM = nasm
LD = ld LD = ld
NASM_FLAGS := -felf64 NASM_FLAGS := -felf64 -Isrc -Ox -Ov -w+all -w-reloc-abs-dword -w-reloc-rel-dword
LD_FLAGS := --strip-all 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 SRC_PATH := src
OBJ_PATH := build/obj OBJ_PATH := build/obj
BIN_PATH := build/bin BIN_PATH := build/bin
BIN_NAME := asm-game-of-life
SRC_FILES := $(wildcard $(SRC_PATH)/*.asm) SRC_FILES := $(wildcard $(SRC_PATH)/*.asm)
OBJ_FILES := $(patsubst $(SRC_PATH)/%.asm,$(OBJ_PATH)/%.o,$(SRC_FILES)) OBJ_FILES := $(patsubst $(SRC_PATH)/%.asm,$(OBJ_PATH)/%.o,$(SRC_FILES))
all: make-build-dir $(BIN_PATH)/asm-game-of-life all: $(BIN_PATH)/$(BIN_NAME) | make-build-dir
debug: NASM_FLAGS += $(DEBUG_NASM_FLAGS)
debug: LD_FLAGS = $(DEBUG_LD_FLAGS)
debug: $(BIN_PATH)/$(BIN_NAME) | make-build-dir
make-build-dir: make-build-dir:
mkdir -p $(OBJ_PATH) mkdir -p $(OBJ_PATH)
mkdir -p $(BIN_PATH) mkdir -p $(BIN_PATH)
$(BIN_PATH)/asm-game-of-life: $(OBJ_FILES) $(BIN_PATH)/$(BIN_NAME): $(OBJ_FILES) | make-build-dir
$(LD) $(LD_FLAGS) $^ -o $@ $(LD) $(LD_FLAGS) $^ -o $@
$(OBJ_PATH)/%.o: $(SRC_PATH)/%.asm $(OBJ_PATH)/%.o: $(SRC_PATH)/%.asm | make-build-dir
$(NASM) $(NASM_FLAGS) $< -o $@ $(NASM) $(NASM_FLAGS) $< -o $@
clean: clean:
rm -fr build rm -fr build
+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
```
+25
View File
@@ -0,0 +1,25 @@
%include "symbols.asm"
section .bss
brk_pointer: RESQ 1
section .text
global init_alloc
init_alloc:; initialize allocator, optionaly return brk pointer in rax
mov rax, SYS_BRK
xor rdi, rdi
syscall
mov [brk_pointer], rax
ret
global alloc
alloc:; Takes lenght of data in rdi and returns pointer in rax
mov rax, SYS_BRK
mov qword rcx, [brk_pointer]
push rcx
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
+382
View File
@@ -0,0 +1,382 @@
%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
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
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
syscall
test rax, rax; SYS_POLL returns 0 when no change happens within timeout
jz .no_input
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
je .no_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 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
+140 -99
View File
@@ -1,115 +1,156 @@
SYS_WRITE equ 1 %include "symbols.asm"
SYS_BRK equ 12
SYS_EXIT equ 60
STDOUT equ 1
ESC_CHAR equ 27
ASCII_ZERO equ 48
section .bss section .bss
heap_ptr resp 1 global multipurpuse_buf
multipurpuse_buf: RESB 16
section .data global term_rows
hello: db ESC_CHAR, "[10;15Hhello suckers! :)", 10, 0 term_rows: RESW 1
test: db ESC_CHAR, "[20;25Hmore txt here", 10, 0 global term_cols
clear: db ESC_CHAR, "[2J", 0 term_cols: RESW 1
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 section .text
extern print_str
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 global _start
unsigned_int_to_acii: ; takes value stored in rdi
push rdx
push r12
push r13
mov r12, rdi
mov rax,SYS_BRK
mov rdi,0
syscall
mov [heap_ptr], rax
mov r13, 0
mov rax, r12
mov rcx, 10
.count_loop:
inc r13
cmp rax, 10
jl .loop_exit
xor rdx, rdx
div rcx
push rdx
jmp .count_loop
.loop_count_exit:
push rax
mov rdi, [heap_ptr]
add rdi, r13
inc rdi
mov rax, SYS_BRK
syscall
mov rdi [heap_ptr]
mov rcx 0
.store_loop: ; basicly for loop
cmp rcx, rdi
jnl .loop_store_exit
pop rax
add rax, ASCII_ZERO
mov rdx rdi
add rdx rcx
mov byte rdx, rax
inc rcx
jmp .store_loop
.loop_store_exit
add rdi rcx
mov byte rdi, 0
print_str: ; takes pointer to string in rdi and retuns in rax
push rsi
push rdx
mov rsi, rdi
mov rdx, 0
.count_loop:
cmp byte [rsi+rdx], 0
je .print
inc rdx
jmp .count_loop
.print:
mov rax,SYS_WRITE
mov rdi,STDOUT
syscall
pop rdx
pop rsi
ret
print_at_pos:
_start: _start:
mov rdi,clear ; get terminal dimensions
mov rax, SYS_IOCTL
mov rdi, STDOUT
mov rsi, TIOCGWINSZ
lea rdx, [multipurpuse_buf]
syscall
mov word ax, [multipurpuse_buf]; rows are stored at offset 0
mov [term_rows], ax
mov word ax, [multipurpuse_buf+2]; cols are stored at offset 2
mov [term_cols], ax
; handle args
pop rcx; get argc (number of arguments)
pop rax; get rid of program name arugument
cmp rcx, 1
jle .no_arguments_provided
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]
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 [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_str
mov rdi,hello call print_game_ui
call print_str
call disable_canonical_mode_and_echo
mov rdi,test
call print_game_ui
call handle_user_input
call reset_terminal
lea rdi, [show_cursor]
call print_str 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
+169
View File
@@ -0,0 +1,169 @@
%include "symbols.asm"
section .text
global print_str
print_str: ; takes pointer to string in rdi and retuns in rax
push rsi
push rdx
mov rsi, rdi
xor rdx, rdx
.count_loop:
cmp byte [rsi+rdx], 0
je .print
inc rdx
jmp .count_loop
.print:
mov rax, SYS_WRITE
mov rdi, STDOUT
syscall
pop rdx
pop rsi
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 return len of string in rax
xor r11, r11
mov rcx, 10
mov rax, rsi
.count_loop:
inc r11
cmp rax, 10
jl .loop_count_exit
xor rdx, rdx
div rcx
push rdx
jmp .count_loop
.loop_count_exit:
push rax
xor rcx, rcx
.store_loop: ; basicly for loop
cmp rcx, r11
jnl .loop_store_exit
pop rax
add rax, ASCII_ZERO
mov byte [rdi + rcx], al
inc rcx
jmp .store_loop
.loop_store_exit:
mov rax, r11
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
+28
View File
@@ -0,0 +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