number terms!
This commit is contained in:
parent
6a31b0560a
commit
9d43ebe2aa
2 changed files with 183 additions and 164 deletions
306
04b/in03
306
04b/in03
|
@ -11,23 +11,14 @@ C=:labels_end
|
||||||
D=:labels
|
D=:labels
|
||||||
8C=D
|
8C=D
|
||||||
|
|
||||||
I=8S
|
|
||||||
A=d3
|
|
||||||
?I!A:usage_error
|
|
||||||
; open input file
|
; open input file
|
||||||
J=S
|
J=:input_filename
|
||||||
; argv[1] is at *(rsp+16)
|
|
||||||
J+=d16
|
|
||||||
J=8J
|
|
||||||
I=d0
|
I=d0
|
||||||
syscall x2
|
syscall x2
|
||||||
J=A
|
J=A
|
||||||
?J<0:input_file_error
|
?J<0:input_file_error
|
||||||
; open output file
|
; open output file
|
||||||
J=S
|
J=:output_filename
|
||||||
; argv[2] is at *(rsp+24)
|
|
||||||
J+=d24
|
|
||||||
J=8J
|
|
||||||
I=x241
|
I=x241
|
||||||
D=x1ed
|
D=x1ed
|
||||||
syscall x2
|
syscall x2
|
||||||
|
@ -126,6 +117,7 @@ C=x20
|
||||||
call :string=
|
call :string=
|
||||||
D=A
|
D=A
|
||||||
?D!0:handle_local
|
?D!0:handle_local
|
||||||
|
; arguments are treated the same as local variables
|
||||||
I=:line
|
I=:line
|
||||||
J=:"argument"
|
J=:"argument"
|
||||||
C=x20
|
C=x20
|
||||||
|
@ -140,7 +132,9 @@ call :string=
|
||||||
D=A
|
D=A
|
||||||
?D!0:handle_return
|
?D!0:handle_return
|
||||||
|
|
||||||
|
; set delimiter to newline
|
||||||
C=xa
|
C=xa
|
||||||
|
|
||||||
I=:line
|
I=:line
|
||||||
J=:"function"
|
J=:"function"
|
||||||
call :string=
|
call :string=
|
||||||
|
@ -173,7 +167,7 @@ D=A
|
||||||
syscall x3c
|
syscall x3c
|
||||||
|
|
||||||
align
|
align
|
||||||
:local_start
|
:local_variable_name
|
||||||
reserve d8
|
reserve d8
|
||||||
|
|
||||||
:handle_local
|
:handle_local
|
||||||
|
@ -188,27 +182,22 @@ align
|
||||||
I=R
|
I=R
|
||||||
; skip ' '
|
; skip ' '
|
||||||
I+=d1
|
I+=d1
|
||||||
call :read_type
|
|
||||||
R=A
|
; store away pointer to variable name
|
||||||
I+=d1
|
C=:local_variable_name
|
||||||
|
8C=I
|
||||||
|
|
||||||
; check if already defined
|
; check if already defined
|
||||||
C=:local_start
|
|
||||||
8C=I
|
|
||||||
J=:local_variables
|
J=:local_variables
|
||||||
D=d5
|
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C!0:local_redeclaration
|
?C!0:local_redeclaration
|
||||||
C=:local_start
|
C=:local_variable_name
|
||||||
I=8C
|
I=8C
|
||||||
|
|
||||||
J=:local_variables_end
|
J=:local_variables_end
|
||||||
J=8J
|
J=8J
|
||||||
call :ident_copy
|
call :ident_copy
|
||||||
; store type
|
|
||||||
1J=R
|
|
||||||
J+=d1
|
|
||||||
; increase stack_end, store it in J
|
; increase stack_end, store it in J
|
||||||
C=:stack_end
|
C=:stack_end
|
||||||
D=4C
|
D=4C
|
||||||
|
@ -218,11 +207,6 @@ align
|
||||||
J+=d4
|
J+=d4
|
||||||
; store null terminator
|
; store null terminator
|
||||||
1J=0
|
1J=0
|
||||||
; update :stack_end
|
|
||||||
D=:stack_end
|
|
||||||
C=8D
|
|
||||||
C+=d8
|
|
||||||
8D=C
|
|
||||||
; update :local_variables_end
|
; update :local_variables_end
|
||||||
I=:local_variables_end
|
I=:local_variables_end
|
||||||
8I=J
|
8I=J
|
||||||
|
@ -241,7 +225,8 @@ align
|
||||||
align
|
align
|
||||||
:global_start
|
:global_start
|
||||||
reserve d8
|
reserve d8
|
||||||
|
:global_variable_name
|
||||||
|
reserve d8
|
||||||
:handle_global
|
:handle_global
|
||||||
; ignore if this is the second pass
|
; ignore if this is the second pass
|
||||||
C=:second_pass
|
C=:second_pass
|
||||||
|
@ -250,43 +235,33 @@ align
|
||||||
|
|
||||||
; skip ' '
|
; skip ' '
|
||||||
I+=d1
|
I+=d1
|
||||||
call :read_type
|
|
||||||
; put type in R
|
; store away pointer to variable name
|
||||||
R=A
|
C=:global_variable_name
|
||||||
; skip ' ' after type
|
8C=I
|
||||||
I+=d1
|
|
||||||
|
|
||||||
; check if already defined
|
; check if already defined
|
||||||
C=:global_start
|
|
||||||
8C=I
|
|
||||||
J=:global_variables
|
J=:global_variables
|
||||||
D=d5
|
|
||||||
|
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C!0:global_redeclaration
|
?C!0:global_redeclaration
|
||||||
C=:global_start
|
|
||||||
I=8C
|
|
||||||
|
|
||||||
|
C=:global_variable_name
|
||||||
|
I=8C
|
||||||
|
|
||||||
J=:global_variables_end
|
J=:global_variables_end
|
||||||
J=8J
|
J=8J
|
||||||
call :ident_copy
|
call :ident_copy
|
||||||
; store type
|
|
||||||
1J=R
|
|
||||||
J+=d1
|
|
||||||
; store address
|
; store address
|
||||||
D=:static_memory_end
|
D=:static_memory_end
|
||||||
D=4D
|
C=4D
|
||||||
4J=D
|
4J=C
|
||||||
J+=d4
|
J+=d4
|
||||||
; store null terminator
|
; increase static_memory_end
|
||||||
1J=0
|
|
||||||
; update :static_memory_end
|
|
||||||
D=:static_memory_end
|
|
||||||
C=8D
|
|
||||||
C+=d8
|
C+=d8
|
||||||
8D=C
|
4D=C
|
||||||
|
; store null terminator
|
||||||
|
1J=0
|
||||||
; update :global_variables_end
|
; update :global_variables_end
|
||||||
I=:global_variables_end
|
I=:global_variables_end
|
||||||
8I=J
|
8I=J
|
||||||
|
@ -308,7 +283,7 @@ align
|
||||||
|
|
||||||
; reset stack_end
|
; reset stack_end
|
||||||
D=:stack_end
|
D=:stack_end
|
||||||
8D=0
|
4D=0
|
||||||
|
|
||||||
; go read the next line
|
; go read the next line
|
||||||
!:read_line
|
!:read_line
|
||||||
|
@ -374,8 +349,7 @@ align
|
||||||
|
|
||||||
I=:line
|
I=:line
|
||||||
I+=d1
|
I+=d1
|
||||||
J=:labels
|
J=:global_variables
|
||||||
D=d4
|
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C!0:label_redefinition
|
?C!0:label_redefinition
|
||||||
|
@ -387,6 +361,7 @@ align
|
||||||
call :ident_copy
|
call :ident_copy
|
||||||
R=J
|
R=J
|
||||||
|
|
||||||
|
; figure out where in the file we are
|
||||||
J=d4
|
J=d4
|
||||||
I=d0
|
I=d0
|
||||||
D=d1
|
D=d1
|
||||||
|
@ -394,6 +369,7 @@ align
|
||||||
C=A
|
C=A
|
||||||
C+=x400000
|
C+=x400000
|
||||||
J=R
|
J=R
|
||||||
|
; store address
|
||||||
4J=C
|
4J=C
|
||||||
J+=d4
|
J+=d4
|
||||||
|
|
||||||
|
@ -452,14 +428,10 @@ align
|
||||||
align
|
align
|
||||||
:ident_lookup_i
|
:ident_lookup_i
|
||||||
reserve d8
|
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
|
; returns address of whatever's right after the identifier in the list, or 0 if not found
|
||||||
:ident_lookup
|
:ident_lookup
|
||||||
C=:ident_lookup_sep
|
|
||||||
8C=D
|
|
||||||
C=:ident_lookup_i
|
C=:ident_lookup_i
|
||||||
8C=I
|
8C=I
|
||||||
|
|
||||||
|
@ -480,9 +452,8 @@ align
|
||||||
; check if this was it
|
; check if this was it
|
||||||
?C!0:return_J
|
?C!0:return_J
|
||||||
; nope. keep going
|
; nope. keep going
|
||||||
C=:ident_lookup_sep
|
; skip over address:
|
||||||
C=8C
|
J+=d4
|
||||||
J+=C
|
|
||||||
!:ident_lookup_loop
|
!:ident_lookup_loop
|
||||||
|
|
||||||
; can the character in rbx appear in an identifier?
|
; can the character in rbx appear in an identifier?
|
||||||
|
@ -520,14 +491,10 @@ align
|
||||||
|
|
||||||
; variable
|
; variable
|
||||||
J=:local_variables
|
J=:local_variables
|
||||||
xcc
|
|
||||||
D=d5
|
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C=0:rax2term_try_global
|
?C=0:rax2term_try_global
|
||||||
; it's a local variable
|
; it's a local variable
|
||||||
; skip over its type
|
|
||||||
C+=d1
|
|
||||||
; read the offset from rbp
|
; read the offset from rbp
|
||||||
D=4C
|
D=4C
|
||||||
; put negated offset in rcx
|
; put negated offset in rcx
|
||||||
|
@ -546,16 +513,15 @@ align
|
||||||
D=d4
|
D=d4
|
||||||
syscall x1
|
syscall x1
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
:rax2term_try_global
|
:rax2term_try_global
|
||||||
J=:global_variables
|
J=:global_variables
|
||||||
D=d5
|
|
||||||
call :ident_lookup
|
call :ident_lookup
|
||||||
C=A
|
C=A
|
||||||
?C=0:bad_term
|
?C=0:bad_term
|
||||||
; it's a global variable
|
; it's a global variable
|
||||||
; skip over its type
|
; get its address
|
||||||
C+=d1
|
|
||||||
C=4C
|
C=4C
|
||||||
D=:rax2term_addr
|
D=:rax2term_addr
|
||||||
4D=C
|
4D=C
|
||||||
|
@ -579,12 +545,121 @@ align
|
||||||
return
|
return
|
||||||
|
|
||||||
:term_char
|
:term_char
|
||||||
; @TODO
|
I+=d1
|
||||||
xcc
|
I=1I
|
||||||
|
!:set_rax_to_immediate
|
||||||
|
|
||||||
|
:number_is_negative
|
||||||
|
reserve d1
|
||||||
|
|
||||||
:term_number
|
:term_number
|
||||||
; @TODO
|
C=1I
|
||||||
xcc
|
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
|
align
|
||||||
:rax2term_addr
|
:rax2term_addr
|
||||||
|
@ -593,6 +668,13 @@ align
|
||||||
:mov_ebx_imm32_prefix
|
:mov_ebx_imm32_prefix
|
||||||
xbb
|
xbb
|
||||||
|
|
||||||
|
:mov_rax_imm64_prefix
|
||||||
|
x48
|
||||||
|
xb8
|
||||||
|
|
||||||
|
align
|
||||||
|
:imm64
|
||||||
|
reserve d8
|
||||||
:mov_rax_[rbx]
|
:mov_rax_[rbx]
|
||||||
x48
|
x48
|
||||||
x8b
|
x8b
|
||||||
|
@ -604,60 +686,12 @@ align
|
||||||
x8b
|
x8b
|
||||||
x85
|
x85
|
||||||
|
|
||||||
|
:input_filename
|
||||||
|
str in04b
|
||||||
|
x0
|
||||||
|
|
||||||
; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number:
|
:output_filename
|
||||||
; 0 for non-pointer types
|
str out04b
|
||||||
; 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
|
|
||||||
|
|
||||||
|
|
||||||
:usage_error
|
|
||||||
B=:usage_error_message
|
|
||||||
call :general_error
|
|
||||||
|
|
||||||
:usage_error_message
|
|
||||||
str Please provide an input and an output file.
|
|
||||||
xa
|
|
||||||
x0
|
x0
|
||||||
|
|
||||||
:input_file_error
|
:input_file_error
|
||||||
|
@ -696,15 +730,6 @@ align
|
||||||
xa
|
xa
|
||||||
x0
|
x0
|
||||||
|
|
||||||
:bad_type
|
|
||||||
B=:bad_type_error_message
|
|
||||||
!:program_error
|
|
||||||
|
|
||||||
:bad_type_error_message
|
|
||||||
str Bad type.
|
|
||||||
xa
|
|
||||||
x0
|
|
||||||
|
|
||||||
:bad_term
|
:bad_term
|
||||||
B=:bad_term_error_message
|
B=:bad_term_error_message
|
||||||
!:program_error
|
!:program_error
|
||||||
|
@ -924,19 +949,6 @@ align
|
||||||
?D!C:memccpy
|
?D!C:memccpy
|
||||||
return
|
return
|
||||||
|
|
||||||
:"char"
|
|
||||||
str char
|
|
||||||
x20
|
|
||||||
:"short"
|
|
||||||
str short
|
|
||||||
x20
|
|
||||||
:"int"
|
|
||||||
str int
|
|
||||||
x20
|
|
||||||
:"long"
|
|
||||||
str long
|
|
||||||
x20
|
|
||||||
|
|
||||||
:"global"
|
:"global"
|
||||||
str global
|
str global
|
||||||
x20
|
x20
|
||||||
|
|
39
04b/in04b
39
04b/in04b
|
@ -1,3 +1,6 @@
|
||||||
|
:test
|
||||||
|
return -0x3874f
|
||||||
|
|
||||||
; declaration:
|
; declaration:
|
||||||
; global <type> <name>
|
; global <type> <name>
|
||||||
; local <type> <name>
|
; local <type> <name>
|
||||||
|
@ -10,8 +13,8 @@
|
||||||
; <lvalue> += <rvalue>
|
; <lvalue> += <rvalue>
|
||||||
; <lvalue> -= <rvalue>
|
; <lvalue> -= <rvalue>
|
||||||
; <function>(<term>, <term>, ...)
|
; <function>(<term>, <term>, ...)
|
||||||
; syscall <term> <term> ...
|
|
||||||
; return <rvalue>
|
; return <rvalue>
|
||||||
|
; string <str>
|
||||||
; byte <number>
|
; byte <number>
|
||||||
; term:
|
; term:
|
||||||
; <var>
|
; <var>
|
||||||
|
@ -22,17 +25,13 @@
|
||||||
; 0xabc
|
; 0xabc
|
||||||
; lvalue:
|
; lvalue:
|
||||||
; <var>
|
; <var>
|
||||||
; *<var>
|
; *1 <var> / *2 <var> / *4 <var> / *8 <var>
|
||||||
; <var>[<term>]
|
|
||||||
; rvalue:
|
; rvalue:
|
||||||
; `<string>`
|
|
||||||
; <var>
|
; <var>
|
||||||
; &<var>
|
; &<var>
|
||||||
; *1 <var> / *2 <var> / *4 <var> / *8 <var>
|
; *1 <var> / *2 <var> / *4 <var> / *8 <var>
|
||||||
; <var>[<term>]
|
|
||||||
; ~<var>
|
; ~<var>
|
||||||
; <function>(<term>, <term>, ...)
|
; <function>(<term>, <term>, ...)
|
||||||
; syscall <term>, <term>, ...
|
|
||||||
; <term> + <term>
|
; <term> + <term>
|
||||||
; <term> - <term>
|
; <term> - <term>
|
||||||
; NOTE: *, /, % are signed (imul and idiv)
|
; NOTE: *, /, % are signed (imul and idiv)
|
||||||
|
@ -51,6 +50,12 @@ global x
|
||||||
global y ;123
|
global y ;123
|
||||||
global z
|
global z
|
||||||
|
|
||||||
|
:syscall
|
||||||
|
function
|
||||||
|
; ...
|
||||||
|
byte 0x0f
|
||||||
|
byte 0x05
|
||||||
|
|
||||||
:strlen
|
:strlen
|
||||||
function
|
function
|
||||||
argument s
|
argument s
|
||||||
|
@ -72,7 +77,7 @@ function
|
||||||
argument c
|
argument c
|
||||||
local p
|
local p
|
||||||
p = &c
|
p = &c
|
||||||
syscall 1 1 p 1 0 0 0 0
|
syscall(1, 1, p, 1)
|
||||||
return
|
return
|
||||||
|
|
||||||
:puts
|
:puts
|
||||||
|
@ -80,17 +85,17 @@ function
|
||||||
argument s
|
argument s
|
||||||
local len
|
local len
|
||||||
len = strlen(s)
|
len = strlen(s)
|
||||||
syscall 1 1 s len 0 0 0 0
|
syscall(1, 1, s, len)
|
||||||
return
|
return
|
||||||
|
|
||||||
:main
|
:main
|
||||||
function
|
function
|
||||||
local hello
|
puts(str_hello_world)
|
||||||
hello = `Hello, world!
|
syscall(0x3c, 0)
|
||||||
`
|
:str_hello_world
|
||||||
puts(hello)
|
string Hello, world!
|
||||||
syscall 0x3c 0 0 0 0 0 0 0
|
byte 10
|
||||||
|
byte 0
|
||||||
|
|
||||||
:f
|
:f
|
||||||
function
|
function
|
||||||
|
@ -103,6 +108,8 @@ function
|
||||||
*4p = v
|
*4p = v
|
||||||
if v == 0 goto something
|
if v == 0 goto something
|
||||||
*1p = v + 1
|
*1p = v + 1
|
||||||
return *2p
|
v = *2p
|
||||||
|
return v
|
||||||
:something
|
:something
|
||||||
return *4p
|
v = *4p
|
||||||
|
return v
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue