|
@@ -67,6 +67,7 @@ read_ptr_end:
|
|
|
|
|
|
section .text
|
|
|
|
|
|
+ ;; Return: EAX
|
|
|
gen_label:
|
|
|
;; Increment by 1 gen_label and return its original value
|
|
|
mov eax, [label_num]
|
|
@@ -101,11 +102,8 @@ write_label_loop:
|
|
|
|
|
|
|
|
|
;; Input in EDX (variable name)
|
|
|
- ;; Destroys: EAX
|
|
|
+ ;; Destroys: EAX, ESI, EDI
|
|
|
push_var:
|
|
|
- push esi
|
|
|
- push edi
|
|
|
-
|
|
|
;; Check input length
|
|
|
mov esi, edx
|
|
|
call check_symbol_length
|
|
@@ -124,9 +122,6 @@ push_var:
|
|
|
;; Increment the stack depth
|
|
|
inc DWORD [stack_depth]
|
|
|
|
|
|
- pop edi
|
|
|
- pop esi
|
|
|
-
|
|
|
;; If this is a temp var, increment also temp_depth
|
|
|
cmp edx, temp_var
|
|
|
jne push_var_non_temp
|
|
@@ -178,12 +173,9 @@ pop_temps_ret:
|
|
|
|
|
|
|
|
|
;; Input in EDX
|
|
|
- ;; Destroys: ECX
|
|
|
+ ;; Destroys: ECX, ESI, EDI
|
|
|
;; Returns: EAX
|
|
|
find_in_stack:
|
|
|
- push esi
|
|
|
- push edi
|
|
|
-
|
|
|
xor ecx, ecx
|
|
|
find_in_stack_loop:
|
|
|
;; Check for termination
|
|
@@ -216,8 +208,6 @@ find_in_stack_found:
|
|
|
jmp find_in_stack_end
|
|
|
|
|
|
find_in_stack_end:
|
|
|
- pop edi
|
|
|
- pop esi
|
|
|
ret
|
|
|
|
|
|
|
|
@@ -496,26 +486,21 @@ add_symbol_label:
|
|
|
ret
|
|
|
|
|
|
|
|
|
+ ;; Input in [ESP+4] (name) and [ESP+8] (want_address)
|
|
|
+ ;; Destroys: EAX, ECX, EDX, EBX, ESI, EDI
|
|
|
push_expr:
|
|
|
- push ebp
|
|
|
- mov ebp, esp
|
|
|
- push ebx
|
|
|
- push esi
|
|
|
-
|
|
|
;; Try to interpret argument as number
|
|
|
- mov eax, [ebp+8]
|
|
|
+ mov eax, [esp+4]
|
|
|
call decode_number_or_char
|
|
|
- mov ebx, edx
|
|
|
cmp eax, 0
|
|
|
je push_expr_stack
|
|
|
|
|
|
;; It is a number, check that we do not want the address
|
|
|
- cmp DWORD [ebp+12], 0
|
|
|
+ cmp DWORD [esp+8], 0
|
|
|
jne platform_panic
|
|
|
|
|
|
;; Emit the code
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
+ mov ebx, edx
|
|
|
mov cl, 0x68 ; push ??
|
|
|
call emit
|
|
|
mov ecx, ebx
|
|
@@ -525,7 +510,7 @@ push_expr:
|
|
|
|
|
|
push_expr_stack:
|
|
|
;; Call find_in_stack
|
|
|
- mov edx, [ebp+8]
|
|
|
+ mov edx, [esp+4]
|
|
|
call find_in_stack
|
|
|
cmp eax, -1
|
|
|
je push_expr_symbol
|
|
@@ -535,12 +520,10 @@ push_expr_stack:
|
|
|
shl ebx, 2
|
|
|
|
|
|
;; It is on the stack: check if we want the address or not
|
|
|
- cmp DWORD [ebp+12], 0
|
|
|
+ cmp DWORD [esp+8], 0
|
|
|
jne push_expr_stack_addr
|
|
|
|
|
|
;; We want the value, emit the code
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
mov ecx, 0x24b4ff ; push [esp+??]
|
|
|
call emit24
|
|
|
mov ecx, ebx
|
|
@@ -550,8 +533,6 @@ push_expr_stack:
|
|
|
|
|
|
push_expr_stack_addr:
|
|
|
;; We want the address, emit the code
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
mov ecx, 0x24848d ; lea eax, [esp+??]
|
|
|
call emit24
|
|
|
mov ecx, ebx
|
|
@@ -563,39 +544,31 @@ push_expr_stack_addr:
|
|
|
|
|
|
push_expr_symbol:
|
|
|
;; Get symbol data
|
|
|
- mov edx, [ebp+8]
|
|
|
+ mov edx, [esp+4]
|
|
|
call find_symbol_or_panic
|
|
|
mov ebx, eax
|
|
|
|
|
|
- ;; If arity is -2, check we do not want the address
|
|
|
- cmp edx, -2
|
|
|
- jne push_expr_after_assert
|
|
|
- cmp DWORD [ebp+12], 0
|
|
|
- jne platform_panic
|
|
|
-
|
|
|
-push_expr_after_assert:
|
|
|
- ;; Check if we want the address or arity is -2
|
|
|
+ ;; Handle (in this order) global constants, cases when we want the
|
|
|
+ ;; address and global variables
|
|
|
cmp edx, -2
|
|
|
- je push_expr_addr
|
|
|
- cmp DWORD [ebp+12], 0
|
|
|
- jne push_expr_addr
|
|
|
-
|
|
|
- ;; Check if arity is -1
|
|
|
+ je push_expr_symbol_const
|
|
|
+ cmp DWORD [esp+8], 0
|
|
|
+ jne push_expr_symbol_addr
|
|
|
cmp edx, -1
|
|
|
- je push_expr_val
|
|
|
- mov esi, edx
|
|
|
+ je push_expr_symbol_var
|
|
|
|
|
|
- ;; This is a real function call, emit the code (part 1)
|
|
|
+ ;; This is a real function call, save arity and emit the call
|
|
|
+ mov esi, edx
|
|
|
mov cl, 0xe8 ; call ??
|
|
|
call emit
|
|
|
mov eax, ebx
|
|
|
call compute_rel
|
|
|
mov ecx, eax
|
|
|
call emit32
|
|
|
+
|
|
|
+ ;; Multiply the arity by 4 and emit stack unwinding
|
|
|
mov ecx, 0xc481 ; add esp, ??
|
|
|
call emit16
|
|
|
-
|
|
|
- ;; Multiply the arity by 4 and continue emitting code
|
|
|
mov ecx, esi
|
|
|
shl ecx, 2
|
|
|
call emit32
|
|
@@ -603,10 +576,10 @@ push_expr_after_assert:
|
|
|
call emit
|
|
|
|
|
|
;; Update stack variables
|
|
|
-push_expr_symbol_loop:
|
|
|
+push_expr_symbol_call_loop:
|
|
|
;; Check for termination
|
|
|
cmp esi, 0
|
|
|
- je push_expr_symbol_loop_end
|
|
|
+ je push_expr_ret
|
|
|
|
|
|
;; Call pop_var
|
|
|
mov eax, 1
|
|
@@ -614,18 +587,18 @@ push_expr_symbol_loop:
|
|
|
|
|
|
;; Decrement arity and reloop
|
|
|
dec esi
|
|
|
- jmp push_expr_symbol_loop
|
|
|
+ jmp push_expr_symbol_call_loop
|
|
|
|
|
|
-push_expr_symbol_loop_end:
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
+push_expr_symbol_const:
|
|
|
+ ;; Check we do not want the address
|
|
|
+ cmp DWORD [esp+8], 0
|
|
|
+ jne platform_panic
|
|
|
|
|
|
- jmp push_expr_ret
|
|
|
+ ;; But we actually emit the address, because there is where the
|
|
|
+ ;; constant value is stored
|
|
|
|
|
|
-push_expr_addr:
|
|
|
+push_expr_symbol_addr:
|
|
|
;; We want the address, emit the code
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
mov cl, 0x68 ; push ??
|
|
|
call emit
|
|
|
mov ecx, ebx
|
|
@@ -633,48 +606,49 @@ push_expr_addr:
|
|
|
|
|
|
jmp push_expr_ret
|
|
|
|
|
|
-push_expr_val:
|
|
|
+push_expr_symbol_var:
|
|
|
;; We want the value, emit the code
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
- mov cl, 0xb8 ; mov eax, ??
|
|
|
- call emit
|
|
|
+ mov ecx, 0x35ff ; push [??]
|
|
|
+ call emit16
|
|
|
mov ecx, ebx
|
|
|
call emit32
|
|
|
- mov ecx, 0x30ff ; push [eax]
|
|
|
- call emit16
|
|
|
|
|
|
jmp push_expr_ret
|
|
|
|
|
|
push_expr_ret:
|
|
|
- pop esi
|
|
|
- pop ebx
|
|
|
- pop ebp
|
|
|
+ ;; Keep note of the new temporary
|
|
|
+ mov edx, temp_var
|
|
|
+ call push_var
|
|
|
+
|
|
|
ret
|
|
|
|
|
|
|
|
|
-push_expr_until_brace:
|
|
|
- push ebx
|
|
|
- push esi
|
|
|
- push edi
|
|
|
+ ;; Input in EAX
|
|
|
+ ;; Destroys: EAX, ECX, EDX, EBX, ESI, EDI
|
|
|
+push_token:
|
|
|
+ ;; Check if it is a string
|
|
|
+ cmp BYTE [eax], QUOTE
|
|
|
+ je push_token_str
|
|
|
|
|
|
-push_expr_until_brace_loop:
|
|
|
- ;; Get a token
|
|
|
- call get_token
|
|
|
- mov ebx, eax
|
|
|
+ ;; Check if we want the address
|
|
|
+ xor edx, edx
|
|
|
+ cmp BYTE [eax], AT_SIGN
|
|
|
+ jne push_token_value
|
|
|
+ inc eax
|
|
|
+ inc edx
|
|
|
|
|
|
- ;; If it is an open brace, exit loop
|
|
|
- mov ecx, [eax]
|
|
|
- and ecx, 0xffff
|
|
|
- cmp ecx, '{'
|
|
|
- je push_expr_until_brace_end
|
|
|
+push_token_value:
|
|
|
+ ;; Call push_expr
|
|
|
+ push edx
|
|
|
+ push eax
|
|
|
+ call push_expr
|
|
|
+ add esp, 8
|
|
|
|
|
|
- ;; If not, branch depending on whether it is a string or not
|
|
|
- cmp BYTE [ebx], QUOTE
|
|
|
- je push_expr_until_brace_string
|
|
|
- jmp push_expr_until_brace_push
|
|
|
+ ret
|
|
|
+
|
|
|
+push_token_str:
|
|
|
+ mov ebx, eax
|
|
|
|
|
|
-push_expr_until_brace_string:
|
|
|
;; Generate a jump (in esi) and a string (in edi) label
|
|
|
call gen_label
|
|
|
mov esi, eax
|
|
@@ -707,8 +681,6 @@ push_expr_until_brace_string:
|
|
|
call add_symbol_label
|
|
|
|
|
|
;; Emit code to push the string label
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
mov cl, 0x68 ; push ??
|
|
|
call emit
|
|
|
mov edx, edi
|
|
@@ -718,26 +690,29 @@ push_expr_until_brace_string:
|
|
|
mov ecx, eax
|
|
|
call emit32
|
|
|
|
|
|
- jmp push_expr_until_brace_loop
|
|
|
+ ;; Keep note of the new variable
|
|
|
+ mov edx, temp_var
|
|
|
+ call push_var
|
|
|
|
|
|
-push_expr_until_brace_push:
|
|
|
- ;; Check if we want the address
|
|
|
- mov esi, 0
|
|
|
- cmp BYTE [ebx], AT_SIGN
|
|
|
- jne push_expr_until_brace_push_value
|
|
|
- mov esi, 1
|
|
|
- inc ebx
|
|
|
+ ret
|
|
|
|
|
|
-push_expr_until_brace_push_value:
|
|
|
- ;; Call push_expr
|
|
|
- push esi
|
|
|
- push ebx
|
|
|
- call push_expr
|
|
|
- add esp, 8
|
|
|
|
|
|
- jmp push_expr_until_brace_loop
|
|
|
+ ;; Destroys: EAX, ECX, EDX, EBX, ESI, EDI
|
|
|
+push_token_until_brace:
|
|
|
+ ;; Get a token
|
|
|
+ call get_token
|
|
|
+
|
|
|
+ ;; If it is an open brace, exit loop
|
|
|
+ mov ecx, [eax]
|
|
|
+ and ecx, 0xffff
|
|
|
+ cmp ecx, '{'
|
|
|
+ je push_token_until_brace_end
|
|
|
+
|
|
|
+ call push_token
|
|
|
+
|
|
|
+ jmp push_token_until_brace
|
|
|
|
|
|
-push_expr_until_brace_end:
|
|
|
+push_token_until_brace_end:
|
|
|
;; Given the token back
|
|
|
call give_back_token
|
|
|
|
|
@@ -745,18 +720,13 @@ push_expr_until_brace_end:
|
|
|
cmp DWORD [temp_depth], 0
|
|
|
jna platform_panic
|
|
|
|
|
|
- pop edi
|
|
|
- pop esi
|
|
|
- pop ebx
|
|
|
ret
|
|
|
|
|
|
|
|
|
+ ;; Destroys: EAX, ECX, EDX, ESI, EDI
|
|
|
parse_block:
|
|
|
push ebp
|
|
|
- mov ebp, esp
|
|
|
push ebx
|
|
|
- push esi
|
|
|
- push edi
|
|
|
|
|
|
;; Increment block depth
|
|
|
inc DWORD [block_depth]
|
|
@@ -788,17 +758,22 @@ parse_block_loop:
|
|
|
je parse_block_end
|
|
|
|
|
|
;; Jump to the appropriate handler
|
|
|
+
|
|
|
+ ;; semicolon
|
|
|
cmp ecx, ';'
|
|
|
je parse_block_semicolon
|
|
|
|
|
|
+ ;; ret
|
|
|
cmp DWORD [ebx], 'ret'
|
|
|
je parse_block_ret
|
|
|
|
|
|
+ ;; if
|
|
|
mov eax, [ebx]
|
|
|
and eax, 0xffffff
|
|
|
sub eax, 'if'
|
|
|
je parse_block_if
|
|
|
|
|
|
+ ;; while
|
|
|
mov eax, [ebx]
|
|
|
sub eax, 'whil'
|
|
|
mov ecx, [ebx+4]
|
|
@@ -807,16 +782,18 @@ parse_block_loop:
|
|
|
or eax, ecx
|
|
|
je parse_block_while
|
|
|
|
|
|
+ ;; dollar
|
|
|
cmp BYTE [ebx], DOLLAR
|
|
|
je parse_block_alloc
|
|
|
|
|
|
+ ;; backslash
|
|
|
cmp BYTE [ebx], BACKSLASH
|
|
|
je parse_block_call
|
|
|
|
|
|
- cmp BYTE [ebx], QUOTE
|
|
|
- je parse_block_string
|
|
|
-
|
|
|
- jmp parse_block_push
|
|
|
+ ;; Usual token push
|
|
|
+ mov eax, ebx
|
|
|
+ call push_token
|
|
|
+ jmp parse_block_loop
|
|
|
|
|
|
parse_block_semicolon:
|
|
|
;; Emit code to rewind temp stack
|
|
@@ -846,8 +823,8 @@ parse_block_ret_emit:
|
|
|
jmp parse_block_loop
|
|
|
|
|
|
parse_block_if:
|
|
|
- ;; Call push_expr_until_brace
|
|
|
- call push_expr_until_brace
|
|
|
+ ;; Call push_token_until_brace
|
|
|
+ call push_token_until_brace
|
|
|
|
|
|
;; Generate the else label
|
|
|
call gen_label
|
|
@@ -889,14 +866,14 @@ parse_block_if:
|
|
|
jmp parse_block_loop
|
|
|
|
|
|
parse_block_else:
|
|
|
- ;; There is an else: generate the fi label (load in edi)
|
|
|
+ ;; There is an else: generate the fi label (load in EBP)
|
|
|
call gen_label
|
|
|
- mov edi, eax
|
|
|
+ mov ebp, eax
|
|
|
|
|
|
;; Emit code to jump to fi
|
|
|
mov cl, 0xe9 ; jmp ??
|
|
|
call emit
|
|
|
- mov edx, edi
|
|
|
+ mov edx, ebp
|
|
|
call write_label
|
|
|
mov edx, eax
|
|
|
call find_symbol_or_zero
|
|
@@ -912,24 +889,26 @@ parse_block_else:
|
|
|
call parse_block
|
|
|
|
|
|
;; Add the symbol for the fi label
|
|
|
- mov edx, edi
|
|
|
+ mov edx, ebp
|
|
|
call add_symbol_label
|
|
|
|
|
|
jmp parse_block_loop
|
|
|
|
|
|
parse_block_while:
|
|
|
- ;; Generate the restart label (in esi) and the end label (in edi)
|
|
|
- call gen_label
|
|
|
- mov esi, eax
|
|
|
+ ;; Generate the restart label (in EBP)
|
|
|
call gen_label
|
|
|
- mov edi, eax
|
|
|
+ mov ebp, eax
|
|
|
|
|
|
;; Add a symbol for the restart label
|
|
|
- mov edx, esi
|
|
|
+ mov edx, ebp
|
|
|
call add_symbol_label
|
|
|
|
|
|
- ;; Call push_expr_until_brace
|
|
|
- call push_expr_until_brace
|
|
|
+ ;; Call push_token_until_brace
|
|
|
+ call push_token_until_brace
|
|
|
+
|
|
|
+ ;; Generate the end label (in EBX)
|
|
|
+ call gen_label
|
|
|
+ mov ebx, eax
|
|
|
|
|
|
;; Emit code to pop and possibly jump to end label
|
|
|
mov eax, 1
|
|
@@ -938,7 +917,7 @@ parse_block_while:
|
|
|
call emit32
|
|
|
mov ecx, 0x840f ; je ??
|
|
|
call emit16
|
|
|
- mov edx, edi
|
|
|
+ mov edx, ebx
|
|
|
call write_label
|
|
|
mov edx, eax
|
|
|
call find_symbol_or_zero
|
|
@@ -952,7 +931,7 @@ parse_block_while:
|
|
|
;; Emit code to restart the loop
|
|
|
mov cl, 0xe9 ; jmp ??
|
|
|
call emit
|
|
|
- mov edx, esi
|
|
|
+ mov edx, ebp
|
|
|
call write_label
|
|
|
mov edx, eax
|
|
|
call find_symbol_or_zero
|
|
@@ -961,7 +940,7 @@ parse_block_while:
|
|
|
call emit32
|
|
|
|
|
|
;; Add a symbol for the end label
|
|
|
- mov edx, edi
|
|
|
+ mov edx, ebx
|
|
|
call add_symbol_label
|
|
|
|
|
|
jmp parse_block_loop
|
|
@@ -1020,73 +999,12 @@ parse_block_call_loop:
|
|
|
|
|
|
parse_block_call_end:
|
|
|
;; Emit code to push the return value
|
|
|
- mov edx, temp_var
|
|
|
- call push_var
|
|
|
mov cl, 0x50 ; push eax
|
|
|
call emit
|
|
|
|
|
|
- jmp parse_block_loop
|
|
|
-
|
|
|
-parse_block_string:
|
|
|
- ;; Generate a jump (in esi) and a string (in edi) label
|
|
|
- call gen_label
|
|
|
- mov esi, eax
|
|
|
- call gen_label
|
|
|
- mov edi, eax
|
|
|
-
|
|
|
- ;; Emit code to jump to the jump label
|
|
|
- mov cl, 0xe9 ; jmp ??
|
|
|
- call emit
|
|
|
- mov edx, esi
|
|
|
- call write_label
|
|
|
- mov edx, eax
|
|
|
- call find_symbol_or_zero
|
|
|
- call compute_rel
|
|
|
- mov ecx, eax
|
|
|
- call emit32
|
|
|
-
|
|
|
- ;; Add a symbol for the string label
|
|
|
- mov edx, edi
|
|
|
- call add_symbol_label
|
|
|
-
|
|
|
- ;; Emit escaped string and a terminator
|
|
|
- mov ecx, ebx
|
|
|
- call emit_escaped_string
|
|
|
- mov cl, 0
|
|
|
- call emit
|
|
|
-
|
|
|
- ;; Add a symbol for the jump label
|
|
|
- mov edx, esi
|
|
|
- call add_symbol_label
|
|
|
-
|
|
|
- ;; Emit code to push the string label
|
|
|
+ ;; Keep not of the new pushed value
|
|
|
mov edx, temp_var
|
|
|
call push_var
|
|
|
- mov cl, 0x68 ; push ??
|
|
|
- call emit
|
|
|
- mov edx, edi
|
|
|
- call write_label
|
|
|
- mov edx, eax
|
|
|
- call find_symbol_or_zero
|
|
|
- mov ecx, eax
|
|
|
- call emit32
|
|
|
-
|
|
|
- jmp parse_block_loop
|
|
|
-
|
|
|
-parse_block_push:
|
|
|
- ;; Check if we want the address
|
|
|
- xor esi, esi
|
|
|
- cmp BYTE [ebx], AT_SIGN
|
|
|
- jne parse_block_push_value
|
|
|
- mov esi, 1
|
|
|
- inc ebx
|
|
|
-
|
|
|
-parse_block_push_value:
|
|
|
- ;; Call push_expr
|
|
|
- push esi
|
|
|
- push ebx
|
|
|
- call push_expr
|
|
|
- add esp, 8
|
|
|
|
|
|
jmp parse_block_loop
|
|
|
|
|
@@ -1110,8 +1028,6 @@ parse_block_end:
|
|
|
shl ecx, 2
|
|
|
call emit32
|
|
|
|
|
|
- pop edi
|
|
|
- pop esi
|
|
|
pop ebx
|
|
|
pop ebp
|
|
|
ret
|
|
@@ -1138,10 +1054,8 @@ decode_number_or_symbol_symbol:
|
|
|
ret
|
|
|
|
|
|
|
|
|
+ ;; Destroys: EAX, ECX, EDX, EBX, ESI, EDI
|
|
|
parse:
|
|
|
- push ebp
|
|
|
- mov ebp, esp
|
|
|
- push ebx
|
|
|
|
|
|
;; Main loop
|
|
|
parse_loop:
|
|
@@ -1271,11 +1185,10 @@ parse_var:
|
|
|
jmp parse_loop
|
|
|
|
|
|
parse_ret:
|
|
|
- pop ebx
|
|
|
- pop ebp
|
|
|
ret
|
|
|
|
|
|
|
|
|
+ ;; Destroys: EAX, ECX
|
|
|
init_g_compiler:
|
|
|
;; Allocate stack variables list
|
|
|
mov eax, STACK_VARS_LEN * MAX_SYMBOL_NAME_LEN
|
|
@@ -1303,6 +1216,7 @@ init_g_compiler:
|
|
|
ret
|
|
|
|
|
|
|
|
|
+ ;; Destroys: EAX, ECX, EDX, EBX, ESI, EDI
|
|
|
compile:
|
|
|
;; Reset depths and stage
|
|
|
mov DWORD [block_depth], 0
|
|
@@ -1339,4 +1253,3 @@ compile_stage_loop:
|
|
|
add DWORD [stage], 1
|
|
|
|
|
|
jmp compile_stage_loop
|
|
|
-
|