number terms!
This commit is contained in:
parent
6a31b0560a
commit
9d43ebe2aa
2 changed files with 183 additions and 164 deletions
304
04b/in03
304
04b/in03
|
@ -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
|
||||
|
||||
; store away pointer to variable name
|
||||
C=:local_variable_name
|
||||
8C=I
|
||||
|
||||
; check if already defined
|
||||
C=:local_start
|
||||
8C=I
|
||||
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
|
||||
|
||||
; store away pointer to variable name
|
||||
C=:global_variable_name
|
||||
8C=I
|
||||
|
||||
; check if already defined
|
||||
C=:global_start
|
||||
8C=I
|
||||
J=:global_variables
|
||||
D=d5
|
||||
|
||||
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
|
||||
; increase static_memory_end
|
||||
C+=d8
|
||||
4D=C
|
||||
; store null terminator
|
||||
1J=0
|
||||
; update :static_memory_end
|
||||
D=:static_memory_end
|
||||
C=8D
|
||||
C+=d8
|
||||
8D=C
|
||||
; 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,12 +545,121 @@ 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
|
||||
|
@ -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
|
||||
|
@ -604,60 +686,12 @@ align
|
|||
x8b
|
||||
x85
|
||||
|
||||
:input_filename
|
||||
str in04b
|
||||
x0
|
||||
|
||||
; 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
|
||||
|
||||
|
||||
: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
|
||||
|
@ -696,15 +730,6 @@ align
|
|||
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
|
||||
!:program_error
|
||||
|
@ -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
|
||||
|
|
39
04b/in04b
39
04b/in04b
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue