From ea1e7547b0d0afc9a631791a20f507d07f5528f4 Mon Sep 17 00:00:00 2001 From: javalsai Date: Sun, 1 Dec 2024 16:43:57 +0100 Subject: [PATCH] FINALLY, parsing done --- 2024-asm/01/.gitignore | 2 + 2024-asm/01/build.sh | 5 + 2024-asm/01/main | Bin 0 -> 11464 bytes 2024-asm/01/main.asm | 505 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 512 insertions(+) create mode 100644 2024-asm/01/.gitignore create mode 100755 2024-asm/01/build.sh create mode 100755 2024-asm/01/main create mode 100644 2024-asm/01/main.asm diff --git a/2024-asm/01/.gitignore b/2024-asm/01/.gitignore new file mode 100644 index 0000000..bf2e3c0 --- /dev/null +++ b/2024-asm/01/.gitignore @@ -0,0 +1,2 @@ +/*.o +/input.txt diff --git a/2024-asm/01/build.sh b/2024-asm/01/build.sh new file mode 100755 index 0000000..d8421d4 --- /dev/null +++ b/2024-asm/01/build.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euxo pipefail + +nasm -f elf64 -o main.o main.asm +ld -o main main.o diff --git a/2024-asm/01/main b/2024-asm/01/main new file mode 100755 index 0000000000000000000000000000000000000000..bb2170f3807d931e681f5b510d881b7dc88d7f69 GIT binary patch literal 11464 zcmb<-^>JfjWMqH=CI&kOFi*e%ECeAL7&x@STrlClV8Ot`;K0Dnzy?;!0v3f4FdYzD z0c;op1B_-6fT#lrvx1mVJ_FP~7`=uWB+0-4qmlK2?NflrGbljpfzd)BgBchYU^KEm zHU=v>qaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFoZ+Eqw}dp^BV<^ZdV46<{!)@A|Crxpk3-+!3+!xFLyICFnDy=3cPRuF*;p; zcyyOa?B`-&V0iJ8iGjhR)AhrP4hZ9gM`!AT9iYJQ=&l8+d*RU?`hlO-qxC?EhKIH5 z2axHTVW#VWOpgT_+Wdy&f9Z=C6B!s7ULV*2>iC27^Rs$%*S_%RF8%PL0%U%->jMwX z2Obw+cyzkHcp(ZB0=vfb#S0Dy=YvPL>kE(W*dHFe7xEJKQU?1z;7bOxN-7+d(-7MNKP21WCFwFfi<3Vqjp{2XY@M zh<1S({Hz|$KN#u-J@%EuluLp_k`-**evpP2{0s~X`#~cgFIE5l{|{#E0CD+Q4|{YT z_xOL@gMXX2N9(21FCLo5Jvxthbp8U%gH`gg9)95jb`NZ@WIt$d#Iy60XY(Ne&;O^u z&hYsD-J|&zR}G6t^C5PR=0gUK9YUZmzwg=k(X;uWgRkbr!vQ-$8a@7>IMx6%$^az) zG2$@7Dvy1zahzQsck{D?r9Ae5RD=Aw3#1<^3U-^vJ|>u_q5eSxuj>zRXnE{shAPgCU z;9>O=DXhRg2m8^d^O{fRDSp<&Am@(a(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2k zHv|kSxb#y}%k-;Ki}D$yqm9jS{R>j_GV{_E)YbL$^rWK=a=E0V4Xuq0a|4R<3sQ>| z5{uGHb5rw5iWTzmOB4!<^2;()Qd6wB6cj>>6Vp?z6!i3S6EpJ^Y%=o-N=p<95=%1d z6l@Z6GSl-?bMs2S7`K5U!3i)XYNtGq3#bDJ6x(Y>5mFiH1>IylTd8u4!nR%JT8L25?d5|3- z(PGfZ2A;qK^)gu)KK@5n0@23I0PCs36K)S1^}>fk6q( zU}9i~b|1l91_lPm@(U&g*mwa<+zQP2_#ZTU0A@l7Uog$Y02@L8a~T*IV!(`#|3ST8 zFcV7TgJ~uP*x(PC%fP@;17>{u4;l*sGoeH;m}X*tjX8k13=9mjz>JUoK|>H=CX`qW zrkNOE-C{78fq?!IRb(8Qgf;y=;Ey`kca zLa5;o4HaiW6R(1b3!{nugo>-7iMK+<9nr+6K*ht*#J57llhDMELB(^?#BV^wi_yeC zL&aOr#Q#CXx1x#rf(EV_7#S|2iSt0k6@^j5M-VEmi6$-v71u)(*MW+=qKWrF#of@v zZK2}XXyPGI@p3frWTydaV|qaNq%vBaY+$FKuA!$K?H-JYq*c6pDRO@Ymk4ui)$Ez zZ?Jp3n}2|-pQoRDydfGl-pADsRmcd93s&J86a+HH&)+e~odKDHEDN>-CJW{u%lbO{ z`1m`+q#-QlS4S6^8iWW~or{w@$PFMBK7I@+JWP2vzhDnkH6RhNy7=Of z#G(?t?K2B;XQhK|q4&o4j`NGr|BiHFwNC=wu*@u_(!Fu|16%)Am5 z{i%7yrA4XnIWQGaK3Gp`MP>;DsIHGMNGvK&Ekb7N<$>%3nU5k0c6q!}UJAq#B+Ytx zspViUSP!Tr6Q7oulga>R>6InsWTwQYr7)xx73CJEGZYko9GjNHkX2e-5)a{lY(?km zC4(9>@g*O01JZ%h&Q88Bj_QsvlgugT!F%66iWt_N_84Tis6d_@B{h;a|Za0!T38;PvsK-ES zc5R_{fs{#r2nGfQP " + db 0x1b, "[0m", 10 + ERRMSG_NOARG_LEN: equ $ - ERRMSG_NOARG + ERRMSG_FOPEN: db 0x1b, "[1;31m", "Error opening", 0x1b, "[0m", 10 + ERRMSG_FOPEN_LEN: equ $ - ERRMSG_FOPEN + ERRMSG_MALLOC: db 0x1b, "[1;31m", "Error allocating memory", 0x1b, "[0m", 10 + ERRMSG_MALLOC_LEN: equ $ - ERRMSG_MALLOC + ERRMSG_UNFULLREAD: db 0x1b, "[1;31m", "Read an unaligned ammount of bytes", 0x1b, "[0m", 10 + ERRMSG_UNFULLREAD_LEN: equ $ - ERRMSG_UNFULLREAD + + DBGMSG_READLN: db " - read an 'aligned' line", 10 + DBGMSG_READLN_LEN: equ $ - DBGMSG_READLN + DBGMSG_READLNFNSH: db "finished reading lines", 10 + DBGMSG_READLNFNSH_LEN: equ $ - DBGMSG_READLNFNSH + +section .data + +section .text + global _start + +_start: + mov rbp, rsp + sub rsp, 32 + ; [rbp-8]: input fd + ; [rbp-16]: alignment + ; [rbp-24]: read buf + ; [rbp-32]: position of stack before the array alloc thing + ; basically pseudo stack frame + + mov rax, [rbp] ; argc + cmp rax, 3 + je .correct_args + mov rsi, ERRMSG_NOARG + mov rdx, ERRMSG_NOARG_LEN + jmp errmsg + .correct_args: + + mov rdi, [rbp+16] ; argv[1] + call open_file + mov [rbp-8], rax + + mov rsi, [rbp+24] ; argv[2] + mov rdi, 10 + call stoi ; num in rax + mov [rbp-16], rax + + call malloc ; takes rax too + ; and we get ptr in rax + mov [rbp-24], rax + + mov [rbp-32], rsp + .read_loop: + mov rax, OS_READ + mov rdi, [rbp-8] + mov rsi, [rbp-24] + mov rdx, [rbp-16] + syscall + test rax, rax + jz .read_loop_end + cmp rax, [rbp-16] + je .read_full_aligned + mov rsi, ERRMSG_UNFULLREAD + mov rdx, ERRMSG_UNFULLREAD_LEN + jmp errmsg + .read_full_aligned: + + ; so we pass an arg from stack + ; + reserving an additional entry + sub rsp, 8 + push qword [rbp-24] ; ptr + call line_parser + ; and we dont restore stack position + ; we store here until we know length + ; to malloc and get it out + + jmp .read_loop + .read_loop_end: + + ; and at this point we can redefine + ; [rbp-8]: input fd + ; [rbp-16]: alignment + ; [rbp-24]: read buf + ; but close all that before + mov rax, OS_CLOSE + mov rdi, [rbp-8] + syscall + mov rdi, [rbp-24] + mov rsi, [rbp-16] + call free + ; and now + ; [rbp-8]: list1 ptr + ; [rbp-16]: list2 ptr + ; [rbp-24]: each list size + + ; nooow, we have all that shii in stack + ; so we qalc the size (sub looks reversed bsc stack goes down) + mov rax, [rbp-32] + sub rax, rsp + shr rax, 1 ; and divide by 2 ("double list") + mov [rbp-24], rax + + call malloc + mov [rbp-8], rax + + mov rax, [rbp-24] + call malloc + mov [rbp-16], rax + + + ; and deinterlace lists from stack to the mem vecs + mov rax, [rbp-24] + mov rbx, [rbp-8] + mov rcx, [rbp-16] + .deint_loop: + sub rax, 8 + + pop r10 + pop r11 + mov [rbx+rax], r10 + mov [rcx+rax], r11 + + test rax, rax + jnz .deint_loop + + ; --dbg-- ensure stuff worked + ; rax = 0; rbx = qword[] list2 + mov r13, 0 + push rbx + .ensure_l: + cmp r13, [rbp-24] + je .ensure_end + + mov rbx, [rsp] + mov rax, [rbx+r13] + call ptos + call print_ptos + + add r13, 8 + jmp .ensure_l + .ensure_end: + pop rbx + ; --dbg-- + + ; exit + mov rdi, 0 + _exit: + mov rax, OS_EXIT + syscall + +; takes [rsp+8/rbp+16]: ptr +; returns: +; [rsp+8 /rbp+16]: 1st num +; [rsp+16/rbp+24]: 2nd num +line_parser: + push rbp + mov rbp, rsp + sub rsp, 8 ; no need for alignment + ; [rbp-8]: start of 2nd num + + ; nullify first space to stoi it + mov rax, [rbp+16] + .null_loop: + inc rax + cmp byte [rax], " " + jne .null_loop + mov byte [rax], 0 + ; now same but find the start + .start_2nd_loop: + inc rax + cmp byte [rax], " " + je .start_2nd_loop + mov [rbp-8], rax + ; and stoi also needs nullbyte, not newline + .newline_loop: + inc rax + cmp byte [rax], 10 ; 10 = '\n' + jne .newline_loop + mov byte [rax], 0 + + mov rdi, 10 + mov rsi, [rbp+16] + call stoi + mov [rbp+16], rax + mov rsi, [rbp-8] + call stoi + mov [rbp+24], rax + + mov rsp, rbp + pop rbp + ret + +; takes: +; rdi: char* path +; returns rax: fd +open_file: + push rbp + mov rbp, rsp + sub rsp, 8 ; reserve 8B + + mov qword [rbp-8], rdi + + mov rsi, MSG_FOPENING_1 + mov rdx, MSG_FOPENING_1_LEN + call print + mov rax, qword [rbp-8] + call just_print_null + mov rsi, MSG_FOPENING_2 + mov rdx, MSG_FOPENING_2_LEN + call print + + mov rax, OS_OPEN + mov rsi, O_RDONLY + mov rdi, [rbp-8] + mov rdx, 0 + syscall + ; fd in rax + + cmp rax, 0 + jg .valid_fd ; rax > 0 (signed) + mov rsi, ERRMSG_FOPEN + mov rdx, ERRMSG_FOPEN_LEN + jmp errmsg + .valid_fd: + + mov rsp, rbp + pop rbp + ret + +; takes: +; rsi: errmsg ptr +; rdx: errmsg len +errmsg: + mov rdi, FD_STDERR + call print_fd + mov rdi, 1 + jmp _exit +print: + mov rdi, FD_STDOUT +; same & rdi: fd +print_fd: + mov rax, OS_WRITE + syscall + ret + +; ---- printing +just_print_null: + mov rdi, rax, + .count_til_null: + inc rdi + movzx rdx, byte [rdi] + test rdx, rdx + jnz .count_til_null + sub rdi, rax +just_print: + mov rsi, rax + mov rdx, rdi + mov rax, OS_WRITE + mov rdi, FD_STDOUT + syscall + ret + +; ---- ptos +; pointer to string +; takes: +; rax: pointer +; returns: +; rsi: memory block (freeable when needed) +; r10: start ptr (within block) +; r9: str len +; garbage: +; rax: consumed integer +; rsi: 16 base :) +; notes: +; div => rdx:rax / r/m64 => rax(quot), rdx(remnd) +ptos: + call nullify_ptros_ptr + ; save registers + mov rsi, ptos_str + mov rdi, 16 + ; align rsi ptr (we write from end) + mov r10, rsi + add r10, 16 ; we do an extra number cuz alignment and less intructs + .ptos_iter: + dec r10 + mov rdx, 0 + div rdi + cmp rdx, 10 + jl .ptos_iter_after_alpha_shift + add rdx, 7 + .ptos_iter_after_alpha_shift: + add rdx, 48 + mov byte [r10], dl + test rax,rax + jnz .ptos_iter + .ptos_return: + mov r9, rsi + add r9, 64 + sub r9, r10 + ret +nullify_ptros_ptr: + push rax + mov rax, 16 + .npp_iter: + dec rax + mov [ptos_str+rax], byte '0' + test rax, rax + jnz .npp_iter + pop rax + ret +print_ptos: + mov rax, OS_WRITE + mov rdi, FD_STDOUT + mov rsi, PTR_0X + mov rdx, 2 + syscall + mov rax, OS_WRITE + mov rsi, ptos_str + mov rdx, 16 + syscall +print_newline: + mov rax, OS_WRITE + mov rdi, FD_STDOUT + mov rsi, NEWLINE + mov rdx, 1 + syscall + ret + + +; -- malloc +; takes: +; rax: size +; returns: +; rax: addr +; +; /dev/null's fd gets lost tho +; +malloc: + push rbp + mov rbp, rsp + sub rsp, 8 ; reserve 8B, no alignment needed + + mov qword [rbp-8], rax + + ; open /dev/null + mov rax, OS_OPEN + mov rdi, ZERO_DEV + mov rsi, O_RDWR + mov rdx, 0 + syscall + ; fd in rax + + ; mmap it + mov r8, rax ; fd into r8 + mov r9, 0 ; "off"? + mov rax, OS_MMAP + mov rdi, 0 + mov rsi, [rbp-8] + mov rdx, PROT_READ | PROT_WRITE + mov r10, MAP_PRIVATE + syscall + + mov rsp, rbp + pop rbp + ret + +; -- free +; takes: +; rdi: ptr +; rsi: size +free: + mov rax, OS_MUNMAP + syscall + ret + +; -- stoi / itos +; TODO: moar than 10 radix + +; string to interger (ik ppl call this atoi, but nvm) +; takes: +; string pointer (null terminated): rsi +; radix: rdi +; returns: +; rax: result +; garbage: +; rdx: last processed digit +; rsi: ptr to str final nullbyte+1 +; notes: +; mul => rdx:rax = rax * r/m64 +stoi: + mov rax, 0 + .stoi_parse_digit: + cmp byte [rsi], 0 + je .stoi_return ; compare + mul rdi ; shift radix + + mov rdx, [rsi] + and rdx, 0b1111 ; grab digit + add rax, rdx ; add digit to the number + inc rsi + jmp .stoi_parse_digit + .stoi_return: + ret + +; integer to string (idk how ppl name this, but I already got stoi) +; takes: +; rax: integer +; rdi: radix +; returns: +; rsi: memory block (freeable when needed) +; r10: start ptr (within block) +; r9: str len +; garbage: +; rax: consumed integer +; notes: +; div => rdx:rax / r/m64 => rax(quot), rdx(remnd) +itos: + ; save registers + push rax + push rdi + ; malloc some mem + mov rax, 64 ; page size (max representable value is 64 bits long, + ; a full 64 bit register with radix 2) + call malloc + test rax, rax + jnz .successful_malloc + ; allocation error likely? + mov rsi, ERRMSG_MALLOC + mov rdx, ERRMSG_MALLOC_LEN + jmp errmsg + .successful_malloc: + mov rsi, rax ; put malloc'd mem into rsi + ; restore registers + pop rdi + pop rax + + ; align rsi ptr (we write from end) + mov r10, rsi + add r10, 64 ; we do an extra number cuz alignment and less intructs + .itos_iter: + dec r10 + mov rdx, 0 ; is used as upper half of divide, so set to 0 + div rdi ; now rax holds the new shifted result by default and we get + ; the remainder in rdx to shift into number range (higher + ; than 10 radix will work, but range of letters will be broken) + add rdx, 48 ; '0' == 48 + mov byte [r10], dl ; lower(8) rdx + test rax,rax ; gotta run at least once to at least get a zero when rax = 0 + jnz .itos_iter + + .itos_return: + mov r9, rsi + add r9, 64 + sub r9, r10 + ret + +print_r10_r9: +print_last_itos: + mov rax, OS_WRITE + mov rdi, FD_STDOUT + mov rsi, r10 + mov rdx, r9 + syscall + ret