From 50451840b729c0def8940a68a9797ca86ff574b2 Mon Sep 17 00:00:00 2001 From: IgorCielniak Date: Thu, 18 Dec 2025 11:32:35 +0100 Subject: [PATCH] write_file --- a.out | Bin 10824 -> 11184 bytes a.sl | 2 +- build/a.asm | 13 + build/a.o | Bin 4096 -> 4240 bytes build/debug_addresses.asm | 521 +++++++++++++++++++++++++++++ build/debug_addresses.o | Bin 0 -> 5168 bytes build/str.asm | 503 ++++++++++++++++++++++++++++ build/str.o | Bin 0 -> 4816 bytes build/test_read_file.asm | 592 +++++++++++++++++++++++++++++++++ build/test_read_file.o | Bin 0 -> 5744 bytes build/test_write_buf.asm | 555 +++++++++++++++++++++++++++++++ build/test_write_buf.o | Bin 0 -> 5088 bytes build/test_write_file.asm | 594 ++++++++++++++++++++++++++++++++++ build/test_write_file.o | Bin 0 -> 5632 bytes hello.sl | 2 +- main.py | 1 - main.sl | 2 +- stat_offset | Bin 0 -> 15968 bytes stat_offset.c | 8 + stdlib/io.sl | 134 ++++++++ stdlib.sl => stdlib/stdlib.sl | 80 ++++- str.out | Bin 0 -> 11600 bytes str.sl | 8 + t.sl | 2 +- test.sl | 2 +- test_read_file.out | Bin 0 -> 11696 bytes test_read_file.sl | 33 ++ test_write_buf.sl | 8 + test_write_file.sl | 20 ++ tests/run_tests.py | 8 +- write | Bin 0 -> 11648 bytes write_buf_test | Bin 0 -> 11360 bytes 32 files changed, 3064 insertions(+), 24 deletions(-) create mode 100644 build/debug_addresses.asm create mode 100644 build/debug_addresses.o create mode 100644 build/str.asm create mode 100644 build/str.o create mode 100644 build/test_read_file.asm create mode 100644 build/test_read_file.o create mode 100644 build/test_write_buf.asm create mode 100644 build/test_write_buf.o create mode 100644 build/test_write_file.asm create mode 100644 build/test_write_file.o create mode 100755 stat_offset create mode 100644 stat_offset.c create mode 100644 stdlib/io.sl rename stdlib.sl => stdlib/stdlib.sl (81%) create mode 100755 str.out create mode 100644 str.sl create mode 100755 test_read_file.out create mode 100644 test_read_file.sl create mode 100644 test_write_buf.sl create mode 100644 test_write_file.sl create mode 100755 write create mode 100755 write_buf_test diff --git a/a.out b/a.out index 84b793a659b6d0ccb4e736df2a69444a68292cc5..9c30d5e02e35843ea55b84d3b9115de109492304 100755 GIT binary patch literal 11184 zcmeI2Uu;uV9LLZ8u@2A{MO?xjN>ULLs9OhtMPjB!&$)-)%YC6U@OX7q6_ZyrdyMg#%g>QW8N0SzdNAf^YgrAX^=uCJtu2|L zBwL7lifl4xE&;HQIxJG1QGYT&&W()8T>4?VIoQsP30!VJ&tzUNYU}{379|;xNgwNSYY@bp0(w7`vYy~h91?dQO)`mn`wI|%=tNd?mvZzvu>aY8@TgIz+<)d&V{UOG}afobv
I(yuJC-;YRImp$>pLwoc}>sm_AJA_;?_~)ASA9JZjWFV)Xtn~ z&Nbi!>on_3ae-i-t4ObPp4>ccC&kurPWNx69(zZehfc%3b{-mqoBAyLCbT6N`K?+p zzJKy-DEVnMzbzT`Lq)9WXk$;Xq&5-;R9AApoZYH^I$14(n5ZD<81F zs(^nX)W%29SYf!02Dtg*mLIS6;44g7##fwEf6f#NQ#If-bs9?21QwRZ#J+3=Yz1ru zYz1ruYz1ruYz1ru{VP`xO88iMK19zjXlJ zwkUj*{I@IoBJq6+zf3%<@b8HqR`{>PKUDZl;%60Jiwh6q{6XRO5Wk`D2Z=lH^Ye%@ zSweid!dDRYDtry`rxo5oykFr@5Fb)_7x7mV{w(n~72Zqyn8Fjp#}&Sd_!Wh}OuV4* z1H>2KU#ZVw;%gNC9`TI|KSn&EaQ-k0>$OYadGdcv;pd5;Q}`v~R}_AQ_zi_$CBArJ z<-C3;zFy(CiEmPPJwB(y__r#20r8y*Zz4XV@TJ5LD!hgGQHA@7uYRC%{Lc~ZQurY8 zsKO5t&nWx|=a9H7<9{#<|A_PJ1^$f_NCojBsAVTnZmA@^%@5=M%H=OGVyM z;XgSG|AqJgccuTkz+JG8@;fdW>=x&Dj?)3}T3oD}sq;EX{%U;IosP!BkKjLBp;R9; zQf4S=dgBQrvNLKLJ3_H^gbgH;VWY=b)htWC7EwwT8MKc@;)3?4%@o4~f+dZ3WFQue zM~p-~HYjL+G8#7x_=#$$o4mu(tx?%BmPqtdjOf<5DD_6;(bP7B-1wlv>3-4YKr(7Z zjP7)=sD_i!oO>j8M3SPE8VC_fCQN}0A2?Du9wn=p?%6KPzG8UvBeSm*$5#q&__~WB zWg#RBG$_Njnn-KdXbnqiOR3!2BOOR|qqV2Z8Yz|KS{QOE`ugPT`qJ@Y85dE648^I# z1j!MX6E|9=LP;nJ?__Dd{ZT1LvaA>hg^k{5OuEaewm$skQovilHpEj7O8<7jhiAcr!Z_-7@)`u6ILlHh{!k*8xA)|v1DLd z!{|=oCWRf(j0lEg%$pkQGeg~wn@N#xlO;2<(_~)m=7omxPW*5AVrY&>c=3Fae?PfI z+~W6|)D2;(F}4Is*dAZ8^2_a~Tx9b5O;N+YJu9z=p^9&JWqWz<)w_k?9ym+NFSUQ{ zyV65=JKQ2aN)yA+PuIf_`@*YHWDMWC%f1Qm?Bk`P=2VQ>U-`8FDvAp?pQ7(;SCl(L HS#AF}_QRa5 literal 10824 zcmeI2ZD?Cn7{^b$WTsm+nRcV-WEsn5g{|w_4%Rs|l}>IX1<~mchL>c?)@X85lACpt zO$V{COIDcB2@_vH^qcs}Nu3PWMLTqE&fyylWgi?4Uyv!%X@&Sa=R7C(=G0d3iyu4} za?W#p=Xp8jfA0;=?R|P{{J!RnFAI2@jxG*+wgrmHZeXAI;Bdl3iGCy(MX$7m;Qy#Vd~9_~sEG|a-^It))q>6JYA^iqoooHG+!00#Y>RCYuHM)^A1|4@9)KM`asK6c|t?E0$vqw&782ktVQ(}wd6 zgocdKi+1Y-{&0U6o1lNne-sKWa*;8%@fjc|#B|lIS?%X5G0HRSK#MVbsh`Jy`)A<( zHY8*HCl*1A4yDCL?flfjE~7U2!*XN8MZ@_rHvP-N(*VvNS_af`s>bN0(zh{Kx81^> z*8!gL-Lwcg&uW|xW6rg>b3W*&rTiF(Ilf30bpSFD3B<}0p*$!?%vm0ZIWQ$cII6@W zp_tPuc+A-m3C)_spg2Yk$VsRniq$hyEll8bhwnf^-GPY3yOx4bJ z62ir|i*RomERHK_!fngJo!-IpT39*<7zeK4WgIi6XXc`9o=lbH5u>mA4xYf^consC zt9a**&NKJIJaaG4GxyRwb1%AcMuoZOf$tC2?0{5o4GdP`q=GR>$_!T8NCVmT(s)Z` zq6IhUr(7Ps*vq$Yf4ajOwHQ4W9G`>>H#mOU2)^|Jd@dR*Kfx3F&weegpMiN!LG-D{ zZIyq5i)t%_Tw7VJ{J!VXh5=BqQ#iXHxffX-4xED+c`KlC#uvdSaU6n;d%SvfrdF$h zp%1NqRzNGD70?Q31+)TM0j+>m;6GMiD4osb!z1}ZHZ|``@Ta+tU8|{1OE_p^9rFM8 zxTEj~h`*-rM~P1=JW2d( zgk7X> zyrr#iUtbZwRpD2NuTc2U#CsL~2l4wA?&GiRKm$(^yazn*gJU*d%K5b#K56hCE6Be! z9Q9(>!TACfQuz8h?{DzmJO}Tu^Lrco<8$ywh#v_z`UilA@Fr8fmr|V1Ugt39%}m|b zD)LwJvt%igO|9o&^PP!ej+sR}QLsC$yqVscvCTb+Y$?s)`#)t4m+T_L23!iJl^)4v zthAZ8vik%bE@Uj*gpU{|lH{Gr?9Rx@Y(76sIWoH~VeQITnc|R1ZoE{gG%RYS3gFLC zeowj}tl~(5SRroTB4>nWv?kj5@)Y$T&6 zW%i^b+~C?hJEa3@XZGy$%%)wtx2qm5j9gCcE?2VZHl7PHpRlN4p5(CP#?2n7PytNg zU2yk1oRM-ATr-!*SS*#W6XLWpJhNS*HM41&N<+yMTow>7I@1Ob3xbG_6LA3~OS@Rz zGBMUPlSRB};JRXF8mlqZS=^Vi6G`apg6M~&WvBPrtdqNSLSVz~^REZDK_q^q@OJ|- zi@cvgIAE;)9-$b@*9mFF*h;W4et{(6sIbDKlkXLZ5&kXIc-#TQ0DNS;{C;T-3%`T% zeMB*wRUd1^Ej;T8g$266UzQZ_Ol}5*weV;c9mA*0vNj>!U0y9lBT90t=RKCd;P2wM OcL=YwUT3h?_`d*f=g%7e diff --git a/a.sl b/a.sl index f18d4fc..7588dc1 100644 --- a/a.sl +++ b/a.sl @@ -1,4 +1,4 @@ -import stdlib.sl +import stdlib/stdlib.sl : main "hello world" puts diff --git a/build/a.asm b/build/a.asm index 12c9dff..bf532f2 100644 --- a/build/a.asm +++ b/build/a.asm @@ -18,6 +18,19 @@ _start: mov rdi, rax mov rax, 60 syscall +word_strlen: + mov rsi, [r12] ; addr + mov rcx, 0 +strlen_loop: + mov al, [rsi + rcx] + cmp al, 0 + je strlen_done + inc rcx + jmp strlen_loop +strlen_done: + mov [r12], rcx ; len + ret + ret word_puts: ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value diff --git a/build/a.o b/build/a.o index 9d068215e1991b2d043ef83093b25f244c98e78a..6e22e17ba7d7abc4a3d497344e9c10b59c2e8dbe 100644 GIT binary patch delta 1429 zcmZ|MK}Zx)7zgn8#!YwG$wkt}fdm&8I!LfV7U`n9P+63$6c|ac1Q~&@o9jZCVuT3P z4mo^u>f%xn6j87p>JTKJqC;yCBnTyVh$5m8?2v3TZ~o1WAGC+}zW4j@H}B1x>CXB1 z{DQn;mk-IRz0xl~lPTTtoa}GwY!d3%-ssKll%^-LE0W&n$t_xwP9vGxVVR{fTHHL4 zc38vieB#-{+NLe_~I3VaBr@MXW_T& zq^dmpDf4TdTjCuHZld8AbNfGj7v3zlH#~rMFnQEt_n77+}vhPUuj%s;?Kn16!j znSX)L1>N0$1Hr>!;Mf-YIrAp9mZHkM1^$)!9{3ODd!03vBCS-7gsuIW+RYz&(bUKM z2>c}TLHK#*!|)>W9DK&}`ga&ZaGy0?g}-J#4PRwG3;)gh4!pI&e^;j%6QYbDxh)Xl z5j@4b0v}@j3O>X94SazzQNw!1(p97%nXkh|D0o~UzQcDh--IWaOLYxWbbEf$Tm4l8QqW<)OeXDoq9@* z*Qu;0?V&I&>-##UO2zTf3E@q-@j~IszxrZfqOz$U)hHcH${bC`4D%B9bGLWzF^siM dWhcECNZrH#sj0gX?`b(^wCC|Y?wNz%;4fnrep3Jd delta 1277 zcmZ|PJxClu6bJBm>qp#pr-vZxrP0$$RPf9N5o1n42>F1Z7AmBY(EJOqw3uAL)LNYh|XT5vi!ainy|2MlcyRb`<>AIyA z8cVIV)5p|doc1|PxjIbo)LuzQDU~VFMIWX5?BWe-vNHh#YLt(uow_+}bx@24tjN}) z^{|*TrCImB=^!=fb^7%Q{H-tEU|#@(BTd_~YNCVYdB3(vq8gdf7+3qOHx=lgSw=Lmk}2imgmU&4#bHK}Xi z6`Z!6J_l)oWv2V34&Exf5#A%b4L-=nw&Ny6`WWfF@B#Rm@R#tk@Dcct@Co>p=Qp3} zHG=9Qe`jX!1|AW<2!9~l`#PkO!q?D0Ti~5aZ6bJA5GeHpzAJnme#+5u$IXiLCsMn( za2rSPd&1A)wZebHW5WN!pL%}Rf65(>1{|s~wT2S`CtPn{v8C{@@H?A0r90a=t!tO5 zy?mj^FH9X~JJ`xS!IrJ%;3JE_SH`H9DddEo;Rd<8<~Ci1>nV=vbS^K=E$z=gvrx6e QiI7v%k6o1OB>#o|2jb6U)Bpeg diff --git a/build/debug_addresses.asm b/build/debug_addresses.asm new file mode 100644 index 0000000..baf9c7f --- /dev/null +++ b/build/debug_addresses.asm @@ -0,0 +1,521 @@ +section .text +%define DSTK_BYTES 65536 +%define RSTK_BYTES 65536 +%define PRINT_BUF_BYTES 128 +global _start +_start: + ; initialize data/return stack pointers + lea r12, [rel dstack_top] + mov r15, r12 + lea r13, [rel rstack_top] + call word_main + mov rax, 0 + cmp r12, r15 + je .no_exit_value + mov rax, [r12] + add r12, 8 +.no_exit_value: + mov rdi, rax + mov rax, 60 + syscall +word_c_40: + mov rax, [r12] + movzx rax, byte [rax] + mov [r12], rax + ret + ret +word_c_21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rbx], al + ret + ret +word_r_40: + mov rax, [r13] + sub r12, 8 + mov [r12], rax + ret + ret +word_strlen: + mov rax, [r12] ; addr + mov rcx, [r12 + 8] ; len + add r12, 16 ; pop len and addr + mov [r12], rcx ; push len + ret + ret +word_puts: + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel print_buf_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge .print_abs + neg rbx + mov r8, 1 +.print_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne .print_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp .print_sign +.print_digits: +.print_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne .print_loop +.print_sign: + cmp r8, 0 + je .print_finish + dec rsi + mov byte [rsi], '-' + inc rcx +.print_finish: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret + ret +word_push_data_start: + lea rax, [rel data_start] + sub r12, 8 + mov [r12], rax + ret + ret +word_push_print_buf_addr: + lea rax, [rel print_buf] + sub r12, 8 + mov [r12], rax + ret + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_write_buf: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_mkstr: + mov rax, [r12] ; ptr + mov rbx, [r12 + 8] ; len + mov [r12], rbx ; top = len + mov [r12 + 8], rax ; next = ptr + ret + ret +word_mkstr_copy: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr (source) + add r12, 16 ; pop len+addr + + ; compute cap = PRINT_BUF_BYTES - 1 (leave room for newline or NUL) + lea rdi, [rel print_buf] + mov rcx, 127 ; PRINT_BUF_BYTES-1 (PRINT_BUF_BYTES=128) + cmp rdx, rcx + cmova rdx, rcx ; rdx = min(len, cap) + + ; copy rdx bytes from rsi -> rdi using rep movsb + test rdx, rdx + jz .done_copy + ; save callee-saved r14, use it to hold base dest pointer + push r14 + mov r14, rdi ; r14 = base dest (print_buf) + mov rcx, rdx ; counter = copied length + cld + rep movsb + mov rbx, r14 ; move saved base into rbx for return + pop r14 ; restore original r14 + +.done_copy: + ; push copied length and pointer to print_buf (use saved rbx) + sub r12, 8 + mov [r12], rdx ; len + sub r12, 8 + mov [r12], rbx ; addr -> print_buf base + ret + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_main: + call word_push_print_buf_addr + call word_print_int + call word_push_data_start + call word_print_int + ; push 0 + sub r12, 8 + mov qword [r12], 0 + ret +section .data +data_start: +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/debug_addresses.o b/build/debug_addresses.o new file mode 100644 index 0000000000000000000000000000000000000000..b9fa9302dab1e8aa35e51110b18d1f3c76ce07c6 GIT binary patch literal 5168 zcmd6reQXp(6u{?bD_20SD#051M=_^CgtJ^h(txH-sO-jTLL!)GNSABxD3`W(b#IT- zqFQAImzw5 z`Mr;M^JZpu+nvp^CuRf!!f65VxbS)o6{67-Np2KDQSPJvO~kSAcL#HCoT0#IMX{o) zxGQEtAN|W1uMILlU7qosz|nLn|6PI-A%8yp-6ed{)ER#z`8hXU+Zs?5kDx3!QU0|! zL1^8(tIitGx%WFdjMJGN8!Ej}1M5W-azF zv7x0XU3n8shb3#6u!4HNJgg6l1U382@M@r;3M5+S6QSGX;X=XD>-n1S-ZJbr3w_{f z(5KDE!a)d8rQ35Hhy2EHP#gGL^gk6Fk{cv8gbOKR4Tb*3Si_gwS84Vs&He%1w82qp z&M@Zw8D2sar=`a%4{1Xy(D|5ByD4dQp-E0e8yFYcE48spP11+VkD^c0u~~3MgWPOw z^1|sm>a@v|ztw2VMm76;eeBO&rvO~oJ0B>7(*`f)F6)rDRVj^^0zO?ncNW}y+1O`w z`+Cg25UTh;rBcvTrM<TbU>-H_pzBqB?P|Uv3)T#ynM>$xHe-G)f zx8%N(L+bX%aFuUdrNn%22SQS$g!JY1l=GDt(ljuD-_X-R5O=DuC;1@x_2FvV-nzY> z0$`|WFoQv{F4a!*UKl!9dH{}*%mmYV$ln=T0s$q!;X#Wh?|?QoJ{6tkiv;IUYbYGY z3WxR;a9O-j{JQhcc#(3?di0Klf{z)6S{D+?J4==)P zSgT`=Ti{aFf;+Dz57izRsT;1u307$Kh+A2h=W?po>hSPvsi%sqmYg1B#q}6G5!!bW z4tQwaDR{bl0l!gg;YIn(D$1{vU8QHIq5cGTpP(Vt<5M5F1{hPpaWFS z23Po;I}Z=8IqyAFuQX3gPF^`U4wuC!9RNwXoGHh5i74R3*CJMOn>g!f_>YK@~xU%;JC@tc%wp?7FETt`zZ<^aRWhLK~`2J%rIdHvSx(CD} z7Dl~~10u?J6WKR1j_+K2^Q~ii1MybI1g7d}1KV|l7h@WG86Y*ae&k-MI z{3YUZ*hkfC#P4JL1LDgW|B!eCb92g5wd@l@vn%d8UK;^LB{_feuVKEvL6tm zjL#+hJLC5fpJ03;@oIKt9wr`T{88d78E+!q%6N=;ALAQ{?_s=^_^XU}5I@9t5AkD+ z_Ywb^@j>EO8GnU%kbV5VK|IX3TBm?$Wc)DMZ)E&9@okKc5PzQW^Tc0g{5#^`GX691 ztBhYGKEe1+;$ivmD-W%_+#()he5R~dKp2eQMZAac1;lqV{vh!^jMovzzZU#$74eT4 zZo*tcrr^&=E-yv)n_Mmrnyc%af}1Wc9((%~`~~9t@5Ti%QWZQmZfkA1R9E7W zM6xZ{VZ;*&GnvgMvyphVTNqg@Zd!DUq%%fxTgo!F#=CM!(VH<7M!T`R&XJxD!auXGnteZs<<0b3JhIRQ8ETO$)QVnWigeK8kL$eeM}O*V5p?ZAqP+;)t1{V zYp<*mxgI6-nkg%3fReZg1(2?ptw~c!+1@y@?oKGJf>JcvGd+F0A4z1O?w-cXSjxnR zCR{n4qL5auy;G^9Zcb=N>Zmt()XT_-wz(l4A?^q?6C=8UNPWVnPdM6To?PGV7|>ob z>f3$Vq$fLD&~SEOceh)TT-ud!@2ZgTG!2-ca;4oO)H`K0jd~i_^yb@>a>`+PVs|{1 z7QUsGViJZ(!07>dbu%m|nyHAoN#d@)a3uqMeN7%`=;P_fN9qK9vC4lp6mfO72Y_Ki zd-R1*Y}sB!2+fJpPv5df6n6Req>6Kf@d@HL8F%9Brbi2pf6d4J`P}kxH7^BrU;t=N K9A{ibh4>dq@85a= literal 0 HcmV?d00001 diff --git a/build/str.asm b/build/str.asm new file mode 100644 index 0000000..aba2433 --- /dev/null +++ b/build/str.asm @@ -0,0 +1,503 @@ +section .text +%define DSTK_BYTES 65536 +%define RSTK_BYTES 65536 +%define PRINT_BUF_BYTES 128 +global _start +_start: + ; initialize data/return stack pointers + lea r12, [rel dstack_top] + mov r15, r12 + lea r13, [rel rstack_top] + call word_main + mov rax, 0 + cmp r12, r15 + je .no_exit_value + mov rax, [r12] + add r12, 8 +.no_exit_value: + mov rdi, rax + mov rax, 60 + syscall +word_c_40: + mov rax, [r12] + movzx rax, byte [rax] + mov [r12], rax + ret + ret +word_c_21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rbx], al + ret + ret +word_r_40: + mov rax, [r13] + sub r12, 8 + mov [r12], rax + ret + ret +word_strlen: + mov rax, [r12] ; addr + mov rcx, [r12 + 8] ; len + add r12, 16 ; pop len and addr + mov [r12], rcx ; push len + ret + ret +word_puts: + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel data_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_write_buf: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_read_file: + ; stack: path_ptr (top), path_len (next) + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + add r12, 16 ; pop args + + ; open(path_ptr, O_RDONLY=0, mode=0) + mov rax, 2 ; syscall: open + mov rdi, rsi ; filename + xor rsi, rsi ; flags = O_RDONLY + xor rdx, rdx ; mode = 0 + syscall + mov r10, rax ; save open() result + cmp rax, 0 + jl .fail_open + mov r8, rax ; fd + + ; use lseek to determine file size: lseek(fd, 0, SEEK_END) + mov rax, 8 ; syscall: lseek + mov rdi, r8 ; fd + xor rsi, rsi ; offset = 0 + mov rdx, 2 ; SEEK_END + syscall + mov r11, rax ; save lseek() result + cmp rax, 0 + jl .close_fail_lseek + mov rsi, rax ; length = size + + ; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0) + mov rax, 9 ; syscall: mmap + xor rdi, rdi ; addr = NULL + ; rsi already holds length + mov rdx, 1 ; PROT_READ + mov r10, 2 ; MAP_PRIVATE + mov r8, r8 ; fd + xor r9, r9 ; offset = 0 + syscall + mov rbx, rax ; addr + mov r12, r12 ; (no-op, for debug) + mov rax, 3 ; syscall: close + mov rdi, r8 ; fd + syscall + cmp rbx, -4095 + jae .fail_mmap + sub r12, 16 + mov [r12], rsi ; len (rsi held length across syscall) + mov [r12 + 8], rbx ; addr + ret + +.close_fail_lseek: + mov rax, 3 + mov rdi, r8 + syscall + mov rax, r11 ; return lseek() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -1 + ret + +.fail_open: + mov rax, r10 ; return open() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -2 + ret + +.fail_mmap: + mov rax, -1 ; return mmap() error + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -3 + ret + ret +word_main: + ; push str_0 + sub r12, 8 + mov qword [r12], str_0 + ; push 6 + sub r12, 8 + mov qword [r12], 6 + call word_swap + call word_read_file + call word_write_buf + ; push 0 + sub r12, 8 + mov qword [r12], 0 + ret +section .data +data_start: +str_0: db 115, 116, 114, 46, 115, 108, 0 +str_0_len equ 6 +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/str.o b/build/str.o new file mode 100644 index 0000000000000000000000000000000000000000..5c58829ce7817c610523aea611e545b368f41f9f GIT binary patch literal 4816 zcmbW4Z){Ul6u@uYh8rMl3?WNcjK-Qkgt~PQTqL+D!}pRdAp(Ap@Y1c_Xz1G6zA}hg zL@I_yohAlj7XK!E;e(nO|5Z%1qqt?Di=rPeB!&plMKA%0OtWb{=ic-F^tkPVFX?;d z{?4C!@44sR_xem{WZP{%pRg~V*dpAPO@(N8MUvY^y{Prj|0iN!_*=r<+iz3gle%g} zpt>n;hc^1xFb;#07wWwiAMqWaL{sh`Apb*x20}r2|98&gi>9{!Ci1f%Jhx4tsO~{o zZm0fFQeyD24Ss}0qcRggc=EAJm0uauFeUGQ9hmW)pl1Ll23JYmg}`M%U*3OYyY z-dtY9v44R#f8DtBSn48eWFtDCQfg;NnpN(Q6VdXsVz@z@x!56n$oy0E={U6%?r4x( zrd6iKmo#gYv8zp5%X!VZpwIk%=rn+-qpN^IIPJ*A+!You4`yY|Fc@z|onsA&$2{p)Q&6`+rJ_j$DV6DzT(@=y z1OHK?6DA%!NeO+(Rgp_3!%$xsz-#F0Ac!*_SPI@rVP~)rS5>!mQUDCqC}$GD!8a;* zZy2g4-3QepM}osz>ut=egMbpCA84`QMzxvQh3HC8Bq&3zt^66Tt^ar#bLaNr)xENa z?)61DPx-@r~O-U1l}dL#Bk~Izd>Pj3g{D$g)cqj4Go}jHn_rHIrDJg*00^8L{1LU zAWxDap17JdqqW?EoeD=192T%E{VyB_u3M!do^lau0`#ZQ6fMf~yy?`eahW@q-&NTyTf>v$MYIl}h#z7#(al$S>4)ec3gLz$qbBuvsTyeJXI3 zBi1)n@E?TQLkZvwxR(2jeB;dl;W2zK`(>#GhyUC*lRhuMr<*{1)+d z7*_@26O)WDlWm{)nemmxZ!&%taX%}eHN@94-by^g_!i>37}tppF#b64VaA^%evI)L z@z)sdC;mR;`-x95ewg@W#$O~}VfPA^KZx`HYxp-P!1{E8q0pU6Bx4WYYcQJa z7e>~MW=wj7QfVW8AYmH&qsd%c45l+NqsQ3LY)j!5C1o52VUqEbq60ZIEAR#}Ge#;t zm`tSNMmm)|sOUf@kunYVsb;jBtYeA3gzcG3rw1rTqA#VS-b5;q-D{AU98@efp!yul zB+R(co$FQ2SO(msMS6ccqonL$lvpNhDrAJgkmOW?v}UenpHhdN@MuTsup1}r1~Ujp-EL7<`jdvg#oIEVZth96j2XJRKa0!IFf=0 and next is a pointer in [data_start, data_end] + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel data_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_write_buf: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_read_file: + ; stack: path_ptr (top), path_len (next) + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + add r12, 16 ; pop args + + ; open(path_ptr, O_RDONLY=0, mode=0) + mov rax, 2 ; syscall: open + mov rdi, rsi ; filename + xor rsi, rsi ; flags = O_RDONLY + xor rdx, rdx ; mode = 0 + syscall + mov r10, rax ; save open() result + cmp rax, 0 + jl .fail_open + mov r8, rax ; fd + + ; use lseek to determine file size: lseek(fd, 0, SEEK_END) + mov rax, 8 ; syscall: lseek + mov rdi, r8 ; fd + xor rsi, rsi ; offset = 0 + mov rdx, 2 ; SEEK_END + syscall + mov r11, rax ; save lseek() result + cmp rax, 0 + jl .close_fail_lseek + mov rsi, rax ; length = size + + ; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0) + mov rax, 9 ; syscall: mmap + xor rdi, rdi ; addr = NULL + ; rsi already holds length + mov rdx, 1 ; PROT_READ + mov r10, 2 ; MAP_PRIVATE + mov r8, r8 ; fd + xor r9, r9 ; offset = 0 + syscall + mov rbx, rax ; addr + mov r12, r12 ; (no-op, for debug) + mov rax, 3 ; syscall: close + mov rdi, r8 ; fd + syscall + cmp rbx, -4095 + jae .fail_mmap + sub r12, 16 + mov [r12], rsi ; len (rsi held length across syscall) + mov [r12 + 8], rbx ; addr + ret + +.close_fail_lseek: + mov rax, 3 + mov rdi, r8 + syscall + mov rax, r11 ; return lseek() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -1 + ret + +.fail_open: + mov rax, r10 ; return open() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -2 + ret + +.fail_mmap: + mov rax, -1 ; return mmap() error + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -3 + ret + ret +word_main: + ; push str_0 + sub r12, 8 + mov qword [r12], str_0 + ; push 13 + sub r12, 8 + mov qword [r12], 13 + call word_swap + call word_read_file + call word_dup + ; push 0 + sub r12, 8 + mov qword [r12], 0 + call word__3e + mov rax, [r12] + add r12, 8 + test rax, rax + jz L_if_false_0 + call word_write_buf + ; push 0 + sub r12, 8 + mov qword [r12], 0 + call word_exit +L_if_false_0: + call word_dup + ; push -2 + sub r12, 8 + mov qword [r12], -2 + call word__3d_3d + mov rax, [r12] + add r12, 8 + test rax, rax + jz L_if_false_1 + call word_drop + ; push str_1 + sub r12, 8 + mov qword [r12], str_1 + ; push 21 + sub r12, 8 + mov qword [r12], 21 + call word_puts + call word_swap + call word_puts + call word_exit +L_if_false_1: + call word_dup + ; push -1 + sub r12, 8 + mov qword [r12], -1 + call word__3d_3d + mov rax, [r12] + add r12, 8 + test rax, rax + jz L_if_false_2 + call word_drop + ; push str_2 + sub r12, 8 + mov qword [r12], str_2 + ; push 22 + sub r12, 8 + mov qword [r12], 22 + call word_puts + call word_swap + call word_puts + call word_exit +L_if_false_2: + call word_dup + ; push -3 + sub r12, 8 + mov qword [r12], -3 + call word__3d_3d + mov rax, [r12] + add r12, 8 + test rax, rax + jz L_if_false_3 + call word_drop + ; push str_3 + sub r12, 8 + mov qword [r12], str_3 + ; push 13 + sub r12, 8 + mov qword [r12], 13 + call word_puts + call word_exit +L_if_false_3: + ; push str_4 + sub r12, 8 + mov qword [r12], str_4 + ; push 25 + sub r12, 8 + mov qword [r12], 25 + call word_puts + call word_dup + call word_exit + ret +section .data +data_start: +str_0: db 47, 101, 116, 99, 47, 104, 111, 115, 116, 110, 97, 109, 101, 0 +str_0_len equ 13 +str_1: db 111, 112, 101, 110, 40, 41, 32, 102, 97, 105, 108, 101, 100, 58, 32, 101, 114, 114, 110, 111, 61, 0 +str_1_len equ 21 +str_2: db 102, 115, 116, 97, 116, 40, 41, 32, 102, 97, 105, 108, 101, 100, 58, 32, 101, 114, 114, 110, 111, 61, 0 +str_2_len equ 22 +str_3: db 109, 109, 97, 112, 40, 41, 32, 102, 97, 105, 108, 101, 100, 0 +str_3_len equ 13 +str_4: db 117, 110, 107, 110, 111, 119, 110, 32, 114, 101, 97, 100, 95, 102, 105, 108, 101, 32, 102, 97, 105, 108, 117, 114, 101, 0 +str_4_len equ 25 +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/test_read_file.o b/build/test_read_file.o new file mode 100644 index 0000000000000000000000000000000000000000..4d50246d918798de61737cb3915fb6c8f035df1d GIT binary patch literal 5744 zcmbW5eQXp(6u{?biv^XdiUbv7iD!TarFRD^3Z_*syXI;LR^uP)dhKoDa=UMS z?_*}(eC+H!wkmbolt@H)S47+_f|5st=m%VvcUo`dnuO~n6!E-wY6!kSI%ac_9 z7uZ3#Fb!+qhi%1cwt9#dJbBwuHFA+M*us>&{)J%1bAq0$FIE1nOdTDpF=8g_82O4ccqD4Oxy4x75R6M<2o)dej0n4j| zUi!5;q%Egn%@CqRcQ5c9%J;^awbGwrZqnRcn)@BP zXR3H0o^DY1fo|**|!f9K-EgsjQ-Oe;=ya@1~#u?M$ z5o(S5rS6_exd)<6)D+5wUY;4#%Z^G$U=L;$%rF?QM4fL9iN`$Y?wpwJf=We`2vRE3 zDY@?68*4dBiB6b!@FXSFAxA|HnG8d9VSunb?_`Sz=xsWQD1DgATRyuxCFK>*^$GOs~V~)Gv z*3yO3qpJ+rF70j~#_c8Aq`ABO0fK%mp?ocm4WBRdl(FTK)B3H?$JUYPw$ET*N4M>Q zMZFh(hqSq0%cWY^zKQIn1$G+hN5Fd|m|{3|r4ul*RtcyRw}sC`(;EsvWp8kV_xt?_ z;L5LptweSX(ja$|Vcc;wcT9`_0V@@@B-kuqRYsrL0$g`ThH;lmxuc-piKb{#k^9Xm z&D|q&r^Rb>zvz?(UG7L%d@ts+(&Zi>#yuC@q5SxG*Dyp*A{#$~whAsDQ-}OMbKw-vp|^AmeUW{cF5dt2Tg5^?i`S zX4MD4)f*qky)&!2otrd4wbe&M6q`{!e5T$pUfmor2{!>>Ak{nm2A_w(qPh~L9Z+p` zUdRDL)~b)46?0+8Bph=V#{By)@VOFWol0{^!%qAPp(_{xuf?X*yLer`;8^K?Q{)FsYyN`PzH~NcW^QaXZQIJP z5PbzF?VOGK`_ltH6-8^kl^?WPZ8M!Q`oLdCDcYv0$G^8Z<_1T!WztSswDlAUqOGv5 z;Mh*O2c$>()sxD$nM*5s-+eLx-+hhZRBa-CgM9O!t!bF>Kh5|H#AjgwL)Yt4jtI`* zA)a9N@}L2E?qqx)+27CjH^kR7evJ5&jGrK0W_*nJi;SyJf{1vV@#(T05qlX|{fvm8 z7{7|_Pcy!Nc$6J}lf)M=elzhl#&zO%G2Tslfbsi?Z(_WU_|uH%iND172I4yyf1LOz z<3q%cF|P6+5jDnNBl|1ZQhJN{^^AW+{7%Lz#Pf{rC;lkoM~FYm`1i#3G5!njV~qb! z{50eL62F3dbWD}~kBD0tSMwtx?q>WlvR}*i)xBo=Ldj^ZHyrI0<)%^Zy$zhniX@dH>2r z^c1tX%woqZIEH_8XiFFRg#o7y+o4CBl{d@{S;u%dohzDRFmGp!USmnSCne%avV8_; zikxXFI#6^90&fu0HY{^6m$ghIZ{;3QbimG9jsZVaO!ts=Cc8H4dFJx@0g91bYbmKO zYh?@T3^J3A$`l7wor8APF^!&LpDJc-aF-VOhfP~ag~2p2JMSoDB*2hlD@$6Z*t=e- z6MlHKBXuH(lL&$vi5@?sC!{@r8f7Gw5=mx^WX99R13B628Bo%VWN%1o2C_F6hBp*= zJXFs8Ma!3Q5EV^ZRAHXdVR;=ll3s>v5S6tZ^micZrNa)1-m#O+y<%H$E?+PWJkc7t zf@xABgQ+Gpc<$wnQW5GzI%|oPk?n(65Xfi`7vkYUB3wucJn7P0#@W{{MUaJbc--6Hdl-*V+z%P|_UogJd;9W#^`)CA literal 0 HcmV?d00001 diff --git a/build/test_write_buf.asm b/build/test_write_buf.asm new file mode 100644 index 0000000..dba1bc8 --- /dev/null +++ b/build/test_write_buf.asm @@ -0,0 +1,555 @@ +section .text +%define DSTK_BYTES 65536 +%define RSTK_BYTES 65536 +%define PRINT_BUF_BYTES 128 +global _start +_start: + ; initialize data/return stack pointers + lea r12, [rel dstack_top] + mov r15, r12 + lea r13, [rel rstack_top] + call word_main + mov rax, 0 + cmp r12, r15 + je .no_exit_value + mov rax, [r12] + add r12, 8 +.no_exit_value: + mov rdi, rax + mov rax, 60 + syscall +word_c_40: + mov rax, [r12] + movzx rax, byte [rax] + mov [r12], rax + ret + ret +word_c_21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rbx], al + ret + ret +word_r_40: + mov rax, [r13] + sub r12, 8 + mov [r12], rax + ret + ret +word_strlen: + mov rax, [r12] ; addr + mov rcx, [r12 + 8] ; len + add r12, 16 ; pop len and addr + mov [r12], rcx ; push len + ret + ret +word_puts: + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel data_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_write_buf: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_read_file: + ; stack: path_ptr (top), path_len (next) + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + add r12, 16 ; pop args + + ; open(path_ptr, O_RDONLY=0, mode=0) + mov rax, 2 ; syscall: open + mov rdi, rsi ; filename + xor rsi, rsi ; flags = O_RDONLY + xor rdx, rdx ; mode = 0 + syscall + mov r10, rax ; save open() result + cmp rax, 0 + jl .fail_open + mov r8, rax ; fd + + ; use lseek to determine file size: lseek(fd, 0, SEEK_END) + mov rax, 8 ; syscall: lseek + mov rdi, r8 ; fd + xor rsi, rsi ; offset = 0 + mov rdx, 2 ; SEEK_END + syscall + mov r11, rax ; save lseek() result + cmp rax, 0 + jl .close_fail_lseek + mov rsi, rax ; length = size + + ; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0) + mov rax, 9 ; syscall: mmap + xor rdi, rdi ; addr = NULL + ; rsi already holds length + mov rdx, 1 ; PROT_READ + mov r10, 2 ; MAP_PRIVATE + mov r8, r8 ; fd + xor r9, r9 ; offset = 0 + syscall + mov rbx, rax ; addr + mov r12, r12 ; (no-op, for debug) + mov rax, 3 ; syscall: close + mov rdi, r8 ; fd + syscall + cmp rbx, -4095 + jae .fail_mmap + sub r12, 16 + mov [r12], rsi ; len (rsi held length across syscall) + mov [r12 + 8], rbx ; addr + ret + +.close_fail_lseek: + mov rax, 3 + mov rdi, r8 + syscall + mov rax, r11 ; return lseek() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -1 + ret + +.fail_open: + mov rax, r10 ; return open() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -2 + ret + +.fail_mmap: + mov rax, -1 ; return mmap() error + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -3 + ret + ret +word_write_file: + ; stack: path_ptr (top), path_len, buf_ptr, buf_len + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + mov r14, [r12 + 16] ; buf_len + mov rbx, [r12 + 24] ; buf_ptr + add r12, 32 ; pop 4 args + + ; preserve buffer info in callee-saved regs (syscall clobbers rcx/r11) + mov r15, r14 ; r15 = buf_ptr + mov r13, rbx ; r13 = buf_len + + ; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666) + mov rdi, rsi ; filename + mov rsi, 577 ; flags = O_WRONLY(1)|O_CREAT(64)|O_TRUNC(512) + mov rdx, 438 ; mode = 0o666 + mov rax, 2 ; syscall: open + syscall + cmp rax, 0 + jl .fail_open + mov r9, rax ; save fd + + ; write(fd, buf_ptr, buf_len) -- use r15/r13 which survive syscalls + mov rax, 1 ; syscall: write + mov rdi, r9 ; fd + mov rsi, r15 ; buf_ptr + mov rdx, r13 ; buf_len + syscall + mov r10, rax ; save write result + cmp r10, 0 + jl .fail_write + + ; close(fd) + mov rax, 3 ; syscall: close + mov rdi, r9 + syscall + + sub r12, 8 + mov [r12], r10 ; return bytes_written + ret + +.fail_write: + mov rax, 3 ; close before returning error + mov rdi, r9 + syscall + sub r12, 8 + mov [r12], r10 ; return negative errno from write + ret + +.fail_open: + sub r12, 8 + mov [r12], rax ; return negative errno from open + ret + ret +word_main: + ; push str_0 + sub r12, 8 + mov qword [r12], str_0 + ; push 26 + sub r12, 8 + mov qword [r12], 26 + call word_write_buf + ; push 0 + sub r12, 8 + mov qword [r12], 0 + ret +section .data +data_start: +str_0: db 104, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 119, 114, 105, 116, 101, 95, 98, 117, 102, 32, 116, 101, 115, 116, 10, 0 +str_0_len equ 26 +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/test_write_buf.o b/build/test_write_buf.o new file mode 100644 index 0000000000000000000000000000000000000000..ca032b0fa94822bf4a49049754f3bd8b56fceac7 GIT binary patch literal 5088 zcmbW5Yitx%6oBv27E3|45du|+*0?5+z}g3h1VUP%X2$F$MykJ%aoe53%67NT&Qgda zf*TCO+F%SO5?_hohl$3-s8})4!qzqj0-`1+#76>A5J`%S)Y#hfoO{pAY!9VBoTM}7 ze&=z|J@+xQeXb?)@Qgq}xK}`|6MoC3LNxgz$xWhCl$X%|Ct_dtH zZO}&lGRC_q6A8VQ%^B)j3p7}PL<=4jx>Fu16kNTYUmV(BhV2%i=l-ZH z(dHweN(fP{J9Auz{N_-lmit@uY>M<^W+Kvy6DcCA3q4Jd)u(o^(VP>S^Aoyh`_9{Q z`Y`t|@D{8Xlpa++(t1~-^D(9NQqr74vmA()8xy-{X`>gKr4N~ZiayQ9s^E?W+1Xn0 z%;3yAt$6(EVy*tX=KP?K{<-G_fHV6S0EKYcz6;q)I^=E7lE%vc50=lZf=5X<&R4o~ zJ>r}RR!}Nb4Lv_Uq~~o_4BsBi3Rqz<-iSKS8VZkf(w)U2-2s(~CJ~fWmQ!-w*&M3A zNr_Hac<>}8^dV3{@jXQjN*iDEHDZ zw4U?;tR9&OrnR)RF}e%_N`QW##RYd*8y&k9onI0OmZ7$~@EOi+@K6D3=l4>odu1Bk z>(l7onnw5LG`cr@ot9U7#~VH7}Q!L?GWV~wM5tB&IGh~}Z% zxq-UASvbH7%^C0}2*$aB>a{l1H(TndVrwO*{X4lH`}%{2j>EbR9y$S=`Xv0F*Y5pB zZq-ToO=UOBx6@GH58nO$62qy>U4wY7;fbp`qgwq9*r{+N!C?WrGWg>2z;&m;4^O#>GX(l$Xo?mEdET^W&Y-NFR$r9o zMYA-BI{nf5lUUC})Vb7$XD+xyd+%6axLC}rhwNa(L49F;R~CGO2%Hj91)FsU=BEf( zA>y2y1Sb$`L;a|nr1%#VYTj^YQJ8Rd+YHo3ol)KS5k~oWGmPQbQ8?Y?xFIV%IoIos zI&>n=*@!a{aekL|&~yKYo_UnuSwOIVqYmtlDG=)9biw%p(oi|Rj8w@%z6<2b+L%n) zQx>+F$z-~=!%BD7c3TPCG}^KqwYHhD@f^h~Y@0i65st^~m75KCB?2Z=W@-b7qI zedQy>AN7%xT8VFA{3+tkF#a_04;kM>{9DEk5+7mwRpJYItS>of2Um-q|{SF+FT;BX7L7KP)FPHOly@+q6(rd2dGX(#g zxKMI7x!`!W$K^zOp_bl)*Li$$u4`_=TZr@DotSs^RPU*_Y$6$d0Nv%>%$*6_*bz%+P0^jU;zql%qRy2X>Xl@94Boj(Go@%(*3JmLK}^d?ncc}m z$~4lcJUZDbu!Y)!bH$#lAlVkEYvl+=+(B{JI#GLuQgvt6oBZ!oGE zx4>Omq<5H>k}};fVpiH#$Y=mVl2ZxN+S&H)O5NavM>|qC_;DKi;6_867t$4CuF&BM zD@kaK8;x-n*86f}yK6v2HyYbZw5Bh+b78ns(b?&at}~nRWSm45GM1ta(^QU>J8+}X zt&jzxvbOy3b|u_$SS6wviyIw@q-*Xr!|lm*#xy!&iKLOtm?jm{^7K-Z?sAt3Q}}~W z^Xd2Cx5F}oY^z+k%8%X|OQZyT8q(s%a`@V7!OEQRmY6h`-z1oYC|@4r$n= literal 0 HcmV?d00001 diff --git a/build/test_write_file.asm b/build/test_write_file.asm new file mode 100644 index 0000000..841bc91 --- /dev/null +++ b/build/test_write_file.asm @@ -0,0 +1,594 @@ +section .text +%define DSTK_BYTES 65536 +%define RSTK_BYTES 65536 +%define PRINT_BUF_BYTES 128 +global _start +_start: + ; initialize data/return stack pointers + lea r12, [rel dstack_top] + mov r15, r12 + lea r13, [rel rstack_top] + call word_main + mov rax, 0 + cmp r12, r15 + je .no_exit_value + mov rax, [r12] + add r12, 8 +.no_exit_value: + mov rdi, rax + mov rax, 60 + syscall +word_c_40: + mov rax, [r12] + movzx rax, byte [rax] + mov [r12], rax + ret + ret +word_c_21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rbx], al + ret + ret +word_r_40: + mov rax, [r13] + sub r12, 8 + mov [r12], rax + ret + ret +word_strlen: + mov rax, [r12] ; addr + mov rcx, [r12 + 8] ; len + add r12, 16 ; pop len and addr + mov [r12], rcx ; push len + ret + ret +word_puts: + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel data_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_write_buf: + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_read_file: + ; stack: path_ptr (top), path_len (next) + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + add r12, 16 ; pop args + + ; open(path_ptr, O_RDONLY=0, mode=0) + mov rax, 2 ; syscall: open + mov rdi, rsi ; filename + xor rsi, rsi ; flags = O_RDONLY + xor rdx, rdx ; mode = 0 + syscall + mov r10, rax ; save open() result + cmp rax, 0 + jl .fail_open + mov r8, rax ; fd + + ; use lseek to determine file size: lseek(fd, 0, SEEK_END) + mov rax, 8 ; syscall: lseek + mov rdi, r8 ; fd + xor rsi, rsi ; offset = 0 + mov rdx, 2 ; SEEK_END + syscall + mov r11, rax ; save lseek() result + cmp rax, 0 + jl .close_fail_lseek + mov rsi, rax ; length = size + + ; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0) + mov rax, 9 ; syscall: mmap + xor rdi, rdi ; addr = NULL + ; rsi already holds length + mov rdx, 1 ; PROT_READ + mov r10, 2 ; MAP_PRIVATE + mov r8, r8 ; fd + xor r9, r9 ; offset = 0 + syscall + mov rbx, rax ; addr + mov r12, r12 ; (no-op, for debug) + mov rax, 3 ; syscall: close + mov rdi, r8 ; fd + syscall + cmp rbx, -4095 + jae .fail_mmap + sub r12, 16 + mov [r12], rsi ; len (rsi held length across syscall) + mov [r12 + 8], rbx ; addr + ret + +.close_fail_lseek: + mov rax, 3 + mov rdi, r8 + syscall + mov rax, r11 ; return lseek() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -1 + ret + +.fail_open: + mov rax, r10 ; return open() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -2 + ret + +.fail_mmap: + mov rax, -1 ; return mmap() error + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -3 + ret + ret +word_write_file: + ; stack: path_ptr (top), path_len, buf_ptr, buf_len + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15) + mov r13, [r12 + 24] ; buf_len (save in callee-saved r13) + add r12, 32 ; pop 4 args (we saved buf info) + + ; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666) + mov rdi, rsi ; filename + mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC + mov rdx, 438 ; mode = 0o666 + mov rax, 2 ; syscall: open + syscall + cmp rax, 0 + jl .fail_open + mov r9, rax ; save fd + + ; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls + mov rax, 1 ; syscall: write + mov rdi, r9 ; fd + mov rsi, r15 ; buf_ptr + mov rdx, r13 ; buf_len + syscall + mov r10, rax ; save write result + cmp r10, 0 + jl .fail_write + + ; close(fd) + mov rax, 3 ; syscall: close + mov rdi, r9 + syscall + + sub r12, 8 + mov [r12], r10 + ret + +.fail_write: + mov rax, 3 + mov rdi, r9 + syscall + sub r12, 8 + mov [r12], r10 + ret + +.fail_open: + sub r12, 8 + mov [r12], rax + ret + ret +word_main: + ; push str_0 + sub r12, 8 + mov qword [r12], str_0 + ; push 22 + sub r12, 8 + mov qword [r12], 22 + call word_swap + ; push str_1 + sub r12, 8 + mov qword [r12], str_1 + ; push 27 + sub r12, 8 + mov qword [r12], 27 + call word_swap + call word_2swap + call word_write_file + call word_dup + ; push 0 + sub r12, 8 + mov qword [r12], 0 + call word__3e + mov rax, [r12] + add r12, 8 + test rax, rax + jz L_if_false_0 + ; push str_2 + sub r12, 8 + mov qword [r12], str_2 + ; push 13 + sub r12, 8 + mov qword [r12], 13 + call word_puts + call word_puts + ; push 0 + sub r12, 8 + mov qword [r12], 0 + call word_exit +L_if_false_0: + ; push str_3 + sub r12, 8 + mov qword [r12], str_3 + ; push 19 + sub r12, 8 + mov qword [r12], 19 + call word_puts + call word_puts + call word_exit + ret +section .data +data_start: +str_0: db 47, 116, 109, 112, 47, 108, 50, 95, 116, 101, 115, 116, 95, 119, 114, 105, 116, 101, 46, 116, 120, 116, 0 +str_0_len equ 22 +str_1: db 104, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 119, 114, 105, 116, 101, 95, 102, 105, 108, 101, 32, 116, 101, 115, 116, 10, 0 +str_1_len equ 27 +str_2: db 119, 114, 111, 116, 101, 32, 98, 121, 116, 101, 115, 58, 32, 0 +str_2_len equ 13 +str_3: db 119, 114, 105, 116, 101, 32, 102, 97, 105, 108, 101, 100, 32, 101, 114, 114, 110, 111, 61, 0 +str_3_len equ 19 +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/test_write_file.o b/build/test_write_file.o new file mode 100644 index 0000000000000000000000000000000000000000..b6082c558ea8ed511122cb60a064d34d94969f02 GIT binary patch literal 5632 zcmbW4eQaCR6~M3Cgt{NhftFIO`NOM>1gN-)-3o$%$W5tB!4+ zpGhN94X`@#FxdbVX=Qv!Oi24<(m<#v%Opta(5Qp9tkb4RNC>GFi#k49iW(pVbI!fz zedN^XAG?y@JNI|ax%b?2KYZV>cNq6AiA01~BI1`KsCiU~-asU|S42fyi2i>f_JzM2 zn0xOM1&%XC2eVrSb@X4#c*k-D_At&Pz7h0M_;LR-`9Cfw5Ne0_e{&08H1+)NCO_}R zbK41ug*_m&L;{c&x8g{}DW5u#gy+i`uJa$y=yh#~6$CSMPjbO%ef}R)GDE}xq zv_lm|-oG(^8yaTZ{~F_Wp)`8|OeZAkx#~pqdRs!TO-D6%W@0PQSUVCe_O{U7wnU@h z>GgVN;;E%r-y!tcXVH+hZX}}6M2GIK@*L`W6H%@9jTqZyjALZN7{`eeMo(j`*XViw z;LkPpxaNM0ZrY)<&Z-HF{at*-+D}N26#>%5x1jT+Qu`rkZlg~QM61nwdUy)H*{&uWB=>ay3cCvfAqPp9zPD?^iykrLUY=okE-W&h}&5% zjqd_{qU|Ru;1!C-{k!g7GThU#b_#{Eq1V?W^tz*x5!i!S12YW9+fnCRL*g+{y4#u1 zT~MjkB!ZO6bV{zfdlMbkDA5TM51yoiKIE*(DU;1mU)Vs{Fwj9GempQ0yp#Iw#5$Z+ z-Q7(MU{mYlNIEe1b;>>546P?U0;@+xf??eeuFP$O1|>j0(BgtSqRq`OM%RQ|f@P@n zH2#Kj8#~;<+y%XabuU~;_tJHAuU<#@%5`)v2Rf~;_KrV#jLU^o!5YxqPqf_v zSl`h`U|_&0Ayu$hXJCGsP#T8&;R5&rLTzRWl?xQ#qe9Ia4lM(-4%1w~Z8IH*@x9Xr z(NDe&=b9Wb#Diz%Hr-Xnjp3d#+#d}0g3N$k`%a9lrqIp+f}NXjVQ;iRsFM=~Cl5$7 zZTL5&k`3}&kY~r{Ww6&M*Q3$|ndkeFjJ$4nGX{W=|aMG>1!4rS>^KZd_ z79L@XSsgMH2A;ecT_(}xC_XlTSp!h0Y;uOnn+hq@u_}%^V&@$z=^SvxKC4hD#Ru)u za9l!jFki6ZXtY9%*d@n`_m4vDo;cLNCq9@3eJ*aO8B zk*w^iIJT4R2WfOzy{T?ng{-n)&_t^W{&%&BOU+igr7drCcyGYPeQjCV;zqGSnnlFz z%v{}XA|l0jAKCXZ{s3{j%Y=)%r$xlWVF+?o)+6E(#`hC{i}5Fj|C8}&iC<>?2=TR; zz)*Qz$`Qf&Ux=rey}S)Tp8FX8fb1V;{9nZPGk%`UbFhAPF+NT0lo&rn{4vJ=P5gI^ ze?t6y#y=x|j`1tRFEidGzMg$FER*Aph+i?@LHr@ce@c9a@dWV$jBg@-kntYk&ojQA z_@5ZxMSP3=2#}jcJ}Sg_GyV+mJmaquuQ7g<_<uBz}eQ3&i;c@Ylp&WZ%CLIUiCP z1P{`xMflBZUzv*zM z85U;6$=VLRlEso~9mqT8quD~$5+fx$XAYQ~yF4k?tt8uLa7idwMMcY1ry}qHZQ5qh z8Y$$9mRTwmMinjF`J!XOPgS%1WSz?o4d#pa%083KWKg+kS@o&z zJ^j@|Rn6JpE-gxrTDFoZBUxf_B~r*tfg#DoJZYWkz<#Ap`OTvpsZ&8asi1K))$cdy z30Y5|pv=@3BI%r&&UxDIKu!;M29$I&JrL4bf$YtN=}pD(us6ElYSEW*5>=DgB6V1z zbQHaTn`tjYHi*jF4#r!~d+D%4qLt0bwL|7!H91fyRV))Pm}a43S(HfI*Go;Q>@5|h z2nG?{V^t49Jt>=z_13DO_2F#3C=4?{2mwJfW|zQ=Ev1OacqBH{b7n3#;+2;!uS~7$)j}c<9E0hGn(GUxOaY+828TU J*BIyL@sBeORh0k$ literal 0 HcmV?d00001 diff --git a/hello.sl b/hello.sl index 9f3cb37..c60fb3a 100644 --- a/hello.sl +++ b/hello.sl @@ -1,4 +1,4 @@ -import stdlib.sl +import stdlib/stdlib.sl : main "hello world" puts diff --git a/main.py b/main.py index d853ce9..b8580c3 100644 --- a/main.py +++ b/main.py @@ -2138,7 +2138,6 @@ def _register_compile_time_primitives(dictionary: Dictionary) -> None: register("list-new", _ct_list_new, compile_only=True) register("list-clone", _ct_list_clone, compile_only=True) register("list-append", _ct_list_append, compile_only=True) - register("drop", _ct_drop) register("list-pop", _ct_list_pop, compile_only=True) register("list-pop-front", _ct_list_pop_front, compile_only=True) register("list-peek-front", _ct_list_peek_front, compile_only=True) diff --git a/main.sl b/main.sl index 7548779..2779b0b 100644 --- a/main.sl +++ b/main.sl @@ -1,4 +1,4 @@ -import stdlib.sl +import stdlib/stdlib.sl import fn.sl : main diff --git a/stat_offset b/stat_offset new file mode 100755 index 0000000000000000000000000000000000000000..7556586edcbb5f9d296fde24650eff741c933c00 GIT binary patch literal 15968 zcmeHOYit}>6~4QU6PG6O+D)kAlz0URN~k>XTWKqk^)u_rNlfAhs#3;d@2tIOA7*#9 zu>&fu3{|5vYWPDDicpb2sRTm(0g`zLT+)_;cr^clP(_rIDwTLRKv7B|!#Q`(w;2!X zM5^FNrMc41chBRy_s*F+yLWcZ{ru4Aa5NH8C^hP%ilvE|r%8z6*&eA7B-B2&iHQ0OrN20nsl@fMg8vc`=;!fJmRdcBrQX%}35m;uAb2b??-k*_B0S)Vj1!1>a!mNM zPvRNGHnMR626;2W3*w+hQ$X&6%h4-N>fQ7=CcJy%x)~M3E>Eq1=RR%WLTGB0abDU&S;j(o<&1 zv5JnFvod*Qnp1O@na<>`Z03ZmW{a7;lUD4-;qOrgMo0Pw%nqZ&=&sZ|yOcRHe$Y(W zMSD6^a_r*x!GUZcZ;xA(S(}=i&K2^~iRrmkb)?}%DgHI|;Uiy*sM{gr6&^viM|L$5?%m+DnU0eb=3>G_)SB)6nj4FV(j!u;Y0_@*mOu-Te%EZX{2xBwzUR{^SeSYm$+d zlNW9{Td09rX`s%%bR_ANLs9 zUh@Dy&GLJrbt|r$BHT&%6k!+PHwXs_M+sZ6x$ch$`5h;h$cZB=G8c<%-?*Xf486c& zJ-^Fe`HSm*m>mW;=vQhxsmkwqze4&rq1qf9-rV$H{hi0_7S#Uc`##dSQ@=K3{wL{k zhWzj@j@?=B(C5j3p8Mi)W@vo73DwZ%*b~u#P3uh>5X)f+BM?R)j6fKHFalu&!U%*B z2qO?iAdJ9!Bm&4QL>?h>1UXlc%SI0>iHn;=b|mj`o5;vl+%7VnjhaP9-XcFwae@7< z8*YK+=OsxHxrGbsSbH-c^`hAI110I7)>ftN6l@aQDhLpoT9SN3Vo!mhz!4XT<`oSu3AMeaP|4dr9FD%t7XKU9y7HZ6Z_jD z<2RU8MCXUNGbM}yd zh-y}`geT*=ah7#NyUtb4 z+{9|_oY($$tKfD2rKa6g$)iUrzt{dvmHP+!x2RGrpSzI)5{Huy$F!clEfPK@RSnX| z)V4}IVeKY;W3)lxdj|RkSP#L6hoqfg`wx>o?(;+S)1+^RZc~`A&>v?#_aG$s8d6V? zK1SEQDFIIp$4TEvmI;|Z`adZ$of3b{6R@5U{}K8A+%1N)r04Mj{huR!9AqE6jWX5!?X+?^XQ%Yd8at9(nTw0o2haxH%}Cw zWRj<|%9Yah9n<^&kcMTN!$%_<@wtw%dwO`71=mYq4IVC3Jux4eE=k^-V|V_ zN(FPq%BOh4z{p|pN@en9xn!pl1%wXfWT_-v*{DF93~-XX`=IKUg4Np@Ru6~cNcU1{ zKId4Igig`J8PsU&gI%0eM!w+K#&o`H%oYo?cF~#lsV2)A+NP38iK?%Eq?M=~IUGbw5flGlbeWjqGz)RmRXP-7mQLaYp$t2vs2fm`HViM+0%TZ_KSy%OAS zhINgYwJ++7AEFPhCBR>6Ulsdu!TQ0Il;Ul3etvL&761S3FZkYqj(@lOeEe<#<8TxV z@;^@cf6!V4dRqO@lQSY3o<|;)`R4t z3%B7fpCN(QTHs@S1*9xHT`+$50UskPuiYSH{RV6kesKJvR;Q`LLk1t~N#L?LqW|Fe zKO_8p@x%HQh&VBy>p}k4Nyjlk`<34Z`JKSJom_MYUjMVC_4DJxtDx`z`1t{z3-A+S z0K#uA{__F;m=J)s<9|QEpAZ7DAuwTr?foRc$GQZF=OT +#include +#include + +int main() { + printf("st_size offset: %zu\n", offsetof(struct stat, st_size)); + return 0; +} diff --git a/stdlib/io.sl b/stdlib/io.sl new file mode 100644 index 0000000..02764c2 --- /dev/null +++ b/stdlib/io.sl @@ -0,0 +1,134 @@ + +# L2 IO Primitives + +# : read_file ( path_ptr path_len -- len addr | 0 0 ) +# Reads the file at the given path (pointer+length, not null-terminated), +# returns (len addr) of mapped file, or (0 0) on error. + +:asm read_file { + ; stack: path_ptr (top), path_len (next) + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + add r12, 16 ; pop args + + ; open(path_ptr, O_RDONLY=0, mode=0) + mov rax, 2 ; syscall: open + mov rdi, rsi ; filename + xor rsi, rsi ; flags = O_RDONLY + xor rdx, rdx ; mode = 0 + syscall + mov r10, rax ; save open() result + cmp rax, 0 + jl .fail_open + mov r8, rax ; fd + + ; use lseek to determine file size: lseek(fd, 0, SEEK_END) + mov rax, 8 ; syscall: lseek + mov rdi, r8 ; fd + xor rsi, rsi ; offset = 0 + mov rdx, 2 ; SEEK_END + syscall + mov r11, rax ; save lseek() result + cmp rax, 0 + jl .close_fail_lseek + mov rsi, rax ; length = size + + ; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0) + mov rax, 9 ; syscall: mmap + xor rdi, rdi ; addr = NULL + ; rsi already holds length + mov rdx, 1 ; PROT_READ + mov r10, 2 ; MAP_PRIVATE + mov r8, r8 ; fd + xor r9, r9 ; offset = 0 + syscall + mov rbx, rax ; addr + mov r12, r12 ; (no-op, for debug) + mov rax, 3 ; syscall: close + mov rdi, r8 ; fd + syscall + cmp rbx, -4095 + jae .fail_mmap + sub r12, 16 + mov [r12], rsi ; len (rsi held length across syscall) + mov [r12 + 8], rbx ; addr + ret + +.close_fail_lseek: + mov rax, 3 + mov rdi, r8 + syscall + mov rax, r11 ; return lseek() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -1 + ret + +.fail_open: + mov rax, r10 ; return open() error code + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -2 + ret + +.fail_mmap: + mov rax, -1 ; return mmap() error + sub r12, 16 + mov [r12], rax + mov qword [r12 + 8], -3 + ret +} +; + +# : write_file ( path_ptr path_len buf_ptr buf_len -- bytes_written | neg_errno ) +:asm write_file { + ; stack: path_ptr (top), path_len, buf_ptr, buf_len + mov rsi, [r12] ; path_ptr + mov rdx, [r12 + 8] ; path_len + mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15) + mov r13, [r12 + 24] ; buf_len (save in callee-saved r13) + add r12, 32 ; pop 4 args (we saved buf info) + + ; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666) + mov rdi, rsi ; filename + mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC + mov rdx, 438 ; mode = 0o666 + mov rax, 2 ; syscall: open + syscall + cmp rax, 0 + jl .fail_open + mov r9, rax ; save fd + + ; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls + mov rax, 1 ; syscall: write + mov rdi, r9 ; fd + mov rsi, r15 ; buf_ptr + mov rdx, r13 ; buf_len + syscall + mov r10, rax ; save write result + cmp r10, 0 + jl .fail_write + + ; close(fd) + mov rax, 3 ; syscall: close + mov rdi, r9 + syscall + + sub r12, 8 + mov [r12], r10 + ret + +.fail_write: + mov rax, 3 + mov rdi, r9 + syscall + sub r12, 8 + mov [r12], r10 + ret + +.fail_open: + sub r12, 8 + mov [r12], rax + ret +} +; \ No newline at end of file diff --git a/stdlib.sl b/stdlib/stdlib.sl similarity index 81% rename from stdlib.sl rename to stdlib/stdlib.sl index a25fa30..37d4e7f 100644 --- a/stdlib.sl +++ b/stdlib/stdlib.sl @@ -1,3 +1,41 @@ +# : c@ ( addr -- byte ) +:asm c@ { + mov rax, [r12] + movzx rax, byte [rax] + mov [r12], rax + ret +} +; + +# : c! ( byte addr -- ) +:asm c! { + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rbx], al + ret +} +; + +# : r@ ( -- x ) +:asm r@ { + mov rax, [r13] + sub r12, 8 + mov [r12], rax + ret +} +; + +# : strlen ( addr len -- len ) +:asm strlen { + mov rax, [r12] ; addr + mov rcx, [r12 + 8] ; len + add r12, 16 ; pop len and addr + mov [r12], rcx ; push len + ret +} +; + :asm puts { ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value @@ -84,6 +122,18 @@ puts_finish_digits: } ; +# : write_buf ( len addr -- ) +:asm write_buf { + mov rdx, [r12] ; len + mov rsi, [r12 + 8] ; addr + add r12, 16 ; pop len + addr + mov rax, 1 ; syscall: write + mov rdi, 1 ; fd = stdout + syscall + ret +} +; + :asm drop { add r12, 8 } @@ -303,20 +353,22 @@ puts_finish_digits: ; :asm mmap { - mov r9, [r12] - add r12, 8 - mov r8, [r12] - add r12, 8 - mov r10, [r12] - add r12, 8 - mov rdx, [r12] - add r12, 8 - mov rsi, [r12] - add r12, 8 - mov rdi, [r12] - mov rax, 9 - syscall - mov [r12], rax + ; Save rsp and align to 16 bytes for syscall ABI + mov rax, rsp + and rsp, -16 + mov rdi, [r12+40] ; addr + mov rsi, [r12+32] ; length + mov rdx, [r12+24] ; prot + mov r10, [r12+16] ; flags + mov r8, [r12+8] ; fd + mov r9, [r12] ; offset + add r12, 48 ; pop 6 args + mov rax, 9 ; syscall: mmap + syscall + mov rsp, rax ; restore rsp + sub r12, 8 + mov [r12], rax ; push result + ret } ; diff --git a/str.out b/str.out new file mode 100755 index 0000000000000000000000000000000000000000..fab96b162376525bb193ab31d54ef1893549cd95 GIT binary patch literal 11600 zcmeI2Z)_aJ6~M=5JFyes4jMuv3^LL|p}-NJL5d+DJBndfxg=mFx zp;#bo+k6#Bx`(P~NT+KNQvk83;2FW+2Q!n1L_@VFtnsgc%4k5N06EK$w9aV+K;=7k9>5MB4ozHGX9y8WA&V z;qiI`Q<3gF<#d>}wzyf{*I~HR6Dt8m+mRU2zYEiCi`VN~Z`Qiv+gq_cD9q}|9RY1E z74HBSG1EOmcc|SG?=Y(W6`Oya8gCzq3XvK=GZKr4R9}5_f2!}*E!P?DUc-GGyBXV# zIA=`YbN@?NMBAs@*Fl_%d}NGYGYDk2QhOm8Zhb&b#HgMWTRM%|w+3V%FnO5;$1bEL( zw<~VCpiZ$xi8jCV3Nu+DV9G2FwaPW&O|o)}oK27!)p zu&&?=F=6G%RU?Nq-CN?Zz_?0@@!^QiFev6_nGW7}L)*q|flVSK!LTk1HfFB?hZ5lMpv8Ul8)Nq5d~`{` z6YMslul@oq;pomf-WGq9pzev&=$<}}?)RtB?K+L_cfQW3sUyOhJ;vois$h8;?mI^H z*k@*KbNo_VhTSISI1NQCjVmu*gKSs#EuZMb3AP*VJ}NED0>2~1MTg~y)D+)bcAdVRf%-}4JxN2V!_lmM0t;(Uz?gXY zy&Tv%&;TlDgLn9VHxD1KKIosAa&nLcd070hQn?H-$GRo$U||H+om8jbQQ zhz>R!FyCpoKMlC*DfhJ|_zgm1dJ>gQimy=t=L(!A(`|8lW2b6d?~%Du3%n=UwDNX2s037Ak09RfiMGM2Eq({ z=M0pcQlgxnzdJrtw~6BoZUN8iaJ7g__5a(GL7aG!@dWXH##azu!}u!V>lwe9_+5i~IM&-lN|{$9r4CH@TK zU(dtO!y5+vUu5<@#1Al@CjKGg>xj=XZWBM}oPHUBE{ep@V|puVDNU;wi>= z5x<{t`R)Sd`#9r!$o@IT4-!Af_#4EJGX4(nFBt!jc#$& z*D`(&@pX(>i4QUUF!7CyKS}&~#-Am=pYcBtKg#&uh)2$Cp4W@Sf5!L}@#`6Xjrh%s zA0=)v{vPox#qzQf}KK{w*J^YCXqzN*Ro&-3tq5Z}?=Y@Y)jgM8}m z)3mdfCI8vtx@=`s z37bke$F_zl8;F-+O0suxqg_%`c~gei$eoZZ1*K>W7e~iBWS0q)z&SC;f=5pdWQpA z+n4pCvhBAanCYG(=D63bO-;f|3i8|IXS zod*G`%5vZ?l@w8xBx+UTit;22`&!me8Fw3OU18biQiw!(Y{bb7LG6@OeY=(%`))@h zq*($w>LcZQ)#pQR{1e1GXZ7E=G3D0#o|Z--Of4ZU0tx%WF{Lhj{&uUT{=Sy9@NCe0 z{S=z`T3Ywl=l8;HWw%v-m#dokvtDYcu_Io~7dpC?yp;mLZ--Ox!?EyMrYeE|VW7t* hB&+Qh7+h~MCC)W?oed3UBGtFj_s>@ZjX~!9zXca&U}pdT literal 0 HcmV?d00001 diff --git a/str.sl b/str.sl new file mode 100644 index 0000000..d713da5 --- /dev/null +++ b/str.sl @@ -0,0 +1,8 @@ +import stdlib/stdlib.sl +import stdlib/io.sl + +: main + "str.sl" swap read_file + write_buf + 0 +; \ No newline at end of file diff --git a/t.sl b/t.sl index 7eee533..998dad5 100644 --- a/t.sl +++ b/t.sl @@ -1,4 +1,4 @@ -import stdlib.sl +import stdlib/stdlib.sl import fn.sl fn foo(int a, int b){ diff --git a/test.sl b/test.sl index 5dd56e1..9b8fbf7 100644 --- a/test.sl +++ b/test.sl @@ -1,4 +1,4 @@ -import stdlib.sl +import stdlib/stdlib.sl import fn.sl :asm mem-slot { diff --git a/test_read_file.out b/test_read_file.out new file mode 100755 index 0000000000000000000000000000000000000000..dbf7c098d39d2f9c4ab2c4a4170696a0a40ccf48 GIT binary patch literal 11696 zcmeI2e{2-T701WFh#@3*Nr>eZSGrV}0*YgNXK3n#wl;xiSGnsCg+_^#WOKe-;}hq- zV{b2p0t&4IWqWa}M)Z#;CH<#u`bYmLY81J&Y79qkX%Z_1RYD?4Dh1J#N-I+&oB-|h zy_q+=dqeF%`fqk6@63GOn>RDx`EhsaeST}|k=B+LCa+fZ6~;@^A&$hIvHAO?2V+C* zORNp7O0$IL zS*ys&_{75`R3KC!R3KC!R3KC!R3KC!R3KC!R3KC!RN&L7Kx*pVe6)q7-M^)#?l+>X ztUeAu%coI_^xzGrQ?Iti^~sZ+nmaqa31FlHi57W->27O)+kYmE^bxCt;!+apxXvRzIwcp{~ zMh@3dJHM5n?Z->lezJt^r%TvgUBY(6w`o8NoUZqYO@k8~B(o;=wqzw zaRmin!v*9&q7r>KcKzSRex1=>40YIdjb@@Q9pa5xniQeKj3nEpbK|nJ72p7b#{VB zeGBG}LbLTXfeH|^QGfoXn7sj)cpzpM#=Q0k)cG97oX6bL81pPdmjgsq>h~!z*VNAi zTpkL<scfC@gapjO#B-PPZNJe;ZG9Zsc`XL zK@0nh!grJZS%n`WensIwBHne!5YNfmkwy4x#FL8uQR2f2KS}%P!YS!mx#2--j zuZcgV@ZS?JD*P?tdlWuL{D%rZNBnJtUm*UG!v9J9iozF&uU^$Wt_Jak72es3E2D)y zuJAjFZ&!E^@m&gELwujY6U1Lq_$K1NRQRLBH{RXc{~g4)Df|WEd4(S#KB@56h<~8) z*NG>)n%g~2{Gh_;h`*=s^PIyi)*R>JBK#8PmmB!2Ja}Cte|*9ayl#*`K5YnI%kUWt zyu*c04}#Z9&M!B*f)Mgu#gutNr-``Qvkf;MGh1_{<=9eUbdLivL$RZ(}8e zKjQJ>U>NqzMfejQ-`wP%U4)MlpN}>Bf7ptz)WPOZK6mzje-z%@Q~UWn&Rdx}t_R6q zjn76Z`9f~JW0oDm`>5~Bl*gF?-x6%6&ng<`uDoMBmnl?CHc_;5M%LKSFLTL+$k`q% zJ9fde1T9sZGQ%4Lvkl9fDC8~EC|ZTxf|l&OJiagu&;BRS%Ql$ngoP^XOKMj`__V<0E32|quOl@27jF^~;dO+PQ^!jMye z-{VB(@rvc;aS{d1Skz#VgyMG0~aTj z6XNcblf0bt$^*PS;FUM<@&;b!p-s>+2b%;$5sBfz%CH3y2`6HaW&~2l7U`JGIp!{h^>Md8sMvI>{Qrg3P!&IV>GfRyoQaB<-ut@L z1Ys&Mb`RvRK0m&Y%5yV@1;(->@$Sv<7BjX6EckR^)|cm5HYTd if # if file_len > 0, success + write_buf # print file contents (file_len file_addr) + 0 + exit + then + dup -2 == if # open() failed + drop + "open() failed: errno=" puts + swap puts + exit + then + dup -1 == if # fstat() failed + drop + "fstat() failed: errno=" puts + swap puts + exit + then + dup -3 == if # mmap() failed + drop + "mmap() failed" puts + exit + then + "unknown read_file failure" puts + dup # file_len file_len file_addr + exit # Exit with returned file_len as the program exit code (debug) +; diff --git a/test_write_buf.sl b/test_write_buf.sl new file mode 100644 index 0000000..72720b1 --- /dev/null +++ b/test_write_buf.sl @@ -0,0 +1,8 @@ +import stdlib/stdlib.sl +import stdlib/io.sl + +: main + "hello from write_buf test\n" + write_buf + 0 +; diff --git a/test_write_file.sl b/test_write_file.sl new file mode 100644 index 0000000..002f8f4 --- /dev/null +++ b/test_write_file.sl @@ -0,0 +1,20 @@ +import stdlib/stdlib.sl +import stdlib/io.sl + +: main + "/tmp/l2_test_write.txt" # push path (len addr) + swap # -> (addr len) = path_ptr path_len + "hello from write_file test\n" # push buf (len addr) + swap # -> (addr len) = buf_ptr buf_len + 2swap # reorder pairs -> path_ptr path_len buf_ptr buf_len + write_file + dup 0 > if + "wrote bytes: " puts + puts + 0 + exit + then + "write failed errno=" puts + puts + exit +; diff --git a/tests/run_tests.py b/tests/run_tests.py index cb66aa3..3a7f36b 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -30,7 +30,7 @@ CASES: List[TestCase] = [ TestCase( name="call_syntax_parens", source=f""" -import {ROOT / 'stdlib.sl'} +import {ROOT / 'stdlib/stdlib.sl'} import {ROOT / 'fn.sl'} : main @@ -51,7 +51,7 @@ fn foo(int a, int b){{ TestCase( name="loops_and_cmp", source=f""" -import {ROOT / 'stdlib.sl'} +import {ROOT / 'stdlib/stdlib.sl'} : main 0 @@ -69,7 +69,7 @@ import {ROOT / 'stdlib.sl'} TestCase( name="override_dup_compile_time", source=f""" -import {ROOT / 'stdlib.sl'} +import {ROOT / 'stdlib/stdlib.sl'} : dup 6 @@ -102,7 +102,7 @@ compile-only TestCase( name="string_puts", source=f""" -import {ROOT / 'stdlib.sl'} +import {ROOT / 'stdlib/stdlib.sl'} : main \"hello world\" puts diff --git a/write b/write new file mode 100755 index 0000000000000000000000000000000000000000..7daac9ddec99ef0ed0253cc00d237101eccb2ff1 GIT binary patch literal 11648 zcmeI2Z)_aJ6~M=i9qa^pN1eDqNu>i0H3)LC?}#7}T06vOSGo(8hznGR&Dpn3R-Et5 z-X2cC5ztdwmaA0>0xAW~9MISL7SP#2}ErR?q zwwUX-_#&uD3sKIJOqMJv0QS*}RcbTpPnP=^3q4s%J+$MZn2@trkEl@DPxv@%7B%Ug zcvyrH2qO?iAdEm5fiMDL1i}b}5eOp?Mj(tp7=iC&1k&Tz-4|_Q8TWL0e9c|aW;Xi? z{4AfqP-NDB<+SP5mbhLy(5AUF6B__VT9IgxH<<3W#A`Jv*Q=}IPcFiCAJZ%UX$wfJ z>3AEsi0ba;(x7^OyiKco!N%@RkGJlOFqR&_Vg`%#wXvS``a`>J)7<@<`w^OHyN^1T zPvGzVe_|GCoo;bD+PU%?z|$>1 zSOP_0H16BFdoJxBjnZoSzNC=A{f3tsMRpSpu7oXo;Cy?tvK=$$ivb_t)Uh-vHRh%7f_BbvVLIrz3bB}A4lV|nnSbR0^m6(n( z&OjE;;P%K=A=;G#T@&p%!B)*Z;4Ki$^CpVdhWNx%E~kiX;GE8HV?1_GMfU82eI41e z9}e|F_&cgy{VqSM4dc6*Uc0ZSp?nIgr~EC3OIJAq8>^2&pLi|271-X;0Lo{BEBuZ( z4;4>0DqKl$S-`1`{PtJCb$4o_4a&4T1M*2!MU5K2 zZ~8QMn#WG-uJik%mn&r4sZ94ljAt$5o}5@D%%T0neAC%_y|fWV2L}$~3;VmR<}0M( zmf#{dtTV7abx5_e`|k#L0iiZCg~A5G*C-I{hEvPHs>3qp@z@-Q!TkQw3!|TW1MW3G zV;B$KnHzOiTsLX=NZP%Sc0b_}&?{fEu?`yA5kPQqGcKHsiy)Nog@T(0YBMcye2yyX zoiP2`v3WjNF8onIxDtg12xmXT>}N2A+2sLU5VP5RUx6{5bl4hBO1e%3JY9jBXZ{EF zvye#*Zm&aRBia?FIY!(rRae7+bPvWvqp4virzZ^lq*2^+PGju{)+39VaW&;py-P!{C5 zm}%RE;_VCdjla=b*txo@gI_BdyiKrLz6U@GUBr_Lzm<58!Z#8BxxzOSe?Z~CB>s@X zbHx9m@JEQhr*N0}d4)esyz|N)UX$70OYql-Cl&oa6Yo{{Tf`qw_+jD?D*Qv@zgGBZ z;#Gy8BmTU?=ZXJO;Vrnpu#N{64$qi4Kc(=ih@V&ZwZtPo>_I~>ts#EB!fzp-Q1~6h z`xU;K_=v*qA-+rDTZuoVaEtg03b%>BuJA{R&nWyi#7`*v8RB(?zes##M~@d9th_?} zW`(~_{BDK6NxZ1=Y2uG6{0Q;iDf|QChZO!X@e>OFjQDwle?ffZvc`Fd*Lj-Q9SU!6 z##uM9UnsnT_%?l_}rvt%s8|ilhA=LXwzhBYc%=sd=RpI>}?``n3^%8uW z$2T_U+n3;D#E-`s^)EEzD{*iLl+Tf;KtBp^-Kpbzj`L=w&PykK)ju03Tlw5t|Kpy2 zvL~{oVP=$^tnDNUMZ?@-ImW};eA#59MLTB<8aH*xTC!WzY>$;3J8u>Q9Vt5{h8Z}s zje4%Y3moLO!f*1yLKa3RY>mL27(Zx$=nU zQ+z=gC=ZEd&IWU?QGD36MXfZNB?jMJ1TvDKNcDn6Ql~ulpb#fL_ozqWr0*x`J2#R8 zo=aKD$_fq2NUkH2${DGgly>{|)Sy(Lpc|>dfYkKsaxDzG6vM-EcEja@SI0#ZF0%#d zut?!3$cY;%86g|0LfiJ|J7URj*nz5<&GAh`>av*_%oj_hf!_p;e91H^khUl1lH!Qm zDvH3Lg#U$8^x(G>+y!r6T;zKn&RPYQHmo5S5RAs?V!5o76&fm;{b-6Hqe zN#0I+?G$gPc$>R2A*wkzG7utB7!K?cTM$ujBDOqkPp@X6tzit5@R-1vV}^+?8B3IQ z4m;TaC>>jr+hxr$;cIzEj<-^Ud#{O;eFegaK=S}*P8{nj57dXI|_e$jwj?H~JwEAw0F-k3nYzf6?) wu5kwburEw2M8WX?D6(%tyf}*kgY=Rj#QuWmN@yr5Ts%(iOWzn&hPrD14UU~{=>Px# literal 0 HcmV?d00001 diff --git a/write_buf_test b/write_buf_test new file mode 100755 index 0000000000000000000000000000000000000000..3f474ae540bb074e500ff9eacae45543b2fb45c4 GIT binary patch literal 11360 zcmeI2e`p*<6vrpOYSLEkY-^1sf1Glnl^XM-MT4OvX;XIb4g_0K5SL4C(;mIt#l1b# zXoA(VrRy2QQvWEm+CN17LqQQrjH0m@8*4Sy`j6lbM1$6!q!x@A^?YyU&FNX#$&5J z7g(}|D9@5lmMka$_ECc-)fx3C%jRVwPL?tb+i_P&_*tk^7*sY8KFTVECG!*a3ts_W z0bc=M0bc=M0bc=M0bc=M0bc=M0bhatqXLn!Ypw`Zu&DEGWbB4Ou#%mfgRkY|C`GjW z54%>+SBLf7RITPrk9PnJ)F9CU$C&O^hYJPi*Yl0x{Z&}+VS4Vz+7fR*60U_5LETv? z8|3c}*J`=n*vRdXv6|rkW0A3o$FOKGjC4lYPmSK9Imb2U3v8zCJ!7vN$M5}b;Vn>e zqNYDk$(DOa8{4=Y$b@jaL(-f=7oUihTVSJg+WeM<6MelXKm{REa7{43EvUVr{%@7Z2u&)CLkHbTK56X9@c4CpCVj^ zi1T3?{0pHrJ&DdT$DimB>xNT{!h*}kW-1hQ=5^I7&?A9G| z=tP{;5$CUn^F7x=&;8CuR?`4a1A^x_>cA874+wpHx#0W(Yq~m&e@&J4l_0`dZGjJ2 zH~|#k<6pi4z5>1iz5>1iz5>1iz5@SY1$LUrWIEJur3XSoR>C%o-fVx!HZwMUFJ9up z@7mSuTu}|d-x?Xb6>y#We?A4=NW4|y?Zi73zM1%K3Xc-MN8xu7zgOXX#9vkTF!7HS zzMuGcg+D=j?WLXElD8v^@aKuQD)Fxn?^5^_@p}~h0r6c5|BU!Pg?~dlukbnIhZO!h z@fQ_dg$oSpcv9g3;@>E|p7?o%Urju)s+0F5Z|jM#Q}|89n-tzne7nM<#0M3A2k}vb z8^j+~_)g-76@D-AR}_9f@o9zcBmT9*4-hXZ{4nu`)#ds;OZ+B@e2SCRN;h1cTubl7iqD0~(19SUzGzFXnf z5+7A~3-JRA?;!qy!fz$M@v`#q?;^fU;g1kcDEtWVoWfrs{++_#CH{xPzaqYDZTWb9 zjEO{AR95r_}MTWRVz@8tZ#d99#$H9zakCX(?R@h70+{y=PsWd@j$ zv169qlu8@s?u2dJ7fWVMHk7vFMxU{vSz4_v!m?bJv8|+;5_B+YXBgffnPsHRp=2Uu z8tGJWSkOT$k+Kc=h-$2tqT`7j3E484P7hL!#Ez7(`V*-{W~V`6d{FW1py<<`g{a0Y zXwDtIC8god0M^XMr*H|QW`O7^h;wS z8EtW+EiPe;XSemq021A3>nrh^o-NnHkV`QzAZIs_O}REMqDUD_QHN=gBPAzpv`K|5 zFh#WG&37;%<*-UjGZr`c6G<5^t4)2$bjCFLV~M1Z%$Oz#X}NyxNe{}cqBy)si1qY( z@aj!G1+R;-sxB}4KrE4B@t7SGyPDy4Y!-I|cPn?9AWR%~J2)bo Slo0Mt)BC{dOM}5y+y4#Y_2@$Y literal 0 HcmV?d00001