23 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
8 changed files with 523 additions and 118 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)
+5
View File
@@ -8,6 +8,11 @@ DEBUG_LD_FLAGS := -g
DEBUG_NASM_FLAGS := -g -F dwarf DEBUG_NASM_FLAGS := -g -F dwarf
# check for avx2 support # 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) ifeq ($(shell grep -o 'avx512[^ ]*' /proc/cpuinfo | head -n 1),avx512)
NASM_FLAGS += -DAVX512 NASM_FLAGS += -DAVX512
endif endif
+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
```
+127 -38
View File
@@ -14,27 +14,45 @@ 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, "[30;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
stop_str: db "STOP ", 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 section .text
extern print_str extern print_str
extern string_copy extern string_copy
extern memory_set extern memory_set
extern memory_copy
extern alloc extern alloc
extern unsigned_int_to_ascii
global init_gameboard global init_gameboard
init_gameboard: init_gameboard:
@@ -81,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]
@@ -93,75 +112,145 @@ 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
ret ret
%macro check_if_hashtag 1 %macro check_if_hashtag 2
cmp r8, %1 cmp %1, r8
jl +7 jl .no_count_%2
cmp r9, %1 cmp %1, r9
ja +5 ja .no_count_%2
mov r11b, [%1] mov r11b, [%1]
cmp r11b, '#' cmp r11b, '#'
jne +2 jne .no_count_%2
inc dl inc dl
.no_count_%2:
%endmacro %endmacro
global step_simulation: global step_simulation:
step_simultion: step_simulation:
mov rdi, [next_frame_ptr]; destination mov rdi, [next_frame_ptr]; destination
mov rsi, [gameboard_ptr]; source mov rsi, [gameboard_ptr]; source
mov rcx, [gameboard_size]; number of iterations mov rcx, [gameboard_size]; number of iterations
mov r8, rsi; store lowest address posible so we are not checking out of bounds mov r8, rsi; store lowest address posible so we are not checking out of bounds
mov r9, rsi mov r9, rsi
add r9, rcx; store higest address posible so we are not checking out of bounds add r9, rcx; store higest address posible so we are not checking out of bounds
mov r10, [term_cols] 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 ;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 rax, rax; this shouldn't be needed but just to be sure
xor r11, r11 xor r11, r11
xor rdx, rdx; we will use dl as # counter xor rdx, rdx; we will use dl as # counter
.for_every_column_on_gameboard: .for_every_column_on_gameboard:
mov al, [rdi]; NOTE to self if i need extra register i can shift this to ah and free up r11 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 rdi inc rsi
check_if_hashtag rdi check_if_hashtag rsi, 1; check column to the to the right
dec rdi dec rsi
check_if_hashtag rdi-1 dec rsi
check_if_hashtag rsi, 2; check the one to the left
inc rsi
add rsi, r10
add rdi, r10
check_if_hashtag rdi 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 rdi
check_if_hashtag rdi inc rsi
dec rdi test rcx, rcx
jnz .for_every_column_on_gameboard
check_if_hashtag rdi-1 mov rsi, [next_frame_ptr]; source
mov rdi, [gameboard_ptr]; destination
mov rdx, [gameboard_size]; number of iterations
sub rdx, r10; remove statusbar
sub rdi, r10 call memory_copy
sub rdi, r10
check_if_hashtag rdi
inc rdi
check_if_hashtag rdi
dec rdi
check_if_hashtag rdi-1
add rdi, r10
; TODO create jump table
ret ret
+272 -31
View File
@@ -1,8 +1,8 @@
%include "symbols.asm" %include "symbols.asm"
section .bss section .bss
cursor_rows: RESW 1; TODO DONT FORGET TO INICIALIZE alignb 16
cursor_cols: RESW 1 termios: RESZ 1; 60 bytes is needed i use 64 for alligment and it is easier to work with
extern multipurpuse_buf extern multipurpuse_buf
@@ -12,14 +12,24 @@ section .bss
extern gameboard_ptr extern gameboard_ptr
extern simulation_running extern simulation_running
section .data
cursor_rows: 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
@@ -30,84 +40,141 @@ section .rodata
section .text section .text
extern print_str extern print_str
extern step_simulation
extern unsigned_int_to_ascii
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 r13
lea r12, [multipurpuse_buf]
.main_loop: .main_loop:
xor r13, r13
; put the cursor where it should be
call print_cursor
xor rax, rax xor rax, rax
mov qword [multipurpuse_buf], rax; zeroout the buffer mov qword [r12], rax; zeroout the buffer
mov rax, SYS_POLL mov rax, SYS_POLL
mov rdi, STDIN mov dword [r12], STDIN; create pollfd struct
mov word [r12+4], POLLIN
mov rdi, r12
mov rsi, 1; only one file descriptor is provided mov rsi, 1; only one file descriptor is provided
mov rdx, 0; 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
jz .no_input jz .no_input
xor rax, rax
mov qword [r12], rax; zeroout the buffer
mov rax, SYS_READ mov rax, SYS_READ
mov rdi, STDIN mov rdi, STDIN
lea rsi, [multipurpuse_buf] lea rsi, [r12]
mov rdx, 8; size of multipurpuse buffer mov rdx, 8; size of multipurpuse buffer
syscall; read user input syscall; read user input
mov rax, [multipurpuse_buf] cmp rax, EAGAIN
shr rax, 5; we need only 3 bytes for this inpus sceame je .no_input
cmp eax, 0x001B5B44; check if input is more than left arrow mov rax, [r12]
ja .handle_single_byte_chars
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]
sub eax, 0x1B5B41
jmp [arrow_switch_statement+(rax*8)]; lets hope this works jmp [arrow_switch_statement+(rax*8)]; lets hope this works
.arrow_up: .arrow_up:
dec word [cursor_rows] dec word [cursor_rows]
jnz .move_cursor_up
inc word [cursor_rows]
jmp .end_input_handling
.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:
inc word [cursor_rows] mov r8w, [cursor_rows]
inc r8w
cmp word r8w, r9w
ja .end_input_handling
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:
inc word [cursor_cols] mov r8w, [cursor_cols]
inc r8w
cmp word r8w, r10w
ja .end_input_handling
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
inc word [cursor_cols]
jmp .end_input_handling
.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:
shr eax, 2; get the char to al
cmp al, 0xa; NEWLINE (enter key) cmp al, 0xa; NEWLINE (enter key)
jne .check_p jne .check_p
xor rax, rax; zeroout rax xor rax, rax; zeroout rax
mov ax, [cursor_rows] mov ax, [cursor_rows]
mul dword [term_cols] dec ax
add rax, [cursor_cols] mul word [term_cols]
mov cx, [cursor_cols]
dec cx
add ax, cx
lea rdi, [gameboard_ptr+rax] mov rdi, [gameboard_ptr]
add rdi, rax
mov cl, [rdi] mov cl, [rdi]
cmp cl, '#' cmp cl, '#'
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'
@@ -115,27 +182,201 @@ 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 .no_input jne .check_q
movss xmm0, [simulation_speed]
mov eax, 0x3DCCCCCD; 0.1f
vmovd xmm1, eax
; TODO implement simulation speed 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: .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 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 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
+65 -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
@@ -19,11 +19,18 @@ 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
@@ -33,6 +40,11 @@ extern alloc
extern init_gameboard extern init_gameboard
extern print_game_ui extern print_game_ui
extern handle_user_input
extern disable_canonical_mode_and_echo
extern reset_terminal
global _start global _start
_start: _start:
; get terminal dimensions ; get terminal dimensions
@@ -50,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
@@ -80,12 +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 print_game_ui
call handle_user_input
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
+9 -45
View File
@@ -24,7 +24,7 @@ print_str: ; takes pointer to string in rdi and retuns in rax
ret ret
global unsigned_int_to_ascii global unsigned_int_to_ascii
unsigned_int_to_ascii: ; takes pointer to array in rdi and value stored in rsi DOES NOT BOUNDS CHECK 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 xor r11, r11
mov rcx, 10 mov rcx, 10
mov rax, rsi mov rax, rsi
@@ -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
@@ -154,52 +154,16 @@ memory_copy:; takes destination in rdi, source in rsi and lenght in rdx
mov r9, rdi mov r9, rdi
cmp rdx, 16 mov rcx, rdx
jnl .write_16_or_more_bytes shr rcx, 3; calculate how many 8 byte chunks we need
mov rcx, rdx and rdx, 0x7; calculate the reminder
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
rep movsq; move as many 8 byte chunks as posible
test al, al; check if resault is 0
jz .addr_is_16_Byte_alligned
mov cl, 16 mov rcx, rdx
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: rep movsb; move the rest
sub rdx, rcx; we will write these bytes now
rep movsb
.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
.move_16_bytes:
movdqa xmm8, [rsi]
movdqa [rdi], xmm8
add rdi, 16
add rsi, 16
sub rdx, 16
cmp rdx, 16; test if rdx is less than 16 mov rax, r9; return pointer to memory area same as memcpy in libc
jge .move_16_bytes
.function_exit:
test rdx, rdx; test if rdx is 0
jz .true_function_exit
movzx rcx, dl
jmp .write_less_than_16_bytes
.true_function_exit:
mov rax, r9; return pointer to memory area same as memset in libc
ret ret
+9 -1
View File
@@ -5,14 +5,22 @@ 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
TIOCGWINSZ equ 0x5413 TIOCGWINSZ equ 0x5413
POLLIN equ 1 TCGETS equ 0x5401
TCSETS equ 0x5402
F_SETFL equ 4 F_SETFL equ 4
O_NONBLOCK equ 2048 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 ASCII_ZERO equ 48
ESC_CHAR equ 27 ESC_CHAR equ 27