diff options
author | pommicket <pommicket@gmail.com> | 2022-01-05 23:44:04 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-05 23:44:04 -0500 |
commit | 9d43ebe2aa32be615104a0dc3aec386b2017ccac (patch) | |
tree | ad8fb9decf938fe27a1cc2e0672f64b6ac180a02 /04b | |
parent | 6a31b0560a203fd4ae6642114dad488545ed0c3a (diff) |
number terms!
Diffstat (limited to '04b')
-rw-r--r-- | 04b/in03 | 308 | ||||
-rw-r--r-- | 04b/in04b | 39 |
2 files changed, 183 insertions, 164 deletions
@@ -11,23 +11,14 @@ C=:labels_end D=:labels 8C=D -I=8S -A=d3 -?I!A:usage_error ; open input file - J=S - ; argv[1] is at *(rsp+16) - J+=d16 - J=8J + J=:input_filename I=d0 syscall x2 J=A ?J<0:input_file_error ; open output file - J=S - ; argv[2] is at *(rsp+24) - J+=d24 - J=8J + J=:output_filename I=x241 D=x1ed syscall x2 @@ -126,6 +117,7 @@ C=x20 call :string= D=A ?D!0:handle_local +; arguments are treated the same as local variables I=:line J=:"argument" C=x20 @@ -140,7 +132,9 @@ call :string= D=A ?D!0:handle_return +; set delimiter to newline C=xa + I=:line J=:"function" call :string= @@ -173,7 +167,7 @@ D=A syscall x3c align -:local_start +:local_variable_name reserve d8 :handle_local @@ -188,27 +182,22 @@ align I=R ; skip ' ' I+=d1 - call :read_type - R=A - I+=d1 - ; check if already defined - C=:local_start + ; store away pointer to variable name + C=:local_variable_name 8C=I + + ; check if already defined J=:local_variables - D=d5 call :ident_lookup C=A ?C!0:local_redeclaration - C=:local_start + C=:local_variable_name I=8C J=:local_variables_end J=8J call :ident_copy - ; store type - 1J=R - J+=d1 ; increase stack_end, store it in J C=:stack_end D=4C @@ -218,11 +207,6 @@ align J+=d4 ; store null terminator 1J=0 - ; update :stack_end - D=:stack_end - C=8D - C+=d8 - 8D=C ; update :local_variables_end I=:local_variables_end 8I=J @@ -241,7 +225,8 @@ align align :global_start reserve d8 - +:global_variable_name + reserve d8 :handle_global ; ignore if this is the second pass C=:second_pass @@ -250,43 +235,33 @@ align ; skip ' ' I+=d1 - call :read_type - ; put type in R - R=A - ; skip ' ' after type - I+=d1 - ; check if already defined - C=:global_start + ; store away pointer to variable name + C=:global_variable_name 8C=I - J=:global_variables - D=d5 + ; check if already defined + J=:global_variables call :ident_lookup C=A ?C!0:global_redeclaration - C=:global_start - I=8C + C=:global_variable_name + I=8C J=:global_variables_end J=8J call :ident_copy - ; store type - 1J=R - J+=d1 ; store address D=:static_memory_end - D=4D - 4J=D + C=4D + 4J=C J+=d4 - ; store null terminator - 1J=0 - ; update :static_memory_end - D=:static_memory_end - C=8D + ; increase static_memory_end C+=d8 - 8D=C + 4D=C + ; store null terminator + 1J=0 ; update :global_variables_end I=:global_variables_end 8I=J @@ -308,7 +283,7 @@ align ; reset stack_end D=:stack_end - 8D=0 + 4D=0 ; go read the next line !:read_line @@ -374,8 +349,7 @@ align I=:line I+=d1 - J=:labels - D=d4 + J=:global_variables call :ident_lookup C=A ?C!0:label_redefinition @@ -387,6 +361,7 @@ align call :ident_copy R=J + ; figure out where in the file we are J=d4 I=d0 D=d1 @@ -394,6 +369,7 @@ align C=A C+=x400000 J=R + ; store address 4J=C J+=d4 @@ -452,14 +428,10 @@ align align :ident_lookup_i reserve d8 -:ident_lookup_sep - reserve d8 -; look up identifier rsi in list rdi with separation rdx between entries +; look up identifier rsi in list rdi ; returns address of whatever's right after the identifier in the list, or 0 if not found :ident_lookup - C=:ident_lookup_sep - 8C=D C=:ident_lookup_i 8C=I @@ -480,9 +452,8 @@ align ; check if this was it ?C!0:return_J ; nope. keep going - C=:ident_lookup_sep - C=8C - J+=C + ; skip over address: + J+=d4 !:ident_lookup_loop ; can the character in rbx appear in an identifier? @@ -520,14 +491,10 @@ align ; variable J=:local_variables - xcc - D=d5 call :ident_lookup C=A ?C=0:rax2term_try_global ; it's a local variable - ; skip over its type - C+=d1 ; read the offset from rbp D=4C ; put negated offset in rcx @@ -546,16 +513,15 @@ align D=d4 syscall x1 + return :rax2term_try_global J=:global_variables - D=d5 call :ident_lookup C=A ?C=0:bad_term ; it's a global variable - ; skip over its type - C+=d1 + ; get its address C=4C D=:rax2term_addr 4D=C @@ -579,13 +545,122 @@ align return :term_char - ; @TODO - xcc + I+=d1 + I=1I + !:set_rax_to_immediate + +:number_is_negative + reserve d1 :term_number - ; @TODO - xcc + C=1I + D='- + ; set rdx to 0 if number is positive, 1 if negative + ?C=D:term_number_negative + D=d0 + !:term_number_cont + :term_number_negative + D=d1 + I+=d1 + :term_number_cont + ; store away negativity + C=:number_is_negative + 1C=D + + C=1I + D='0 + ?C=D:term_hex_number + ; it's a decimal number + ; rbp will store the number + R=d0 + :decimal_number_loop + C=1I + D='9 + ?C>D:decimal_number_loop_end + D='0 + ?C<D:decimal_number_loop_end + C-=D + ; multiply by 10 + B=d10 + A=R + mul + R=A + ; add this digit + R+=C + + I+=d1 + !:decimal_number_loop + :decimal_number_loop_end + !:term_number_output + +:term_hex_number + I+=d1 + C=1I + D='x + ; 0 followed by something other than x + ?C!D:bad_term + I+=d1 + ; rbp will store the number + R=d0 + :hex_number_loop + C=1I + D='0 + ?C<D:hex_number_loop_end + D=d58 + ?C<D:hex_number_0123456789 + D='a + ?C<D:hex_number_loop_end + D='f + ?C>D:hex_number_loop_end + ; one of the digits a-f + D=xffffffffffffffa9 + !:hex_number_digit + :hex_number_0123456789 + D=xffffffffffffffd0 + :hex_number_digit + C+=D + ; shift left by 4 + R<=d4 + ; add digit + R+=C + I+=d1 + !:hex_number_loop + :hex_number_loop_end + !:term_number_output +:term_number_output + ; we now have the *unsigned* number in rbp. first, take the sign into consideration + C=:number_is_negative + D=1C + ?D=0:number_not_negative + ; R = -R + C=R + R=d0 + R-=C + :number_not_negative + I=R + !:set_rax_to_immediate + + + +; set <rax> to the immediate in rsi. +:set_rax_to_immediate + C=:imm64 + 8C=I + + ; write prefix + J=d4 + D=d2 + I=:mov_rax_imm64_prefix + syscall x1 + + ; write immediate + J=d4 + D=d8 + I=:imm64 + syscall x1 + return + align :rax2term_addr reserve d4 @@ -593,6 +668,13 @@ align :mov_ebx_imm32_prefix xbb +:mov_rax_imm64_prefix + x48 + xb8 + +align +:imm64 + reserve d8 :mov_rax_[rbx] x48 x8b @@ -602,62 +684,14 @@ align :load_rbp_offset_prefix x48 x8b - x85 - - -; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number: -; 0 for non-pointer types -; 1 for pointer to char -; 2 for pointer to short -; 4 for pointer to int -; 8 for pointer to long -:read_type - C=1I - D='* - ?C=D:read_pointer_type - ; it's not a pointer - call :read_simple_type - A=d0 - return - :read_pointer_type - ; it's a pointer! - I+=d1 - !:read_simple_type - -; returns 1 for char, 2 for short, 4 for int, 8 for long -:read_simple_type - R=I - C=x20 - I=R - J=:"char" - call :string= - D=A - ?D!0:return_1 - I=R - J=:"short" - call :string= - D=A - ?D!0:return_2 - I=R - J=:"int" - call :string= - D=A - ?D!0:return_4 - I=R - J=:"long" - call :string= - D=A - ?D!0:return_8 - !:bad_type + x85 +:input_filename + str in04b + x0 -:usage_error - B=:usage_error_message - call :general_error - -:usage_error_message - str Please provide an input and an output file. - xa +:output_filename + str out04b x0 :input_file_error @@ -695,15 +729,6 @@ align str Bad label. xa x0 - -:bad_type - B=:bad_type_error_message - !:program_error - -:bad_type_error_message - str Bad type. - xa - x0 :bad_term B=:bad_term_error_message @@ -924,19 +949,6 @@ align ?D!C:memccpy return -:"char" - str char - x20 -:"short" - str short - x20 -:"int" - str int - x20 -:"long" - str long - x20 - :"global" str global x20 @@ -1,3 +1,6 @@ +:test + return -0x3874f + ; declaration: ; global <type> <name> ; local <type> <name> @@ -10,8 +13,8 @@ ; <lvalue> += <rvalue> ; <lvalue> -= <rvalue> ; <function>(<term>, <term>, ...) -; syscall <term> <term> ... ; return <rvalue> +; string <str> ; byte <number> ; term: ; <var> @@ -22,17 +25,13 @@ ; 0xabc ; lvalue: ; <var> -; *<var> -; <var>[<term>] +; *1 <var> / *2 <var> / *4 <var> / *8 <var> ; rvalue: -; `<string>` ; <var> ; &<var> ; *1 <var> / *2 <var> / *4 <var> / *8 <var> -; <var>[<term>] ; ~<var> ; <function>(<term>, <term>, ...) -; syscall <term>, <term>, ... ; <term> + <term> ; <term> - <term> ; NOTE: *, /, % are signed (imul and idiv) @@ -51,6 +50,12 @@ global x global y ;123 global z +:syscall +function + ; ... + byte 0x0f + byte 0x05 + :strlen function argument s @@ -72,7 +77,7 @@ function argument c local p p = &c - syscall 1 1 p 1 0 0 0 0 + syscall(1, 1, p, 1) return :puts @@ -80,17 +85,17 @@ function argument s local len len = strlen(s) - syscall 1 1 s len 0 0 0 0 + syscall(1, 1, s, len) return :main function - local hello - hello = `Hello, world! -` - puts(hello) - syscall 0x3c 0 0 0 0 0 0 0 - + puts(str_hello_world) + syscall(0x3c, 0) +:str_hello_world +string Hello, world! +byte 10 +byte 0 :f function @@ -103,6 +108,8 @@ function *4p = v if v == 0 goto something *1p = v + 1 - return *2p + v = *2p + return v :something - return *4p + v = *4p + return v |