From 18a66f62962a2b99969e38a07570cd95f3d4053f Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Sat, 26 Oct 2019 22:45:02 -0400 Subject: [PATCH] Rearranged types to ensure better compliance with C type rules --- bootstrap/.gitignore | 6 - bootstrap/bootstrap-x86.sh | 71 - bootstrap/x86/cc_x86.M1 | 4974 ------------------------------------ cc.h | 1 + cc_types.c | 86 +- test/test.answers | 8 +- test/test100/proof.answer | 2 +- 7 files changed, 57 insertions(+), 5091 deletions(-) delete mode 100644 bootstrap/.gitignore delete mode 100755 bootstrap/bootstrap-x86.sh delete mode 100644 bootstrap/x86/cc_x86.M1 diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore deleted file mode 100644 index 082c2c4..0000000 --- a/bootstrap/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -M2.M1 -M2.hex2 -cc_x86 -hold -seed.hex2 - diff --git a/bootstrap/bootstrap-x86.sh b/bootstrap/bootstrap-x86.sh deleted file mode 100755 index 68e6d57..0000000 --- a/bootstrap/bootstrap-x86.sh +++ /dev/null @@ -1,71 +0,0 @@ -#! /usr/bin/env bash -## Copyright (C) 2017 Jeremiah Orians -## This file is part of M2-Planet. -## -## M2-Planet is free software: you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## (at your option) any later version. -## -## M2-Planet is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with M2-Planet. If not, see . - -set -eux -[ -e ../bin/M2-Planet ] && rm ../bin/M2-Planet - -# Make the required bin directry -[ -d ../bin ] || mkdir ../bin - -# Macro assemble with libc written in M1-Macro -M1 -f x86/cc_x86.M1 \ - --LittleEndian \ - --architecture x86 \ - -o seed.hex2 || exit 1 - -# Resolve all linkages -hex2 -f ../test/common_x86/ELF-i386.hex2 \ - -f seed.hex2 \ - --LittleEndian \ - --architecture x86 \ - --BaseAddress 0x8048000 \ - -o cc_x86 \ - --exec_enable || exit 2 - -# Build M2-Planet from cc_x86 -catm hold ../test/common_x86/functions/file.c \ - ../test/common_x86/functions/malloc.c \ - ../functions/calloc.c \ - ../test/common_x86/functions/exit.c \ - ../functions/match.c \ - ../functions/in_set.c \ - ../functions/numerate_number.c \ - ../functions/file_print.c \ - ../functions/number_pack.c \ - ../functions/fixup.c \ - ../functions/string.c \ - ../cc.h \ - ../cc_reader.c \ - ../cc_strings.c \ - ../cc_types.c \ - ../cc_core.c \ - ../cc.c -./cc_x86 hold M2.M1 -M1 --architecture x86 \ - --LittleEndian \ - -f ../test/common_x86/x86_defs.M1 \ - -f ../test/common_x86/libc-core.M1 \ - -f M2.M1 \ - -o M2.hex2 - -hex2 -f ../test/common_x86/ELF-i386.hex2 \ - -f M2.hex2 \ - --LittleEndian \ - --architecture x86 \ - --BaseAddress 0x8048000 \ - -o ../bin/M2-Planet-seed \ - --exec_enable diff --git a/bootstrap/x86/cc_x86.M1 b/bootstrap/x86/cc_x86.M1 deleted file mode 100644 index c65e590..0000000 --- a/bootstrap/x86/cc_x86.M1 +++ /dev/null @@ -1,4974 +0,0 @@ -;; Copyright (C) 2017 Jeremiah Orians -;; This file is part of stage0. -;; -;; stage0 is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. -;; -;; stage0 is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with stage0. If not, see . - -DEFINE ADDI8_EAX 83C0 -DEFINE ADDI8_EBX 83C3 -DEFINE ADDI8_ECX 83C1 -DEFINE ADDI8_EDX 83C2 -DEFINE ADDI8_ESI 83C6 -DEFINE ADD_eax_into_ebx 01C3 -DEFINE ADD_ebx_into_eax 01D8 -DEFINE ADD_ecx_into_eax 01C8 -DEFINE ADD_edi_into_ecx 01F9 -DEFINE AND_EAX_EBX 21D8 -DEFINE ANDI32_EAX 25 -DEFINE CALL_EAX FFD0 -DEFINE CALL32 E8 -DEFINE CMPI8_EAX 83F8 -DEFINE CMPI8_EBP 83fd -DEFINE CMPI8_EBX 83FB -DEFINE CMPI8_ECX 83F9 -DEFINE CMPI8_EDX 83FA -DEFINE CMPI8_ESI 83FE -DEFINE CMP_EAX_EBX 39D8 -DEFINE CMP_EAX_ECX 39C8 -DEFINE CMP_EBX_ECX 39D9 -DEFINE CMP_ECX_EBX 39CB -DEFINE CMP_EDI_ESI 39FE -DEFINE CMP_EBX_EDX 39D3 -DEFINE COPY_EAX_to_EBP 89C5 -DEFINE COPY_EAX_to_EBX 89C3 -DEFINE COPY_EAX_to_ECX 89C1 -DEFINE COPY_EAX_to_EDX 89C2 -DEFINE COPY_EAX_to_ESI 89C6 -DEFINE COPY_EBP_to_EAX 89E8 -DEFINE COPY_EBX_to_EAX 89D8 -DEFINE COPY_EBX_to_ECX 89D9 -DEFINE COPY_EBX_to_EDX 89DA -DEFINE COPY_ECX_to_EAX 89C8 -DEFINE COPY_ECX_to_EBX 89CB -DEFINE COPY_EDI_to_ESI 89FE -DEFINE COPY_EDX_to_EAX 89D0 -DEFINE COPY_EDX_to_EBP 89D5 -DEFINE COPY_EDX_to_EBX 89D3 -DEFINE COPY_ESI_to_EAX 89F0 -DEFINE COPY_ESI_to_EDI 89F7 -DEFINE IDIV_EBX F7FB -DEFINE IMUL_EAX_by_EBX 0FAFC3 -DEFINE IMULI8_EAX 6BC0 -DEFINE IMULI8_EBP 6BED -DEFINE INT_80 CD80 -DEFINE JBE8 76 -DEFINE JE32 0F84 -DEFINE JG32 0F8F -DEFINE JG8 7F -DEFINE JL32 0F8C -DEFINE JLE32 0F8E -DEFINE JMP32 E9 -DEFINE JNE32 0F85 -DEFINE LEA32_ECX_from_esp 8D0C24 -DEFINE LOAD32_Absolute32_eax A1 -DEFINE LOAD32_Absolute32_ebx 8B1D -DEFINE LOAD32_Absolute32_ecx 8B0D -DEFINE LOAD32_EAX_from_EAX 8B00 -DEFINE LOAD32_EAX_from_EAX_Immediate8 8B40 -DEFINE LOAD32_EAX_from_EBP_Immediate8 8B45 -DEFINE LOAD32_EAX_from_EBX 8B03 -DEFINE LOAD32_EAX_from_EBX_Immediate8 8B43 -DEFINE LOAD32_EAX_from_ECX_Immediate8 8B41 -DEFINE LOAD32_EAX_from_EDX_Immediate8 8B42 -DEFINE LOAD32_EBP_from_EBP 8B6D00 -DEFINE LOAD32_EBX_from_EAX_Immediate8 8B58 -DEFINE LOAD32_EBX_from_EBX 8B1B -DEFINE LOAD32_EBX_from_EBX_Immediate8 8B5B -DEFINE LOAD32_EBX_from_ECX_Immediate8 8B59 -DEFINE LOAD32_ECX_from_EAX_Immediate8 8B48 -DEFINE LOAD32_ECX_from_EBX 8B0B -DEFINE LOAD32_ECX_from_ECX 8B09 -DEFINE LOAD32_ECX_from_ECX_Immediate8 8B49 -DEFINE LOAD32_ECX_from_EDX_Immediate8 8B4A -DEFINE LOAD32_EDI_from_EDX_Immediate8 8B7A -DEFINE LOAD32_EDX_from_EDX_Immediate8 8B52 -DEFINE LOAD8_al_from_EAX 8A00 -DEFINE LOAD8_al_from_EBX 8A03 -DEFINE LOAD8_al_from_ECX 8A01 -DEFINE LOAD8_al_from_EDX 8A02 -DEFINE LOAD8_bl_from_EBX 8A1B -DEFINE LOAD8_bl_from_ECX 8A19 -DEFINE LOAD8_bl_from_EDX 8A1A -DEFINE LOAD8_cl_from_EBX 8A0B -DEFINE LOAD8_cl_from_EBX_Immediate8 8A4B -DEFINE LOADI32_EAX B8 -DEFINE LOADI32_EBX BB -DEFINE LOADI32_ECX B9 -DEFINE LOADI32_EDI BF -DEFINE LOADI32_EDX BA -DEFINE LOADI32_ESI BE -DEFINE MOVZX_al 0FB6C0 -DEFINE MOVZX_bl 0FB6DB -DEFINE MOVZX_cl 0FB6C9 -DEFINE NULL 00000000 -DEFINE POP_EAX 58 -DEFINE POP_EBP 5D -DEFINE POP_EBX 5B -DEFINE POP_ECX 59 -DEFINE POP_EDI 5F -DEFINE POP_EDX 5A -DEFINE POP_ESI 5E -DEFINE PUSH_EAX 50 -DEFINE PUSH_EBP 55 -DEFINE PUSH_EBX 53 -DEFINE PUSH_ECX 51 -DEFINE PUSH_EDI 57 -DEFINE PUSH_EDX 52 -DEFINE PUSH_ESI 56 -DEFINE RETURN C3 -DEFINE SALI8_EAX C1E0 -DEFINE SHRI8_EAX C1E8 -DEFINE SHRI8_EBX C1EB -DEFINE STORE32_Absolute32_eax A3 -DEFINE STORE32_Absolute32_ebx 891D -DEFINE STORE32_Absolute32_ecx 890D -DEFINE STORE32_Absolute32_edx 8915 -DEFINE STORE32_EAX_into_EBP_Immediate8 8945 -DEFINE STORE32_EAX_into_EBX 8903 -DEFINE STORE32_EAX_into_ECX_Immediate8 8941 -DEFINE STORE32_EAX_into_EDX 8902 -DEFINE STORE32_EAX_into_EDX_Immediate8 8942 -DEFINE STORE32_EBP_into_EDX_Immediate8 896A -DEFINE STORE32_EBX_into_EAX 8918 -DEFINE STORE32_EBX_into_EAX_Immediate8 8958 -DEFINE STORE32_EBX_into_EDX_Immediate8 895A -DEFINE STORE32_ECX_into_EAX 8908 -DEFINE STORE32_ECX_into_EAX_Immediate8 8948 -DEFINE STORE32_ECX_into_EDX_Immediate8 894A -DEFINE STORE32_EDX_into_EAX_Immediate8 8950 -DEFINE STORE32_EDX_into_EBP_Immediate8 8955 -DEFINE STORE32_ESI_into_EBP_Immedate8 8975 -DEFINE STORE32_ESI_into_EDX_Immedate8 8972 -DEFINE STORE8_al_into_Address_EBX 8803 -DEFINE STORE8_al_into_Address_ECX 8801 -DEFINE STORE8_al_into_Address_ESI 8806 -DEFINE STORE8_bl_into_Address_ECX 8819 -DEFINE SUBI8_EAX 83E8 -DEFINE SUBI8_ECX 83E9 -DEFINE SUBI8_ESI 83EE -DEFINE SWAP_EAX_EBX 93 - - - ;; Register usage: - ;; EAX => Temps - - ;; Struct TYPE format: (size 28) - ;; NEXT => 0 - ;; SIZE => 4 - ;; OFFSET => 8 - ;; INDIRECT => 12 - ;; MEMBERS => 16 - ;; TYPE => 20 - ;; NAME => 24 - - ;; Struct TOKEN_LIST format: (size 20) - ;; NEXT => 0 - ;; LOCALS/PREV => 4 - ;; S => 8 - ;; TYPE => 12 - ;; ARGS/DEPTH => 16 - -; Where the ELF Header is going to hit -; Simply jump to _start -; Our main function -:_start - POP_EAX ;·Get·the·number·of·arguments - POP_EBX ;·Get·the·program·name - POP_EBX ;·Get·the·actual·input name - LOADI32_ECX %0 ;·prepare·read_only - LOADI32_EAX %5 ;·the·syscall·number·for·open() - INT_80 ; Now open that damn file - STORE32_Absolute32_eax &Input_file ; Preserve the file pointer we were given - - POP_EBX ;·Get·the·actual·output name - LOADI32_ECX %577 ; Prepare file as O_WRONLY|O_CREAT|O_TRUNC - LOADI32_EDX %384 ; Prepare file as RW for owner only (600 in octal) - LOADI32_EAX %5 ;·the·syscall·number·for·open() - INT_80 ; Now open that damn file - CMPI8_EAX !0 ; Check for missing output - JG32 %_start_out ; Have real input - LOADI32_EAX %1 ; Use stdout - -:_start_out - STORE32_Absolute32_eax &Output_file ; Preserve the file pointer we were given - - LOADI32_EAX %45 ; the Syscall # for SYS_BRK - LOADI32_EBX %0 ; Get current brk - INT_80 ; Let the kernel do the work - STORE32_Absolute32_eax &MALLOC ; Set our malloc pointer - LOADI32_EAX %0 ; HEAD = NULL - CALL32 %read_all_tokens ; Read all tokens - CALL32 %Reverse_List ; Reverse order -; CALL32 %debug_list ; Try to figure out what is wrong - STORE32_Absolute32_eax &global_token ; Set global_token - CALL32 %program ; Convert into program - LOADI32_EAX &header_string1 ; Our header string - CALL32 %File_Print ; Print it - LOAD32_Absolute32_eax &output_list ; Our output_list - CALL32 %recursive_output ; Print core program -; LOADI32_EAX &header_string2 ; Our Enable debug -; CALL32 %File_Print ; Print it - LOADI32_EAX &header_string3 ; Our second label - CALL32 %File_Print ; Print it - LOAD32_Absolute32_eax &globals_list ; Our globals - CALL32 %recursive_output ; Get them - LOADI32_EAX &header_string4 ; Our final header - CALL32 %File_Print ; Print it - LOAD32_Absolute32_eax &strings_list ; Our strings - CALL32 %recursive_output ; Get them - LOADI32_EAX &header_string5 ; Make this a bare assembly - CALL32 %File_Print ; Print it - -:Done - ; program completed Successfully - LOADI32_EBX %0 ; All is well - LOADI32_EAX %1 ; put the exit syscall number in eax - INT_80 ; Call it a good day - -:header_string1 " -# Core program -" -:header_string2 " -:ELF_data -" -:header_string3 " -# Program global variables -" -:header_string4 " -# Program strings -" -:header_string5 " -:ELF_end -" - - -;; read_all_tokens function -;; Receives Token_List* in EAX -;; Tokenizes all input and returns updated list in EAX -;; Returns TOKEN in EAX -;; Uses EAX for C -:read_all_tokens - STORE32_Absolute32_eax &Token - CALL32 %fgetc -:read_all_tokens_loop - CMPI8_EAX !-4 ; Check for EOF - JE32 %read_all_tokens_done ; Stop if found - CALL32 %get_token ; Read all tokens - JMP32 %read_all_tokens_loop ; Loop -:read_all_tokens_done - LOAD32_Absolute32_eax &Token - RETURN - - -;; get_token function -;; Receives INT in EAX -;; Makes a list of TOKEN_LIST -;; C and STRING_INDEX are stored in memory, ECX is used for S and EDX is used for current -;; Returns C in EAX -:get_token - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - - STORE32_Absolute32_eax &C ; Set C - - LOADI32_EAX %20 ; Malloc CURRENT - CALL32 %malloc ; Get Pointer - COPY_EAX_to_EDX ; Set CURRENT - - LOADI32_EAX %256 ; Malloc the string - CALL32 %malloc ; Get pointer to S - COPY_EAX_to_ECX ; Set S - STORE32_ECX_into_EDX_Immediate8 !8 ; CURRENT->S = S -:reset - STORE32_Absolute32_ecx &string_index ; S[0] - LOAD32_Absolute32_eax &C ; Using C - - CALL32 %clear_white_space ; Clear WhiteSpace - STORE32_Absolute32_eax &C ; Set C - - CMPI8_EAX !-4 ; Check for EOF - JE32 %get_token_abort ; if EOF abort - - CMPI8_EAX !35 ; Check for '#' - JNE32 %get_token_alpha ; Nope - - ;; Deal with # line comments - CALL32 %purge_macro ; Let it handle it - STORE32_Absolute32_eax &C ; Set C - JMP32 %reset ; Try again - -:get_token_alpha - LOAD32_Absolute32_eax &C ; Send C - LOADI32_EBX &alphas ; Get alphanumerics - CALL32 %In_Set ; See if in set - CMPI8_EAX !1 ; IF TRUE - JNE32 %get_token_symbol ; Otherwise - - ;; Store keywords - LOAD32_Absolute32_eax &C ; Send C - CALL32 %preserve_keyword ; Store - STORE32_Absolute32_eax &C ; Set C - JMP32 %get_token_done ; Be done with this token - -:get_token_symbol - LOAD32_Absolute32_eax &C ; Send C - LOADI32_EBX &symbols ; Get symbols - CALL32 %In_Set ; See if in set - CMPI8_EAX !1 ; IF TRUE - JNE32 %get_token_strings ; Otherwise - - ;; Store symbols - LOAD32_Absolute32_eax &C ; Send C - CALL32 %preserve_symbol ; Store - STORE32_Absolute32_eax &C ; Set C - JMP32 %get_token_done ; Be done with this token - -:get_token_strings - LOAD32_Absolute32_eax &C ; Send C - LOADI32_EBX &strings ; Get symbols - CALL32 %In_Set ; See if in set - CMPI8_EAX !1 ; IF TRUE - JNE32 %get_token_comment ; Otherwise - - ;; Store String - LOAD32_Absolute32_eax &C ; Send C - CALL32 %consume_word ; Store - STORE32_Absolute32_eax &C ; Set C - JMP32 %get_token_done ; Be done with this token - -:get_token_comment - LOAD32_Absolute32_eax &C ; Send C - CMPI8_EAX !47 ; IF '/' == C - JNE32 %get_token_else ; Otherwise - - CALL32 %consume_byte ; Hope it just is '/' - STORE32_Absolute32_eax &C ; Set C - - CMPI8_EAX !42 ; IF '*' we have '/*' - JNE32 %get_token_comment_line ; Check for '//' - - ;; Deal with /* block comments */ - CALL32 %fgetc ; get next C - STORE32_Absolute32_eax &C ; Set C -:get_token_comment_block_outer - LOAD32_Absolute32_eax &C ; Using C - CMPI8_EAX !47 ; IF '/' != C - JE32 %get_token_comment_block_done ; be done - -:get_token_comment_block_inner - LOAD32_Absolute32_eax &C ; Using C - CMPI8_EAX !42 ; IF '*' != C - JE32 %get_token_comment_block_iter ; jump over - - ;; Deal with inner loop - CALL32 %fgetc ; get next C - STORE32_Absolute32_eax &C ; Set C - JMP32 %get_token_comment_block_inner ; keep going - -:get_token_comment_block_iter - CALL32 %fgetc ; get next C - STORE32_Absolute32_eax &C ; Set C - JMP32 %get_token_comment_block_outer - -:get_token_comment_block_done - CALL32 %fgetc ; get next C - STORE32_Absolute32_eax &C ; Set C - JMP32 %reset ; throw away, try again - -:get_token_comment_line - CMPI8_EAX !47 ; IF '/' we have // - JNE32 %get_token_done ; keep if just '/' - - ;; Deal with // line comment - CALL32 %fgetc ; drop to match - STORE32_Absolute32_eax &C ; Set C - JMP32 %reset ; throw away, try again - -:get_token_else - LOAD32_Absolute32_eax &C ; Send C - CALL32 %consume_byte - STORE32_Absolute32_eax &C ; Set C - -:get_token_done - LOAD32_Absolute32_eax &Token ; TOKEN - STORE32_EAX_into_EDX_Immediate8 !4 ; CURRENT->PREV = TOKEN - STORE32_EAX_into_EDX ; CURRENT->NEXT = TOKEN - STORE32_Absolute32_edx &Token ; TOKEN = CURRENT - -:get_token_abort - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - LOAD32_Absolute32_eax &C ; Return C - RETURN - - -;; Malloc isn't actually required if the program being built fits in the initial memory -;; However, it doesn't take much to add it. -;; Requires [MALLOC] to be initialized and EAX to have the number of desired bytes -:malloc - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - LOAD32_Absolute32_ebx &MALLOC ; Using the current pointer - ADD_eax_into_ebx ; Request the number of desired bytes - LOADI32_EAX %45 ; the Syscall # for SYS_BRK - INT_80 ; call the Kernel - LOAD32_Absolute32_eax &MALLOC ; Return pointer - STORE32_Absolute32_ebx &MALLOC ; Update pointer - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; clear_white_space function -;; Receives INT C in EAX -;; Returns first non-whitespace char in EAX -:clear_white_space - CMPI8_EAX !32 ; Check for ' ' - JE32 %clear_white_space_wipe ; wipe it out - - CMPI8_EAX !10 ; Check for '\n' - JE32 %clear_white_space_wipe ; wipe it output - - CMPI8_EAX !9 ; Check for '\t' - JNE32 %clear_white_space_done ; looks like non-whitespace - -:clear_white_space_wipe - CALL32 %fgetc ; Read a new byte - CMPI8_EAX !-4 ; Check for EOF - JE32 %clear_white_space_done ; Short circuit - JMP32 %clear_white_space ; iterate - -:clear_white_space_done - RETURN - - -;; In_Set function -;; Receives Char C in EAX and CHAR* in EBX -;; Returns 1 if true, zero if false in EAX -:In_Set - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX -:In_Set_loop - LOAD8_cl_from_EBX ; Read char - MOVZX_cl ; Zero extend it - - CMP_EAX_ECX ; See if they match - JE32 %In_Set_True ; return true - - CMPI8_ECX !0 ; Check for NULL - JE32 %In_Set_False ; return false - - ADDI8_EBX !1 ; s = s + 1 - JMP32 %In_Set_loop ; Keep looping - -:In_Set_True - LOADI32_EAX %1 ; Set True - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:In_Set_False - LOADI32_EAX %0 ; Set FALSE - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:alphas "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" -:symbols "<=>|&!-" -:strings '22 27 00' - - -;; purge_macro function -;; Receives CH in EAX -;; Reads chars until Line feed is read -;; returns line feed -:purge_macro - CALL32 %fgetc ; read next char - CMPI8_EAX !10 ; Check for '\n' - JNE32 %purge_macro ; Keep going - RETURN - - -;; preserve_keyword function -;; Receives INT C in EAX -;; collects all chars in keyword -;; Returns C in EAX -;; Uses ECX for INT C -:preserve_keyword - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; Setup C - LOADI32_EBX &alphas ; Concerning ourselves with "abc.." -:preserve_keyword_loop - CALL32 %In_Set ; Check if alphanumerics - CMPI8_EAX !1 ; IF TRUE - JNE32 %preserve_keyword_label ; Otherwise check for label - - COPY_ECX_to_EAX ; Pass C - CALL32 %consume_byte ; consume that byte - COPY_EAX_to_ECX ; Update C - JMP32 %preserve_keyword_loop ; keep looping - -:preserve_keyword_label - COPY_ECX_to_EAX ; Fix return - CMPI8_EAX !58 ; Check for ':' - JNE32 %preserve_keyword_done ; be done - - ;; Fix our goto label - CALL32 %fixup_label ; Fix the label - LOADI32_EAX %32 ; Return Whitespace - -:preserve_keyword_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; preserve_symbol function -;; Receives INT C in EAX -;; collects all chars in symbol -;; Returns C in EAX -;; Uses ECX for INT C -:preserve_symbol - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; Setup C - LOADI32_EBX &symbols ; Concerning ourselves with "<=>.." -:preserve_symbol_loop - CALL32 %In_Set ; Check if alphanumerics - CMPI8_EAX !1 ; IF TRUE - JNE32 %preserve_symbol_done ; Otherwise be done - - COPY_ECX_to_EAX ; Pass C - CALL32 %consume_byte ; consume that byte - COPY_EAX_to_ECX ; Update C - JMP32 %preserve_symbol_loop ; keep looping - -:preserve_symbol_done - COPY_ECX_to_EAX ; Fix return - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; consume_word function -;; receives INT C in EAX -;; returns INT C in EAX -;; Uses EAX for C, EBX for FREQ and ECX for ESCAPE -:consume_word - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_EBX ; FREQ = C - LOADI32_ECX %0 ; ESCAPE = FALSE -:consume_word_loop - CMPI8_ECX !0 ; IF !ESCAPE - JNE32 %consume_word_escape ; Enable escape - - CMPI8_EAX !92 ; if '\\' - JNE32 %consume_word_iter ; keep state - - LOADI32_ECX %1 ; ESCAPE = TRUE - JMP32 %consume_word_iter ; keep going - -:consume_word_escape - LOADI32_ECX %0 ; ESCAPE = FALSE - -:consume_word_iter - CALL32 %consume_byte ; read next char - - CMPI8_ECX !0 ; IF ESCAPE - JNE32 %consume_word_loop ; keep looping - - CMP_EAX_EBX ; IF C != FREQ - JNE32 %consume_word_loop ; keep going - - CALL32 %fgetc ; return next char - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; consume_byte function -;; Receives INT C in EAX -;; Inserts C into string S, updates String S -;; Returns Next char in EAX -:consume_byte - PUSH_EBX ; Protect EBX - LOAD32_Absolute32_ebx &string_index ; S[0] - STORE8_al_into_Address_EBX ; S[0] = C - ADDI8_EBX !1 ; S = S + 1 - STORE32_Absolute32_ebx &string_index ; Update S - CALL32 %fgetc - POP_EBX ; Restore EBX - RETURN - - -;; fixup_label function -;; Receives S in ECX -;; prepends ':' to string and returns registers un changed -;; Uses EAX for HOLD, EBX for PREV and ECX for S[0] -:fixup_label - PUSH_EAX ; Protect EAX - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOADI32_EAX %58 ; HOLD = ':' - LOAD32_ECX_from_EDX_Immediate8 !8 ; HOLD_STRING[0] -:fixup_label_loop - COPY_EAX_to_EBX ; PREV = HOLD - LOAD8_al_from_ECX ; HOLD = HOLD_STRING[I] - MOVZX_al ; make useful - STORE8_bl_into_Address_ECX ; HOLD_STRING[I] = PREV - ADDI8_ECX !1 ; I = I + 1 - CMPI8_EAX !0 ; IF NULL == HOLD - JNE32 %fixup_label_loop ; Keep looping - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - POP_EAX ; Restore EAX - RETURN - - -;; fgetc function -;; Loads FILE* from [INPUT_FILE] -;; Returns -4 (EOF) or char in EAX -:fgetc - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - LOADI32_EAX %-4 ; Put EOF in eax - PUSH_EAX ; Assume bad (If nothing read, value will remain EOF) - LEA32_ECX_from_esp ; Get stack address - LOAD32_Absolute32_ebx &Input_file ; Where are we reading from - LOADI32_EAX %3 ; the syscall number for read - LOADI32_EDX %1 ; set the size of chars we want - INT_80 ; call the Kernel - POP_EAX ; Get either char or EOF - CMPI8_EAX !-4 ; Check for EOF - JE32 %fgetc_done ; Return as is - MOVZX_al ; Make it useful -:fgetc_done - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; Reverse_List function -;; Receives List in EAX -;; Returns the list reversed in EAX -:Reverse_List - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_EBX ; Set HEAD - LOADI32_EAX %0 ; ROOT = NULL -:Reverse_List_Loop - CMPI8_EBX !0 ; WHILE HEAD != NULL - JE32 %Reverse_List_Done ; Stop otherwise - - LOAD32_ECX_from_EBX ; NEXT = HEAD->NEXT - STORE32_EAX_into_EBX ; HEAD->NEXT = ROOT - COPY_EBX_to_EAX ; ROOT = HEAD - COPY_ECX_to_EBX ; HEAD = NEXT - JMP32 %Reverse_List_Loop ; Keep Going - -:Reverse_List_Done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; recursive_output function -;; Receives list in EAX -;; walks the list and prints the I->S for all nodes backwards -;; Uses EBX for I -:recursive_output - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CMPI8_EAX !0 ; Check for NULL - JE32 %recursive_output_done ; Skip the work - COPY_EAX_to_EBX ; I = Head - - LOAD32_EAX_from_EBX ; Iterate to next Token - CALL32 %recursive_output ; Recurse - - LOAD32_EAX_from_EBX_Immediate8 !8 ; Using S - CALL32 %File_Print ; Print it - -:recursive_output_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; File_Print function -;; Receives CHAR* in EAX -;; calls fputc for every non-null char -:File_Print - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_EBX ; Protect S - CMPI8_EAX !0 ; Protect against nulls - JE32 %File_Print_Done ; Simply don't try to print them -:File_Print_Loop - LOAD8_al_from_EBX ; Read byte - MOVZX_al ; zero extend - CMPI8_EAX !0 ; Check for NULL - JE32 %File_Print_Done ; Stop at NULL - - CALL32 %fputc ; write it - ADDI8_EBX !1 ; S = S + 1 - JMP32 %File_Print_Loop ; Keep going - -:File_Print_Done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; fputc function -;; receives CHAR in EAX and load FILE* from [OUTPUT_FILE] -;; writes char and returns -:fputc - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_EAX ; We are writing eax - LEA32_ECX_from_esp ; Get stack address - LOAD32_Absolute32_ebx &Output_file ; Write to target file - LOADI32_EAX %4 ; the syscall number for write - LOADI32_EDX %1 ; set the size of chars we want - INT_80 ; call the Kernel - POP_EAX ; Restore stack - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; program function -;; receives nothing, returns nothing -;; Uses EAX for type_size -:program - ;; The binary initialized the globals to null, so we can skip those steps - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - -:new_type - LOAD32_Absolute32_eax &global_token ; Using global_token - CMPI8_EAX !0 ; Check if NULL - JE32 %program_done ; Be done if null - - LOAD32_EBX_from_EAX_Immediate8 !8 ; GLOBAL_TOKEN->S - LOADI32_EAX &constant ; "CONSTANT" - CALL32 %match ; IF GLOBAL_TOKEN->S == "CONSTANT" - CMPI8_EAX !0 ; If true - JNE32 %program_else ; Looks like not a constant - - ;; Deal with minimal constant case - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EBX %0 ; NULL - LOAD32_Absolute32_ecx &global_constant_list ; global_constant_list - CALL32 %sym_declare ; Declare that constant - STORE32_Absolute32_eax &global_constant_list ; global_constant_list = sym_declare(global_token->s, NULL, global_constant_list); - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX ; global_token->next - STORE32_EBX_into_EAX_Immediate8 !16 ; global_constant_list->arguments = global_token->next - - LOAD32_EBX_from_EBX ; global_token->next->next - STORE32_Absolute32_ebx &global_token ; global_token = global_token->next->next - JMP32 %new_type ; go around again - -:program_else - CALL32 %type_name ; Figure out the type_size - CMPI8_EAX !0 ; IF NULL == type_size - JE32 %new_type ; it was a new type - - ;; Add to global symbol table - COPY_EAX_to_EBX ; put type_size in the right spot - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD32_Absolute32_ecx &global_symbol_list ; Using global_symbol_list - CALL32 %sym_declare ; Declare symbol - STORE32_Absolute32_eax &global_symbol_list ; global_symbol_list = sym_declare(global_token->s, type_size, global_symbol_list); - LOAD32_Absolute32_ebx &global_token ; Using global token - LOAD32_EBX_from_EBX ; global_token->next - STORE32_Absolute32_ebx &global_token ; global_token = global_token->next - - LOAD32_Absolute32_ebx &global_token ; Using global token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &semicolon ; ";" - CALL32 %match ; if(match(";", global_token->s)) - CMPI8_EAX !0 ; If true - JNE32 %program_function ; looks like not a match - - ;; Deal with the global variable - LOAD32_Absolute32_ebx &globals_list ; Using globals_list - LOADI32_EAX &program_string_0 ; ":GLOBAL_" - CALL32 %emit ; Emit it - COPY_EAX_to_EBX ; update globals_list - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !4 ; global token->prev - LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->prev->s - CALL32 %emit ; Emit it - - COPY_EAX_to_EBX ; update globals_list - LOADI32_EAX &program_string_1 ; "\nNOP\n" - CALL32 %emit ; Emit it - STORE32_Absolute32_eax &globals_list ; update globals_list - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - JMP32 %new_type ; go around again - -:program_function - LOAD32_Absolute32_ebx &global_token ; Using global token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_paren ; "(" - CALL32 %match ; if(match(";", global_token->s)) - CMPI8_EAX !0 ; If true - JNE32 %program_error ; Otherwise deal with error case - - ;; Deal with function definition - CALL32 %declare_function ; Lets get the parsing rolling - JMP32 %new_type ; Keep looping through functions - -:program_error - ;; Deal with the case of something we don't support - ;; NOT IMPLEMENTED - -:program_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -;; Strings needed by the program function -:program_string_0 ":GLOBAL_" -:program_string_1 " -NOP -" - - -;; declare_function function -;; Receives nothing and returns nothing -;; Sets current function and adds it to the global function list -:declare_function - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOADI32_EAX %0 ; Using NULL - STORE32_Absolute32_eax ¤t_count ; current_count = 0 - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !4 ; global token->prev - LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->prev->s - LOADI32_EBX %0 ; NULL - LOAD32_Absolute32_ecx &global_function_list ; global_function_list - CALL32 %sym_declare ; sym_declare(global_token->prev->s, NULL, global_function_list); - STORE32_Absolute32_eax &function ; function = sym_declare(global_token->prev->s, NULL, global_function_list); - STORE32_Absolute32_eax &global_function_list ; global_function_list = function - - CALL32 %collect_arguments ; collect all of the function arguments - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global token->s - LOADI32_EBX &semicolon ; ";" - CALL32 %match ; IF global token->s == ";" - CMPI8_EAX !0 ; If true - JNE32 %declare_function_full ; It was a prototype - - ;; Deal with prototypes - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX ; global token->next - STORE32_Absolute32_eax &global_token ; global token = global token->next - JMP32 %declare_function_done ; Move on - -:declare_function_full - ;; Deal will full function definitions - LOADI32_EAX &declare_function_string_0 ; "# Defining function " - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &function ; function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->s - CALL32 %emit_out ; emit it - - LOADI32_EAX &declare_function_string_1 ; "\n:FUNCTION_" - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &function ; function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->s - CALL32 %emit_out ; emit it - - LOADI32_EAX &declare_function_string_3 ; "\n" - CALL32 %emit_out ; emit it - - CALL32 %statement ; Recursively get the function pieces - - LOAD32_Absolute32_eax &output_list ; output - LOAD32_EAX_from_EAX_Immediate8 !8 ; output->s - LOADI32_EBX &declare_function_string_2 ; "RETURN\n" - CALL32 %match ; IF output->s == "RETURN\n" - CMPI8_EAX !0 ; If true we can skip adding it - JE32 %declare_function_done ; otherwise we need to add it - - ;; Add the return to the end of a function lacking a return; - LOADI32_EAX &declare_function_string_2 ; "RETURN\n" - CALL32 %emit_out ; emit it - -:declare_function_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:declare_function_string_0 "# Defining function " -:declare_function_string_1 " -:FUNCTION_" -:declare_function_string_2 "RETURN -" -:declare_function_string_3 " -" - - -;; collect_arguments function -;; Receives nothing -;; Returns Nothing -;; Adds arguments to the function definition -;; holds struct type* type_size in ECX, then replace with struct token_list* a in ECX when type_size is used -:collect_arguments - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next -:collect_arguments_loop - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &close_paren ; ")" - CALL32 %match ; IF global_token->S == ")" - CMPI8_EAX !0 ; we reached the end - JE32 %collect_arguments_done ; be done - - ;; deal with the case of there are arguments - CALL32 %type_name ; Get the type - COPY_EAX_to_ECX ; put type_size safely out of the way - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &close_paren ; ")" - CALL32 %match ; IF global_token->S == ")" - CMPI8_EAX !0 ; is a foo(int, char,void) case - JE32 %collect_arguments_common ; deal with commas - - ;; Trying second else - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &comma ; "," - CALL32 %match ; IF global_token->S == "," - CMPI8_EAX !0 ; then deal with the common - JE32 %collect_arguments_common ; case of commas between arguments - - ;; deal with foo(int a, char b) - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - COPY_ECX_to_EBX ; put type_size in the right place - LOAD32_Absolute32_ecx &function ; Using function - LOAD32_ECX_from_ECX_Immediate8 !16 ; function->args - CALL32 %sym_declare ; sym_declare(global_token->s, type_size, function->arguments); - COPY_EAX_to_ECX ; put a in a safe place - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args - CMPI8_EAX !0 ; IF function->args == NULL - JNE32 %collect_arguments_another ; otherwise it isn't the first - - ;; Deal with the case of first argument in the function - LOADI32_EAX %-4 ; -4 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->depth = -4 - JMP32 %collect_arguments_next ; get to next - -:collect_arguments_another - ;; deal with the case of non-first arguments - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args->depth - SUBI8_EAX !4 ; function->args->depth - 4 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->depth = function->args->depth - 4 - -:collect_arguments_next - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOAD32_Absolute32_eax &function ; Using function - STORE32_ECX_into_EAX_Immediate8 !16 ; function->args = a - -:collect_arguments_common - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &comma ; "," - CALL32 %match ; IF global_token->S == "," - CMPI8_EAX !0 ; then deal with the comma - JNE32 %collect_arguments_loop ; otherwise loop - - ;; keep foo(bar(), 1) expressions working - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - JMP32 %collect_arguments_loop ; keep going - -:collect_arguments_done - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; statement function -;; Receives nothing -;; Returns nothing -;; Walks down global_token recursively to collect the contents of the function -:statement - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_curly_brace ; "{" - CALL32 %match ; IF global_token->S == "{" - JNE32 %statement_label ; otherwise try label - - ;; deal with { statement } - CALL32 %recursive_statement ; Statements inside of statements for days - JMP32 %statement_done ; Be done - -:statement_label - LOAD8_al_from_EBX ; global_token->S[0] - MOVZX_al ; make it useful - CMPI8_EAX !58 ; IF global_token->S == ':' - JNE32 %statement_local ; otherwise try locals - - ;; deal with labels - COPY_EBX_to_EAX ; put global_token->S in the right spot - CALL32 %emit_out ; emit it - - LOADI32_EAX &statement_string_0 ; Using "\t#C goto label\n" - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - JMP32 %statement_done ; be done - -:statement_local - COPY_EBX_to_EAX ; put global_token->S in the right place - LOADI32_EBX &prim_types ; pointer to primative types - CALL32 %lookup_type ; See if found - CMPI8_EAX !0 ; IF NULL == lookup_type(global_token->S, prim_types) - JNE32 %statement_local_success ; Sweet a new local - - ;; Second chance - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &struct ; "struct" - CALL32 %match ; IF global_token->S == "struct" - CMPI8_EAX !0 ; then we are a local - JNE32 %statement_if ; otherwise try IF - -:statement_local_success - CALL32 %collect_local ; Grab those locals - JMP32 %statement_done ; be done - -:statement_if - LOADI32_EAX &if_string ; Using "if" - CALL32 %match ; IF global_token->S == "if" - CMPI8_EAX !0 ; then we have an if statement - JNE32 %statement_do ; otherwise try DO - - ;; Deal with IF statement - CALL32 %process_if ; DO IT - JMP32 %statement_done ; be done - -:statement_do - LOADI32_EAX &do_string ; Using "do" - CALL32 %match ; IF global_token->S == "do" - CMPI8_EAX !0 ; then we have a do statement - JNE32 %statement_while ; otherwise try WHILE - - ;; Deal with DO statement - CALL32 %process_do ; DO IT - JMP32 %statement_done ; be done - -:statement_while - LOADI32_EAX &while_string ; Using "while" - CALL32 %match ; IF global_token->S == "while" - CMPI8_EAX !0 ; then we have a while statement - JNE32 %statement_for ; otherwise try FOR - - ;; Deal with WHILE statement - CALL32 %process_while ; DO IT - JMP32 %statement_done ; be done - -:statement_for - LOADI32_EAX &for_string ; Using "for" - CALL32 %match ; IF global_token->S == "for" - CMPI8_EAX !0 ; then we have a for statement - JNE32 %statement_asm ; otherwise try ASM - - ;; Deal with FOR statement - CALL32 %process_for ; DO IT - JMP32 %statement_done ; be done - -:statement_asm - LOADI32_EAX &asm_string ; Using "asm" - CALL32 %match ; IF global_token->S == "asm" - CMPI8_EAX !0 ; then we have an asm statement - JNE32 %statement_goto ; otherwise try GOTO - - ;; Deal with ASM statement - CALL32 %process_asm ; Hit it - JMP32 %statement_done ; be done - -:statement_goto - LOADI32_EAX &goto_string ; Using "goto" - CALL32 %match ; IF global_token->S == "goto" - CMPI8_EAX !0 ; then we have a goto statement - JNE32 %statement_return ; Otherwise try RETURN - - ;; Deal with GOTO statement - LOADI32_EAX &statement_string_1 ; Using "JUMP %" - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %emit_out ; emit it - - LOADI32_EAX &statement_string_2 ; Using "\n" - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure it has the required - JMP32 %statement_done ; Be done - -:statement_return - LOADI32_EAX &return_string ; Using "return" - CALL32 %match ; IF global_token->S == "return" - CMPI8_EAX !0 ; then we have a return statement - JNE32 %statement_break ; Otherwise try BREAK - - ;; Deal with RETURN Statement - CALL32 %return_result ; Return anything they want - JMP32 %statement_done ; be done - -:statement_break - LOADI32_EAX &break_string ; Using "break" - CALL32 %match ; IF global_token->S == "break" - CMPI8_EAX !0 ; then we have a break statement - JNE32 %statement_continue ; Otherwise try CONTINUE - - ;; Deal with BREAK statement - CALL32 %process_break ; Lets do some damage - JMP32 %statement_done ; be done - -:statement_continue - LOADI32_EAX &continue_string ; Using "continue" - CALL32 %match ; IF global_token->S == "continue" - CMPI8_EAX !0 ; then we have a continue statement - JNE32 %statement_else ; Otherwise we are punting to an expression - - ;; Deal with CONTINUE statement - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOADI32_EAX &statement_string_3 ; Using "\n#continue statement\n" - CALL32 %emit_out ; emit it - - LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Don't forget the ";" - JMP32 %statement_done ; Be done - -:statement_else - CALL32 %expression ; Collect expression - LOADI32_EAX &statement_string_4 ; Using "ERROR in statement\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; make sure we have it - -:statement_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:statement_string_0 " #C goto label -" -:statement_string_1 "JUMP %" -:statement_string_2 " -" -:statement_string_3 " -#continue statement -" -:statement_string_4 "ERROR in statement -Missing ; -" - - -;; recursive_statement function -;; Receives nothing -;; Returns nothing -;; Walks the global_token list to build the contents of statements -;; Uses struct token_list* frame in ECX -:recursive_statement - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOAD32_Absolute32_ecx &function ; Using function - LOAD32_ECX_from_ECX_Immediate8 !4 ; frame = function->locals - -:recursive_statement_loop - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &close_curly_brace ; Using "}" - CALL32 %match ; IF global_token->S == "}" - CMPI8_EAX !0 ; Then we are done recuring - JE32 %recursive_statement_cleanup ; and then we clean up - - ;; Deal with the recursive calls - CALL32 %statement ; Deal with another statement - JMP32 %recursive_statement_loop ; loop some more - -:recursive_statement_cleanup - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOADI32_EAX &recursive_statement_string_0 ; Using "RETURN\n" - LOAD32_Absolute32_ebx &output_list ; Using output - LOAD32_EBX_from_EBX_Immediate8 !8 ; output->S - CALL32 %match ; IF output->S == "RETURN\n" - CMPI8_EAX !0 ; Then we can skip the clean up - JE32 %recursive_statement_done ; and be done - - ;; Deal with cleanup - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EBX_from_EBX_Immediate8 !4 ; i = function->locals - LOADI32_EAX &recursive_statement_string_1 ; Using "POP_ebx\t# _recursive_statement_locals\n" - -:recursive_statement_locals - CMP_ECX_EBX ; IF frame != i - JE32 %recursive_statement_done ; Otherwise be done - - ;; Lets emit - CALL32 %emit_out ; emit it - LOAD32_EBX_from_EBX ; i = i->next - JMP32 %recursive_statement_locals ; keep going - -:recursive_statement_done - LOAD32_Absolute32_eax &function ; Using function - STORE32_ECX_into_EAX_Immediate8 !4 ; function->locals = frame - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:recursive_statement_string_0 "RETURN -" -:recursive_statement_string_1 "POP_ebx # _recursive_statement_locals -" - - -;; return_result function -;; Receives nothing -;; Returns nothing -;; Cleans up function and generates return -;; Also handles returing expressions -:return_result - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; make it useful - CMPI8_EAX !59 ; If global_token->S[0] == ';' - JE32 %return_result_cleanup ; Go straight to cleanup - - CALL32 %expression ; get the expression we are returning - -:return_result_cleanup - LOADI32_EAX &return_result_string_0 ; Using "ERROR in return_result\nMISSING ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EBX_from_EBX_Immediate8 !4 ; function->locals - LOADI32_EAX &return_result_string_1 ; Using "POP_ebx\t# _return_result_locals\n" -:return_result_locals - CMPI8_EBX !0 ; IF NULL == i - JE32 %return_result_done ; Be done - - CALL32 %emit_out ; Emit out pop - LOAD32_EBX_from_EBX ; i = i->NEXT - JMP32 %return_result_locals ; Keep going - -:return_result_done - LOADI32_EAX &return_result_string_2 ; Using "RETURN\n" - CALL32 %emit_out ; Emit it - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:return_result_string_0 "ERROR in return_result -MISSING ; -" -:return_result_string_1 "POP_ebx # _return_result_locals -" -:return_result_string_2 "RETURN -" - - -;; collect_local function -;; Receives nothing -;; Returns nothing -;; Walks global_token list to create function locals -;; Uses ECX for struct token_list* A -:collect_local - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %type_name ; Get the local's type - - COPY_EAX_to_EBX ; Put struct type* type_size in the right place - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD32_Absolute32_ecx &function ; Using function - LOAD32_ECX_from_ECX_Immediate8 !4 ; function->locals - CALL32 %sym_declare ; Declare it - COPY_EAX_to_ECX ; put it away safely - - ;; Try for main - LOADI32_EAX &main_string ; Using "main" - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EBX_from_EBX_Immediate8 !8 ; function->S - CALL32 %match ; IF match("main", function->s) - CMPI8_EAX !0 ; possible - JNE32 %collect_local_fresh ; try to see if fresh function - - ;; Ok we are in main, now to see if main is fresh - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals - CMPI8_EAX !0 ; IF NULL == function->locals - JNE32 %collect_local_fresh ; try to see if fresh function - - ;; Sweet we are in a fresh main - LOADI32_EAX %-20 ; We start at -20 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = -20 - JMP32 %collect_local_common ; Go to the commons - -:collect_local_fresh - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args - CMPI8_EAX !0 ; IF NULL == function->locals - JNE32 %collect_local_first ; Otherwise see if first - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals - CMPI8_EAX !0 ; IF NULL == function->locals - JNE32 %collect_local_first ; Otherwise try first - - ;; Sweet we are in a fresh function - LOADI32_EAX %-8 ; We start at -8 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = -8 - JMP32 %collect_local_common ; Go to the commons - -:collect_local_first - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals - CMPI8_EAX !0 ; IF NULL == function->locals - JNE32 %collect_local_else ; Looks like we are just another local - - ;; Ok we are the first local - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->args->depth - SUBI8_EAX !8 ; function->arguments->depth - 8 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = function->arguments->depth - 8 - JMP32 %collect_local_common ; Go to the commons - -:collect_local_else - ;; Always the last to know - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !4 ; function->locals - LOAD32_EAX_from_EAX_Immediate8 !16 ; function->locals->depth - SUBI8_EAX !4 ; function->locals->depth - 4 - STORE32_EAX_into_ECX_Immediate8 !16 ; a->DEPTH = function->locals->depth - 4 - -:collect_local_common - LOAD32_Absolute32_eax &function ; Using function - - STORE32_ECX_into_EAX_Immediate8 !4 ; function->locals = a - LOAD32_ECX_from_ECX_Immediate8 !8 ; a->S - - LOADI32_EAX &collect_local_string_0 ; Using "# Defining local " - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %emit_out ; emit it - - LOADI32_EAX &collect_local_string_1 ; Using "\n" - CALL32 %emit_out ; emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; Using "=" - CALL32 %match ; IF match("=", global_token->s) - CMPI8_EAX !0 ; Deal with assignment - JNE32 %collect_local_done ; Otherwise finish it - - ;; Deal with assignment - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - CALL32 %expression ; Recurse - -:collect_local_done - LOADI32_EAX &collect_local_string_2 ; Using "ERROR in collect_local\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &collect_local_string_3 ; Using "PUSH_eax\t#" - CALL32 %emit_out ; emit it - - COPY_ECX_to_EAX ; put A->S where it belongs - CALL32 %emit_out ; emit it - - LOADI32_EAX &collect_local_string_1 ; Using "\n" - CALL32 %emit_out ; emit it - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:collect_local_string_0 "# Defining local " -:collect_local_string_1 " -" -:collect_local_string_2 "ERROR in collect_local -Missing ; -" -:collect_local_string_3 "PUSH_eax #" - - -;; process_asm function -;; Receives nothing -;; Returns nothing -;; Simply inlines the asm statements -;; Uses EBX for global_token temp storage -:process_asm - PUSH_EBX ; Protect EBX - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &process_asm_string_0 ; Using "ERROR in process_asm\nMISSING (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - LOAD32_Absolute32_ebx &global_token ; Using global_token -:process_asm_iter - LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !34 ; IF global_token->S[0] == '\"' - JNE32 %process_asm_done ; Otherwise be done - - LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S - ADDI8_EAX !1 ; global_token->S + 1 - CALL32 %emit_out ; Emit it - - LOADI32_EAX &process_asm_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOAD32_EBX_from_EBX ; global_token->NEXT - STORE32_Absolute32_ebx &global_token ; global_token = global_token->NEXT - JMP32 %process_asm_iter ; keep going - -:process_asm_done - LOADI32_EAX &process_asm_string_2 ; Using "ERROR in process_asm\nMISSING )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &process_asm_string_3 ; Using "ERROR in process_asm\nMISSING ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - POP_EBX ; Restore EBX - RETURN - -:process_asm_string_0 "ERROR in process_asm -MISSING ( -" -:process_asm_string_1 " -" -:process_asm_string_2 "ERROR in process_asm -MISSING ) -" -:process_asm_string_3 "ERROR in process_asm -MISSING ; -" - - -;; process_if function -;; Receives nothing -;; Returns Nothing -;; Increments current_count recurses into expression + statement -;; Uses ECX for char* NUMBER_STRING -:process_if - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax ¤t_count ; Using current count - COPY_EAX_to_EBX ; Preparing for update - ADDI8_EBX !1 ; current_count + 1 - STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1 - CALL32 %numerate_number ; convert to string - COPY_EAX_to_ECX ; put NUMBER_STRING in place - - LOADI32_EAX &process_if_string_0 ; Using "# IF_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &process_if_string_1 ; Using "ERROR in process_if\nMISSING (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - CALL32 %expression ; Recurse to get the IF(...) part - - LOADI32_EAX &process_if_string_2 ; Using "TEST\nJUMP_EQ %ELSE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_if_string_3 ; Using "ERROR in process_if\nMISSING )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - CALL32 %statement ; Recursive to get the IF(){...} part - - LOADI32_EAX &process_if_string_4 ; Using "JUMP %_END_IF_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_if_string_5 ; Using ":ELSE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &else_string ; Using "else" - CALL32 %match ; IF global_token->S == "else" - CMPI8_EAX !0 ; Then we need to collect the else too - JNE32 %process_if_done ; Otherwise finish up - - ;; deal with else statement - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - CALL32 %statement ; Recurse to get the ELSE {...} part - -:process_if_done - LOADI32_EAX &process_if_string_6 ; Using ":_END_IF_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:process_if_string_0 "# IF_" -:process_if_string_1 "ERROR in process_if -MISSING ( -" -:process_if_string_2 "TEST -JUMP_EQ %ELSE_" -:process_if_string_3 "ERROR in process_if -MISSING ) -" -:process_if_string_4 "JUMP %_END_IF_" -:process_if_string_5 ":ELSE_" -:process_if_string_6 ":_END_IF_" - - -;; save_break_frame microfunction -;; Overwrites EAX abd EBX -;; Saves break frame on stack -;; Returns to caller -:save_break_frame - POP_EBX ; Save return Address - LOAD32_Absolute32_eax &break_frame ; Get break_frame - PUSH_EAX ; Store as nested_locals - LOAD32_Absolute32_eax &break_target_head ; Get break_target_head - PUSH_EAX ; Store as nested_break_head - LOAD32_Absolute32_eax &break_target_func ; Get break_target_func - PUSH_EAX ; Store as nested_break_func - LOAD32_Absolute32_eax &break_target_num ; Get break_target_num - PUSH_EAX ; Store as nested_break_num - PUSH_EBX ; Put return back in place - RETURN ; Return to caller - - -;; restore_break_frame microfunction -;; Overwrites EAX and EBX -;; Restores break frame from stack -;; Returns to caller -:restore_break_frame - POP_EBX ; Save return Address - POP_EAX ; Get nested_break_num - STORE32_Absolute32_eax &break_target_num ; Restore break_target_num - POP_EAX ; Get nested_break_func - STORE32_Absolute32_eax &break_target_func ; Restore break_target_func - POP_EAX ; Get nested_break_head - STORE32_Absolute32_eax &break_target_head ; Restore break_target_head - POP_EAX ; Get nested_locals - STORE32_Absolute32_eax &break_frame ; Restore break_frame - PUSH_EBX ; Put return back in place - RETURN ; Return to caller - - -;; set_break_frame microfunction -;; Receives char* head in EAX and char* num in EBX -;; Overwrites EAX and EBX -;; Returns to calling function -:set_break_frame - STORE32_Absolute32_eax &break_target_head ; update break_target_head - STORE32_Absolute32_ebx &break_target_num ; update break_target_num - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EAX_from_EBX_Immediate8 !4 ; function->LOCALS - STORE32_Absolute32_eax &break_frame ; break_frame = function->LOCALS - LOAD32_EAX_from_EBX_Immediate8 !8 ; function->S - STORE32_Absolute32_eax &break_target_func ; break_target_func = function->S - RETURN ; Return to sender - - -;; process_do function -;; Receives Nothing -;; Returns Nothing -;; Increments current_count and leverages save/restore_break_frame pieces -;; Uses ECX for char* NUMBER_STRING -:process_do - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %save_break_frame ; Save the frame - - LOAD32_Absolute32_eax ¤t_count ; Using current count - COPY_EAX_to_EBX ; Preparing for update - ADDI8_EBX !1 ; current_count + 1 - STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1 - CALL32 %numerate_number ; convert to string - COPY_EAX_to_ECX ; put NUMBER_STRING in place - - LOADI32_EAX &process_do_string_0 ; Using "DO_END_" - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %set_break_frame ; Set the frame - - LOADI32_EAX &process_do_string_1 ; Using ":DO_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - CALL32 %statement ; Do the DO {...} part - - LOADI32_EAX &process_do_string_2 ; Using "ERROR in process_do\nMISSING while\n" - LOADI32_EBX &while_string ; Using "while" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &process_do_string_3 ; Using "ERROR in process_do\nMISSING (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - CALL32 %expression ; Do the WHILE (...) part - - LOADI32_EAX &process_do_string_4 ; Using "ERROR in process_do\nMISSING )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &process_do_string_5 ; Using "ERROR in process_do\nMISSING ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &process_do_string_6 ; Using "TEST\nJUMP_NE %DO_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_do_string_7 ; Using ":DO_END_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - CALL32 %restore_break_frame ; Restore the old break frame - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:process_do_string_0 "DO_END_" -:process_do_string_1 ":DO_" -:process_do_string_2 "ERROR in process_do -MISSING while -" -:process_do_string_3 "ERROR in process_do -MISSING ( -" -:process_do_string_4 "ERROR in process_do -MISSING ) -" -:process_do_string_5 "ERROR in process_do -MISSING ; -" -:process_do_string_6 "TEST -JUMP_NE %DO_" -:process_do_string_7 ":DO_END_" - - -;; process_while function -;; Receives nothing -;; Returns nothing -;; Increments current_count and leverages save/restore_break_frame pieces -;; Uses ECX for char* NUMBER_STRING -:process_while - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %save_break_frame ; Save break_frame - - LOAD32_Absolute32_eax ¤t_count ; Using current count - COPY_EAX_to_EBX ; Preparing for update - ADDI8_EBX !1 ; current_count + 1 - STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1 - CALL32 %numerate_number ; convert to string - COPY_EAX_to_ECX ; put NUMBER_STRING in place - - LOADI32_EAX &process_while_string_0 ; Using "END_WHILE_" - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %set_break_frame ; Set it and forget it - - LOADI32_EAX &process_while_string_1 ; Using ":WHILE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &process_while_string_2 ; Using "ERROR in process_while\nMISSING (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - CALL32 %expression ; Deal with the WHILE (...) part - - LOADI32_EAX &process_while_string_3 ; Using "TEST\nJUMP_EQ %END_WHILE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_while_string_4 ; Using "# THEN_while_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_while_string_5 ; Using "ERROR in process_while\nMISSING )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - CALL32 %statement ; Deal with the {....} part - - LOADI32_EAX &process_while_string_6 ; Using "JUMP %WHILE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_while_string_7 ; Using ":END_WHILE_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - CALL32 %restore_break_frame ; Restore the old break frame - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:process_while_string_0 "END_WHILE_" -:process_while_string_1 ":WHILE_" -:process_while_string_2 "ERROR in process_while -MISSING ( -" -:process_while_string_3 "TEST -JUMP_EQ %END_WHILE_" -:process_while_string_4 "# THEN_while_" -:process_while_string_5 "ERROR in process_while -MISSING ) -" -:process_while_string_6 "JUMP %WHILE_" -:process_while_string_7 ":END_WHILE_" - - -;; process_for function -;; Receives Nothing -;; Returns Nothing -;; Increments current_count and leverages save/restore_break_frame pieces -;; Uses ECX for char* NUMBER_STRING -:process_for - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %save_break_frame ; Save the frame - - LOAD32_Absolute32_eax ¤t_count ; Using current count - COPY_EAX_to_EBX ; Preparing for update - ADDI8_EBX !1 ; current_count + 1 - STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1 - CALL32 %numerate_number ; convert to string - COPY_EAX_to_ECX ; put NUMBER_STRING in place - - LOADI32_EAX &process_for_string_0 ; Using "FOR_END_" - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %set_break_frame ; Set it and forget it - - LOADI32_EAX &process_for_string_1 ; Using "# FOR_initialization_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &process_for_string_2 ; Using "ERROR in process_for\nMISSING (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make Sure we have it - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &semicolon ; Using ";" - CALL32 %match ; IF global_token->S == ";" - CMPI8_EAX !0 ; Then no initializer - JE32 %process_for_terminator ; And skip getting the expression - - ;; Deal with FOR (...; case - CALL32 %expression ; Get the FOR ( ... ; part - -:process_for_terminator - LOADI32_EAX &process_for_string_3 ; Using ":FOR_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_4 ; Using "ERROR in process_for\nMISSING ;1\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - CALL32 %expression ; Get the FOR ( ; ... ; Part - - LOADI32_EAX &process_for_string_5 ; Using "TEST\nJUMP_EQ %FOR_END_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_6 ; Using "JUMP %FOR_THEN_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_7 ; Using ":FOR_ITER_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_8 ; Using "ERROR in process_for\nMISSING ;2\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - CALL32 %expression ; Get the FOR (;;...) part - - LOADI32_EAX &process_for_string_9 ; Using "JUMP %FOR_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_10 ; Using ":FOR_THEN_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_11 ; Using "ERROR in process_for\nMISSING )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - CALL32 %statement ; Get FOR (;;) {...} part - - LOADI32_EAX &process_for_string_12 ; Using "JUMP %FOR_ITER_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Passing NUMBER_STRING - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - LOADI32_EAX &process_for_string_13 ; Using ":FOR_END_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID_out ; uniqueID_out(function->s, number_string) - - CALL32 %restore_break_frame ; Restore the old break frame - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:process_for_string_0 "FOR_END_" -:process_for_string_1 "# FOR_initialization_" -:process_for_string_2 "ERROR in process_for -MISSING ( -" -:process_for_string_3 ":FOR_" -:process_for_string_4 "ERROR in process_for -MISSING ;1 -" -:process_for_string_5 "TEST -JUMP_EQ %FOR_END_" -:process_for_string_6 "JUMP %FOR_THEN_" -:process_for_string_7 ":FOR_ITER_" -:process_for_string_8 "ERROR in process_for -MISSING ;2 -" -:process_for_string_9 "JUMP %FOR_" -:process_for_string_10 ":FOR_THEN_" -:process_for_string_11 "ERROR in process_for -MISSING ) -" -:process_for_string_12 "JUMP %FOR_ITER_" -:process_for_string_13 ":FOR_END_" - - -;; process_break function -;; Receives nothing -;; Returns nothing -;; Handles the break out of loops case -;; Uses EBX for struct token_list* break_frame and ECX for struct token_list* I -:process_break - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax &break_target_head ; Catch big error - CMPI8_EAX !0 ; IF(NULL == break_target_head) - JE32 %process_break_bad ; I'm sorry Mr White but you have stage-3 lung cancer - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_ECX_from_EAX_Immediate8 !4 ; I = function->LOCALS - LOAD32_Absolute32_ebx &break_frame ; Put break_frame in the right spot - LOADI32_EAX &process_break_string_1 ; Using "POP_ebx\t# break_cleanup_locals\n" - -:process_break_iter - CMPI8_ECX !0 ; IF (NULL == I) - JE32 %process_break_cleaned ; We are done - - CMP_EBX_ECX ; IF I != break_frame - JE32 %process_break_cleaned ; We are done - - CALL32 %emit_out ; Emit it - LOAD32_ECX_from_ECX ; I = I->NEXT - JMP32 %process_break_iter ; Keep looping - -:process_break_cleaned - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &process_break_string_2 ; Using "JUMP %" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &break_target_head ; Get what we are in - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &break_target_func ; Get what function we are in - CALL32 %emit_out ; Emit it - - LOADI32_EAX &underline ; Using "_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &break_target_num ; Get dem digits - CALL32 %emit_out ; Emit it - - LOADI32_EAX &process_break_string_3 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &process_break_string_4 ; Using "ERROR in break statement\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:process_break_bad - ;; Breaking badly - LOADI32_EAX %2 ; Using standard error - STORE32_Absolute32_eax &Output_file ; write to standard error -; CALL32 %line_error ; Write useful debug info - COPY_ECX_to_EAX ; put S in the right place - CALL32 %File_Print ; print it - - LOADI32_EAX &process_break_string_0 ; Ending string - CALL32 %File_Print ; print it - JMP32 %Exit_Failure ; Abort Hard - -:process_break_string_0 "Not inside of a loop or case statement" -:process_break_string_1 "POP_ebx # break_cleanup_locals -" -:process_break_string_2 "JUMP %" -:process_break_string_3 " -" -:process_break_string_4 "ERROR in break statement -Missing ; -" - - -;; expression function -;; Receives Nothing -;; Returns Nothing -;; Walks global_token and updates output_list -;; Uses EAX and EBX for match and ECX for char* store -:expression - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %bitwise_expr ; Collect bitwise expressions - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; "=" - CALL32 %match ; IF global_token->S == "=" - CMPI8_EAX !0 ; We have to deal with assignment - JNE32 %expression_done ; Looks like nope - - ;; Deal with possible assignment - LOADI32_ECX &expression_string_1 ; Assume "STORE_CHAR\n" by default - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !4 ; global_token->PREV - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->PREV->S - LOADI32_EAX &close_bracket ; Using "]" - CALL32 %match ; IF global_token->S == "]" - CMPI8_EAX !0 ; Then we might have a char - JNE32 %expression_int ; Otherwise INT - - LOAD32_Absolute32_ebx ¤t_target ; Using current_target - LOAD32_EBX_from_EBX_Immediate8 !24 ; current_target->NAME - LOADI32_EAX &type_char_indirect_name ; Using "char*" - CALL32 %match ; Intensional inefficency because I feel like it - CMPI8_EAX !0 ; IF current_target->NAME == "char*" - JNE32 %expression_int ; Do char anyway - - JMP32 %expression_common ; Looks like we have to use "STORE_CHAR\n" - -:expression_int - LOADI32_ECX &expression_string_0 ; Use "STORE_INTEGER\n" - -:expression_common - LOADI32_EAX &expression ; Passing expression - CALL32 %common_recursion ; Recurse - COPY_ECX_to_EAX ; Using Store - CALL32 %emit_out ; Emit it - LOADI32_EAX %0 ; Using NULL - STORE32_Absolute32_eax ¤t_target ; current_target = NULL - -:expression_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:expression_string_0 "STORE_INTEGER -" -:expression_string_1 "STORE_CHAR -" - - -;; bitwise_expr function -;; Receives nothing -;; Returns nothing -;; Walks global_token list and updates output list -;; Just calls other functions -:bitwise_expr - CALL32 %relational_expr ; Walk up the tree - CALL32 %bitwise_expr_stub ; Let general recursion do the work - RETURN - - -;; bitwise_expr_stub function -;; Receives nothing -;; Returns Nothing -;; Just calls general_recursion a bunch -;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion -:bitwise_expr_stub - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - - LOADI32_EAX &relational_expr ; Using relational_expr - LOADI32_EBX &bitwise_expr_stub_string_0 ; Using "AND_eax_ebx\n" - LOADI32_ECX &bitwise_and ; Using "&" - LOADI32_EDX &bitwise_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &relational_expr ; Using relational_expr - LOADI32_EBX &bitwise_expr_stub_string_0 ; Using "AND_eax_ebx\n" - LOADI32_ECX &logical_and ; Using "&&" - LOADI32_EDX &bitwise_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &relational_expr ; Using relational_expr - LOADI32_EBX &bitwise_expr_stub_string_1 ; Using "OR_eax_ebx\n" - LOADI32_ECX &bitwise_or ; Using "|" - LOADI32_EDX &bitwise_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &relational_expr ; Using relational_expr - LOADI32_EBX &bitwise_expr_stub_string_1 ; Using "OR_eax_ebx\n" - LOADI32_ECX &logical_or ; Using "||" - LOADI32_EDX &bitwise_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &relational_expr ; Using relational_expr - LOADI32_EBX &bitwise_expr_stub_string_2 ; Using "XOR_ebx_eax_into_eax\n" - LOADI32_ECX &bitwise_xor ; Using "^" - LOADI32_EDX &bitwise_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:bitwise_expr_stub_string_0 "AND_eax_ebx -" -:bitwise_expr_stub_string_1 "OR_eax_ebx -" -:bitwise_expr_stub_string_2 "XOR_ebx_eax_into_eax -" - - -;; relational_expr function -;; Receives nothing -;; Returns Nothing -;; Walks global_token list and updates output list -;; just calls other function -:relational_expr - CALL32 %additive_expr ; Walk up the tree - CALL32 %relational_expr_stub ; Recurse - RETURN - - -;; relational_expr_stub function -;; Receives nothing -;; Returns Nothing -;; Just calls general_recursion a bunch -;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion -:relational_expr_stub - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_0 ; Using "CMP\nSETL\nMOVEZBL\n" - LOADI32_ECX &less_than_string ; Using "<" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_1 ; Using "CMP\nSETLE\nMOVEZBL\n" - LOADI32_ECX &less_than_equal_string ; Using "<=" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_2 ; Using "CMP\nSETGE\nMOVEZBL\n" - LOADI32_ECX &greater_than_equal_string ; Using ">=" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_3 ; Using "CMP\nSETG\nMOVEZBL\n" - LOADI32_ECX &greater_than_string ; Using ">" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_4 ; Using "CMP\nSETE\nMOVEZBL\n" - LOADI32_ECX &equal_to_string ; Using "==" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &additive_expr ; Using additive_expr - LOADI32_EBX &relational_expr_stub_string_5 ; Using "CMP\nSETNE\nMOVEZBL\n" - LOADI32_ECX ¬_equal_string ; Using "!=" - LOADI32_EDX &relational_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:relational_expr_stub_string_0 "CMP -SETL -MOVEZBL -" -:relational_expr_stub_string_1 "CMP -SETLE -MOVEZBL -" -:relational_expr_stub_string_2 "CMP -SETGE -MOVEZBL -" -:relational_expr_stub_string_3 "CMP -SETG -MOVEZBL -" -:relational_expr_stub_string_4 "CMP -SETE -MOVEZBL -" -:relational_expr_stub_string_5 "CMP -SETNE -MOVEZBL -" - - -;; additive_expr function -;; Receives nothing -;; Returns Nothing -;; Walks global_token list and updates output list -;; just calls other function -:additive_expr - CALL32 %postfix_expr ; Walk up the tree - CALL32 %additive_expr_stub ; Recurse - RETURN - - -;; additive_expr_stub function -;; Receives nothing -;; Returns Nothing -;; Just calls general_recursion a bunch -;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion -:additive_expr_stub - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_0 ; Using "ADD_ebx_to_eax\n" - LOADI32_ECX &plus_string ; Using "+" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_1 ; Using "SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n" - LOADI32_ECX &minus_string ; Using "-" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_2 ; Using "MULTIPLY_eax_by_ebx_into_eax\n" - LOADI32_ECX &multiply_string ; Using "*" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_3 ; Using "XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nDIVIDE_eax_by_ebx_into_eax\n" - LOADI32_ECX ÷_string ; Using "/" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_4 ; Using "XCHG_eax_ebx\nLOAD_IMMEDIATE_edx %0\nMODULUS_eax_from_ebx_into_ebx\nMOVE_edx_to_eax\n" - LOADI32_ECX &modulus_string ; Using "%" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_5 ; Using "COPY_eax_to_ecx\nCOPY_ebx_to_eax\nSAL_eax_cl\n" - LOADI32_ECX &left_shift_string ; Using "<<" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - LOADI32_EAX &postfix_expr ; Using postfix_expr - LOADI32_EBX &additive_expr_stub_string_6 ; Using "COPY_eax_to_ecx\nCOPY_ebx_to_eax\nSAR_eax_cl\n" - LOADI32_ECX &right_shift_string ; Using ">>" - LOADI32_EDX &additive_expr_stub ; And recurse - CALL32 %general_recursion ; Hit it - - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:additive_expr_stub_string_0 "ADD_ebx_to_eax -" -:additive_expr_stub_string_1 "SUBTRACT_eax_from_ebx_into_ebx -MOVE_ebx_to_eax -" -:additive_expr_stub_string_2 "MULTIPLY_eax_by_ebx_into_eax -" -:additive_expr_stub_string_3 "XCHG_eax_ebx -LOAD_IMMEDIATE_edx %0 -DIVIDE_eax_by_ebx_into_eax -" -:additive_expr_stub_string_4 "XCHG_eax_ebx -LOAD_IMMEDIATE_edx %0 -MODULUS_eax_from_ebx_into_ebx -MOVE_edx_to_eax -" -:additive_expr_stub_string_5 "COPY_eax_to_ecx -COPY_ebx_to_eax -SAL_eax_cl -" -:additive_expr_stub_string_6 "COPY_eax_to_ecx -COPY_ebx_to_eax -SAR_eax_cl -" - - -;; postfix_expr function -;; Receives nothing -;; Returns Nothing -;; Walks global_token list and updates output list -;; just calls other function -:postfix_expr - CALL32 %primary_expr ; Walk up the tree - CALL32 %postfix_expr_stub ; Recurse - RETURN - - -;; postfix_expr_stub function -;; Receives nothing -;; Returns Nothing -;; Checks for "[" and "->" and deals with them otherwise does nothing -;; Uses EAX, EBX, ECX and EDX for passing constants to general recursion -:postfix_expr_stub - PUSH_EBX ; Protect EBX - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_bracket ; Using "[" - CALL32 %match ; IF global_token->S == "[" - CMPI8_EAX !0 ; then we have an array - JNE32 %postfix_expr_stub_arrow ; Otherwise try arrow - - ;; Deal with array - CALL32 %postfix_expr_array ; Get it - CALL32 %postfix_expr_stub ; Recurse - -:postfix_expr_stub_arrow - LOADI32_EAX &arrow_string ; Using "->" - CALL32 %match ; IF global_token->S == "->" - CMPI8_EAX !0 ; Then we need to deal with struct offsets - JNE32 %postfix_expr_stub_done ; Otherwise be done - - ;; Deal with arrow - CALL32 %postfix_expr_arrow ; Get it - CALL32 %postfix_expr_stub ; Recurse - -:postfix_expr_stub_done - POP_EBX ; Restore EBX - RETURN - - -;; unary_expr_sizeof function -;; Receives nothing -;; Returns nothing -;; Uses ECX for A->SIZE -:unary_expr_sizeof - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &unary_expr_sizeof_string_0 ; Using "ERROR in unary_expr\nMissing (\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - CALL32 %type_name ; Get the type - LOAD32_ECX_from_EAX_Immediate8 !4 ; Set A->TYPE - - LOADI32_EAX &unary_expr_sizeof_string_1 ; Using "ERROR in unary_expr\nMissing )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &unary_expr_sizeof_string_2 ; Using "LOAD_IMMEDIATE_eax %" - CALL32 %emit_out ; Emit it - - COPY_ECX_to_EAX ; Put A->SIZE in the right place - CALL32 %numerate_number ; Turn into string - CALL32 %emit_out ; Emit it - - LOADI32_EAX &unary_expr_sizeof_string_3 ; Using "\n" - CALL32 %emit_out ; Emit it - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:unary_expr_sizeof_string_0 "ERROR in unary_expr -Missing ( -" -:unary_expr_sizeof_string_1 "ERROR in unary_expr -Missing ) -" -:unary_expr_sizeof_string_2 "LOAD_IMMEDIATE_eax %" -:unary_expr_sizeof_string_3 " -" - - -;; postfix_expr_array function -;; Receives Nothing -;; Returns Nothing -;; Uses EBX for struct type* ARRAY and ECX for char* ASSIGN -:postfix_expr_array - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax ¤t_target ; ARRAY = current_target - PUSH_EAX ; Protect it - - LOADI32_EAX &expression ; Using expression - CALL32 %common_recursion ; Recurse - - POP_EBX ; Restore array - STORE32_Absolute32_ebx ¤t_target ; current_target = ARRAY - - LOADI32_ECX &postfix_expr_array_string_0 ; ASSIGN = "LOAD_INTEGER\n" - - LOADI32_EAX &type_char_indirect_name ; Using "char*" - LOAD32_EBX_from_EBX_Immediate8 !24 ; current_target->NAME - CALL32 %match ; IF current_target->NAME == "char*" - CMPI8_EAX !0 ; load a byte - JNE32 %postfix_expr_array_large ; Otherwise adjust - - ;; Deal with loading byte - LOADI32_ECX &postfix_expr_array_string_1 ; ASSIGN = "LOAD_BYTE\n" - JMP32 %postfix_expr_array_common ; Do the next bit - -:postfix_expr_array_large - ;; deal with arrays made of things other than chars - LOADI32_EAX &postfix_expr_array_string_2 ; Using "SAL_eax_Immediate8 !" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax ¤t_target ; Using current_target - LOAD32_EAX_from_EAX_Immediate8 !12 ; current_target->INDIRECT - LOAD32_EAX_from_EAX_Immediate8 !4 ; current_target->INDIRECT->SIZE - CALL32 %ceil_log2 ; ceil_log2(current_target->indirect->size) - CALL32 %numerate_number ; numerate_number(ceil_log2(current_target->indirect->size)) - CALL32 %emit_out ; Emit it - - LOADI32_EAX &postfix_expr_array_string_3 ; Using "\n" - CALL32 %emit_out ; Emit it - -:postfix_expr_array_common - LOADI32_EAX &postfix_expr_array_string_4 ; Using "ADD_ebx_to_eax\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &postfix_expr_array_string_5 ; Using "ERROR in postfix_expr\nMissing ]\n" - LOADI32_EBX &close_bracket ; Using "]" - CALL32 %require_match ; Make sure we have it - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; Using "=" - CALL32 %match ; IF global_token->S == "=" - CMPI8_EAX !0 ; We need to preserve address - JNE32 %postfix_expr_array_done ; Otherwise be done - - ;; Clearing out assign - LOADI32_ECX &postfix_expr_array_string_6 ; ASSIGN = "" - -:postfix_expr_array_done - COPY_ECX_to_EAX ; Using ASSIGN - CALL32 %emit_out ; Emit it - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:postfix_expr_array_string_0 "LOAD_INTEGER -" -:postfix_expr_array_string_1 "LOAD_BYTE -" -:postfix_expr_array_string_2 "SAL_eax_Immediate8 !" -:postfix_expr_array_string_3 " -" -:postfix_expr_array_string_4 "ADD_ebx_to_eax -" -:postfix_expr_array_string_5 "ERROR in postfix_expr -Missing ] -" -:postfix_expr_array_string_6 "" - - -;; ceil_log2 function -;; Receives int a in EAX -;; Performs log2 on A and -;; Returns result in EAX -;; Uses EBX for INT A and ECX for INT RESULT -:ceil_log2 - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOADI32_ECX %0 ; RESULT = 0 - - COPY_EAX_to_EBX ; put A in right place - SUBI8_EAX !1 ; (A - 1) - AND_EAX_EBX ; A & (A - 1) - CMPI8_EAX !0 ; IF 0 == (A & (A - 1)) - JNE32 %ceil_log2_iter ; Starting from -1 - - LOADI32_ECX %-1 ; RESULT = -1 - -:ceil_log2_iter - CMPI8_EBX !0 ; IF A > 0 - JLE32 %ceil_log2_done ; Otherwise be done - - ADDI8_ECX !1 ; RESULT = RESULT + 1 - SHRI8_EBX !1 ; A = A >> 1 - JMP32 %ceil_log2_iter ; Keep looping - -:ceil_log2_done - COPY_ECX_to_EAX ; Return RESULT - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; postfix_expr_arrow function -;; Receives nothing -;; Returns nothing -;; Emits a bunch and updates current_target -;; Uses EBX for struct type* I -:postfix_expr_arrow - PUSH_EBX ; Protect EBX - LOADI32_EAX &postfix_expr_arrow_string_0 ; Using "# looking up offset\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOAD32_EBX_from_EAX_Immediate8 !8 ; Using global_token->S - LOAD32_Absolute32_eax ¤t_target ; Using current_target - CALL32 %lookup_member ; lookup_member(current_target, global_token->s) - COPY_EAX_to_EBX ; struct type* I = lookup_member(current_target, global_token->s) - - LOAD32_EAX_from_EAX_Immediate8 !20 ; I->TYPE - STORE32_Absolute32_eax ¤t_target ; current_target = I->TYPE - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOAD32_EAX_from_EBX_Immediate8 !8 ; I->OFFSET - CMPI8_EAX !0 ; IF 0 != I->OFFSET - JE32 %postfix_expr_arrow_first ; Then we don't need to do an offset - - ;; Deal with needing an offset - LOADI32_EAX &postfix_expr_arrow_string_1 ; Using "# -> offset calculation\nLOAD_IMMEDIATE_ebx %" - CALL32 %emit_out ; Emit it - - LOAD32_EAX_from_EBX_Immediate8 !8 ; I->OFFSET - CALL32 %numerate_number ; Convert to string - CALL32 %emit_out ; Emit it - - LOADI32_EAX &postfix_expr_arrow_string_2 ; Using "\nADD_ebx_to_eax\n" - CALL32 %emit_out ; Emit it - -:postfix_expr_arrow_first - LOAD32_EAX_from_EBX_Immediate8 !4 ; I->SIZE - CMPI8_EAX !4 ; IF I->SIZE >= 4 - JL32 %postfix_expr_arrow_done ; Otherwise be done - - ;; Last chance for load - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; Using "=" - CALL32 %match ; IF global_token->S == "=" - CMPI8_EAX !0 ; Then we have assignment and should not load - JE32 %postfix_expr_arrow_done ; Be done - - ;; Deal with load case - LOADI32_EAX &postfix_expr_arrow_string_3 ; Using "LOAD_INTEGER\n" - CALL32 %emit_out ; Emit it - -:postfix_expr_arrow_done - POP_EBX ; Restore EBX - RETURN - -:postfix_expr_arrow_string_0 "# looking up offset -" -:postfix_expr_arrow_string_1 "# -> offset calculation -LOAD_IMMEDIATE_ebx %" -:postfix_expr_arrow_string_2 " -ADD_ebx_to_eax -" -:postfix_expr_arrow_string_3 "LOAD_INTEGER -" - - -;; primary_expr function -;; Receives nothing -;; Returns nothing -:primary_expr - PUSH_EBX ; Protect EBX - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EAX &sizeof_string ; Using "sizeof" - CALL32 %match ; See if match - CMPI8_EAX !0 ; IF match - JNE32 %primary_expr_neg ; Otherwise try negatives - - ;; Deal with sizeof - CALL32 %unary_expr_sizeof ; Lets do this - JMP32 %primary_expr_done ; Be done - -:primary_expr_neg - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !45 ; IF global_token->S[0] == "-" - JNE32 %primary_expr_not ; Otherwise try logical NOT - - ;; Deal with negative numbers - LOADI32_EAX &primary_expr_string_0 ; Using "LOAD_IMMEDIATE_eax %0\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &postfix_expr ; Passing postfix_expr - CALL32 %common_recursion ; Get what it is notting - - LOADI32_EAX &primary_expr_string_1 ; Using "SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n" - CALL32 %emit_out ; Emit it - JMP32 %primary_expr_done ; Be done - -:primary_expr_not - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !33 ; IF global_token->S[0] == "!" - JNE32 %primary_expr_bin ; Otherwise try '~' - - ;; Deal with logical not - LOADI32_EAX &primary_expr_string_2 ; Using "LOAD_IMMEDIATE_eax %1\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &postfix_expr ; Passing postfix_expr - CALL32 %common_recursion ; Get what it is notting - - LOADI32_EAX &primary_expr_string_3 ; Using "XOR_ebx_eax_into_eax\n" - CALL32 %emit_out ; Emit it - JMP32 %primary_expr_done ; Be done - -:primary_expr_bin - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !126 ; IF global_token->S[0] == "~" - JNE32 %primary_expr_paren ; Otherwise try paren - - ;; Deal with binary NOT - LOADI32_EAX &postfix_expr ; Passing postfix_expr - CALL32 %common_recursion ; Get what it is notting - LOADI32_EAX &primary_expr_string_4 ; Using "NOT_eax\n" - CALL32 %emit_out ; Emit it - JMP32 %primary_expr_done ; Be done - -:primary_expr_paren - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !40 ; IF global_token->S[0] == "(" - JNE32 %primary_expr_ch ; Otherwise try char - - ;; deal with nesting - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - CALL32 %expression ; Lets recurse - LOADI32_EAX &primary_expr_string_5 ; Using "Error in Primary expression\nDidn't get )\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - JMP32 %primary_expr_done ; Be done - -:primary_expr_ch - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !39 ; Using "'" - JNE32 %primary_expr_str ; Otherwise try string - - ;; Deal with chars - CALL32 %primary_expr_char ; Handle that char - JMP32 %primary_expr_done ; Be done - -:primary_expr_str - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !34 ; Using '\"' - JNE32 %primary_expr_var ; Otherwise try a variable - - ;; Deal with strings - CALL32 %primary_expr_string ; Handle that string - JMP32 %primary_expr_done ; Be done - -:primary_expr_var - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - LOADI32_EBX &primary_expr_string_6 ; Using "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" - CALL32 %In_Set ; See if we have a match - CMPI8_EAX !1 ; IF match - JNE32 %primary_expr_num ; otherwise try number - - ;; Deal with variables - CALL32 %primary_expr_variable ; Deal with variable - JMP32 %primary_expr_done ; Be done - -:primary_expr_num - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - LOADI32_EBX &primary_expr_string_7 ; Using "0123456789" - CALL32 %In_Set ; See if we have a match - CMPI8_EAX !1 ; IF match - JNE32 %primary_expr_fail ; otherwise we failed hard - - ;; Deal with numbers - CALL32 %primary_expr_number ; Collect the number - JMP32 %primary_expr_done ; Be done - -:primary_expr_fail - ;; looks like we hit bad input - ;; abort before it gets bad - CALL32 %primary_expr_failure ; No match means failure -:primary_expr_done - POP_EBX ; Restore EBX - RETURN - -:primary_expr_string_0 "LOAD_IMMEDIATE_eax %0 -" -:primary_expr_string_1 "SUBTRACT_eax_from_ebx_into_ebx -MOVE_ebx_to_eax -" -:primary_expr_string_2 "LOAD_IMMEDIATE_eax %1 -" -:primary_expr_string_3 "XOR_ebx_eax_into_eax -" -:primary_expr_string_4 "NOT_eax -" -:primary_expr_string_5 "Error in Primary expression -Didn't get ) -" -:primary_expr_string_6 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_" -:primary_expr_string_7 "0123456789" - - -;; primary_expr_variable function -;; Receives nothing -;; Returns nothing -;; Walks global and updates output -;; Uses EAX for struct token_list* a and ECX for char* S -:primary_expr_variable - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_ECX_from_EAX_Immediate8 !8 ; S = global_token->S - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - COPY_ECX_to_EAX ; Using S - LOAD32_Absolute32_ebx &global_constant_list ; Using global_constant_list - CALL32 %sym_lookup ; sym_lookup(s, global_constant_list) - CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list) - JE32 %primary_expr_variable_local ; Try locals next - - ;; Deal with constant load - LOAD32_EBX_from_EAX_Immediate8 !16 ; a->ARGS - LOADI32_EAX &primary_expr_variable_string_2 ; Using "LOAD_IMMEDIATE_eax %" - CALL32 %emit_out ; Emit it - - LOAD32_EAX_from_EBX_Immediate8 !8 ; a->ARGS->S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &primary_expr_variable_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - JMP32 %primary_expr_variable_done ; Be done - -:primary_expr_variable_local - COPY_ECX_to_EAX ; Using S - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EBX_from_EBX_Immediate8 !4 ; function->locals - CALL32 %sym_lookup ; sym_lookup(s, function->locals) - CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list) - JE32 %primary_expr_variable_arguments ; try arguments next - - ;; Deal with local load - CALL32 %variable_load ; Collect it - JMP32 %primary_expr_variable_done ; Be done - -:primary_expr_variable_arguments - COPY_ECX_to_EAX ; Using S - LOAD32_Absolute32_ebx &function ; Using function - LOAD32_EBX_from_EBX_Immediate8 !16 ; function->args - CALL32 %sym_lookup ; sym_lookup(s, function->args) - CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_constant_list) - JE32 %primary_expr_variable_function ; try functions next - - ;; Deal with argument load - CALL32 %variable_load ; Collect it - JMP32 %primary_expr_variable_done ; Be done - -:primary_expr_variable_function - COPY_ECX_to_EAX ; Using S - LOAD32_Absolute32_ebx &global_function_list ; Using global_function_list - CALL32 %sym_lookup ; sym_lookup(s, global_function_list) - CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_function_list) - JE32 %primary_expr_variable_global ; try globals next - - ;; Deal with functions - CALL32 %function_load ; Deal with the function - JMP32 %primary_expr_variable_done ; Be done - -:primary_expr_variable_global - COPY_ECX_to_EAX ; Using S - LOAD32_Absolute32_ebx &global_symbol_list ; Using global_symbol_list - CALL32 %sym_lookup ; sym_lookup(s, global_symbol_list) - CMPI8_EAX !0 ; IF NULL == sym_lookup(s, global_symbol_list) - JE32 %primary_expr_variable_error ; Give up - - ;; Deal with globals - CALL32 %global_load ; Collect that global - JMP32 %primary_expr_variable_done ; Be done - -:primary_expr_variable_error - LOADI32_EAX %2 ; Using standard error - STORE32_Absolute32_eax &Output_file ; write to standard error -; CALL32 %line_error ; Write useful debug info - COPY_ECX_to_EAX ; put S in the right place - CALL32 %File_Print ; print it - - LOADI32_EAX &primary_expr_variable_string_0 ; Ending string - CALL32 %File_Print ; print it - JMP32 %Exit_Failure ; Abort Hard - -:primary_expr_variable_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:primary_expr_variable_string_0 " is not a defined symbol -" -:primary_expr_variable_string_1 " -" -:primary_expr_variable_string_2 "LOAD_IMMEDIATE_eax %" - - -;; function_call function -;; Receives char* S in EAX and int BOOL in EBX -;; Builds stack frames before and tears them down after function calls -;; Uses ECX for char* S, EDX for int BOOL, ESI for PASSED -:function_call - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_ESI ; Protect ESI - COPY_EAX_to_ECX ; Put S in place - COPY_EBX_to_EDX ; Put BOOL in place - LOADI32_ESI %0 ; PASSED = 0 - - LOADI32_EAX &function_call_string_0 ; Using "ERROR in process_expression_list\nNo ( was found\n" - LOADI32_EBX &open_paren ; Using "(" - CALL32 %require_match ; Make sure we have it - - LOADI32_EAX &function_call_string_1 ; Using "PUSH_edi\t# Prevent overwriting in recursion\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_2 ; Using "PUSH_ebp\t# Protect the old base pointer\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_3 ; Using "COPY_esp_to_edi\t# Copy new base pointer\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !41 ; IF global_token->S[0] == ")" - JE32 %function_call_gen_done ; Then no arguments to send - - ;; looks like we have arguments to collect - CALL32 %expression ; Collect the argument - - LOADI32_EAX &function_call_string_4 ; Using "PUSH_eax\t#_process_expression1\n" - CALL32 %emit_out ; Emit it - LOADI32_ESI %1 ; PASSED = 1 - -:function_call_gen_iter - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !44 ; IF global_token->S[0] == "," - JNE32 %function_call_gen_done ; Otherwise we are done - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - CALL32 %expression ; Collect the argument - - LOADI32_EAX &function_call_string_5 ; Using "PUSH_eax\t#_process_expression2\n" - CALL32 %emit_out ; Emit it - ADDI8_ESI !1 ; PASSED = PASSED + 1 - JMP32 %function_call_gen_iter ; Keep trying - -:function_call_gen_done - ;; All is collected - LOADI32_EAX &function_call_string_6 ; Using "ERROR in process_expression_list\nNo ) was found\n" - LOADI32_EBX &close_paren ; Using ")" - CALL32 %require_match ; Make sure we have it - - CMPI8_EDX !0 ; IF(BOOL == TRUE) - JNE32 %function_call_static ; Otherwise it is a static call - - ;; Deal with a passed function pointer - LOADI32_EAX &function_call_string_7 ; Using "LOAD_BASE_ADDRESS_eax %" - CALL32 %emit_out ; Emit it - - COPY_ECX_to_EAX ; Using S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_8 ; Using "\nLOAD_INTEGER\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_9 ; Using "COPY_edi_to_ebp\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_10 ; Using "CALL_eax\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_13 ; Using "POP_ebx\t# _process_expression_locals\n" - JMP32 %function_call_cleanup ; Clean up - -:function_call_static - ;; Deal with fixed function name - LOADI32_EAX &function_call_string_9 ; Using "COPY_edi_to_ebp\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_11 ; Using "CALL_IMMEDIATE %FUNCTION_" - CALL32 %emit_out ; Emit it - - COPY_ECX_to_EAX ; Using S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_12 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_13 ; Using "POP_ebx\t# _process_expression_locals\n" - -:function_call_cleanup - CMPI8_ESI !0 ; IF PASSED > 0 - JLE32 %function_call_done ; Otherwise be done - - ;; The desired string is already in EAX - CALL32 %emit_out ; Emit it - - SUBI8_ESI !1 ; PASSED = PASSED - 1 - JMP32 %function_call_cleanup ; Keep going - -:function_call_done - LOADI32_EAX &function_call_string_14 ; Using "POP_ebp\t# Restore old base pointer\n" - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_call_string_15 ; Using "POP_edi\t# Prevent overwrite\n" - CALL32 %emit_out ; Emit it - - POP_ESI ; Restore ESI - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:function_call_string_0 "ERROR in process_expression_list -No ( was found -" -:function_call_string_1 "PUSH_edi # Prevent overwriting in recursion -" -:function_call_string_2 "PUSH_ebp # Protect the old base pointer -" -:function_call_string_3 "COPY_esp_to_edi # Copy new base pointer -" -:function_call_string_4 "PUSH_eax #_process_expression1 -" -:function_call_string_5 "PUSH_eax #_process_expression2 -" -:function_call_string_6 "ERROR in process_expression_list -No ) was found -" -:function_call_string_7 "LOAD_BASE_ADDRESS_eax %" -:function_call_string_8 " -LOAD_INTEGER -" -:function_call_string_9 "COPY_edi_to_ebp -" -:function_call_string_10 "CALL_eax -" -:function_call_string_11 "CALL_IMMEDIATE %FUNCTION_" -:function_call_string_12 " -" -:function_call_string_13 "POP_ebx # _process_expression_locals -" -:function_call_string_14 "POP_ebp # Restore old base pointer -" -:function_call_string_15 "POP_edi # Prevent overwrite -" - - -;; variable_load function -;; Receives struct token_list* A in EAX -;; Returns nothing -;; Updates output and current_target -;; Uses ECX for A -:variable_load - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; Protect A - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_paren ; Using "(" - CALL32 %match ; IF global_token->S == "(" - CMPI8_EAX !0 ; Then it might be a function - JNE32 %variable_load_regular ; Otherwise it is regular - - LOAD32_EBX_from_ECX_Immediate8 !12 ; A->TYPE - LOAD32_EBX_from_EBX_Immediate8 !24 ; A->TYPE->NAME - LOADI32_EAX &type_function_name ; Using "FUNCTION" - CALL32 %match ; IF A->TYPE->NAME == "FUNCTION" - CMPI8_EAX !0 ; Then it must be a function - JNE32 %variable_load_regular ; otherwise just another regular - - ;; deal with function - LOAD32_EAX_from_ECX_Immediate8 !16 ; A->DEPTH - CALL32 %numerate_number ; Convert to string - LOADI32_EBX %0 ; pass 0 for true - CALL32 %function_call ; Create the function call - JMP32 %variable_load_done ; Be done - -:variable_load_regular - LOAD32_EAX_from_ECX_Immediate8 !12 ; A->TYPE - STORE32_Absolute32_eax ¤t_target ; current_target = A->TYPE - - LOADI32_EAX &variable_load_string_0 ; Using "LOAD_BASE_ADDRESS_eax %" - CALL32 %emit_out ; Emit it - - LOAD32_EAX_from_ECX_Immediate8 !16 ; A->DEPTH - CALL32 %numerate_number ; Convert to string - CALL32 %emit_out ; Emit it - - LOADI32_EAX &variable_load_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - - ;; Check for special case of assignment - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; Using "=" - CALL32 %match ; IF global_token->S == "=" - CMPI8_EAX !0 ; Then we skip loading - JE32 %variable_load_done ; And be done - - ;; Deal with common case - LOADI32_EAX &variable_load_string_2 ; Using "LOAD_INTEGER\n" - CALL32 %emit_out ; Emit it - -:variable_load_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:variable_load_string_0 "LOAD_BASE_ADDRESS_eax %" -:variable_load_string_1 " -" -:variable_load_string_2 "LOAD_INTEGER -" - - -;; function_load function -;; Receives struct token_list* a in EAX -;; Returns nothing -;; Uses ECX to hold A->S -:function_load - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_EAX_from_EAX_Immediate8 !8 ; A->S - COPY_EAX_to_ECX ; Protect A->S - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_paren ; Using "(" - CALL32 %match ; IF global_token->S == "(" - CMPI8_EAX !0 ; The we need to do a function call - JNE32 %function_load_regular ; Otherwise just load it's address - - ;; Deal with function call - COPY_ECX_to_EAX ; Using A->S - LOADI32_EBX %1 ; Using FALSE - CALL32 %function_call ; Deal with it - JMP32 %function_load_done ; Be done - -:function_load_regular - LOADI32_EAX &function_load_string_0 ; Using "LOAD_IMMEDIATE_eax &FUNCTION_" - CALL32 %emit_out ; Emit it - - COPY_ECX_to_EAX ; Using A->S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &function_load_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - -:function_load_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:function_load_string_0 "LOAD_IMMEDIATE_eax &FUNCTION_" -:function_load_string_1 " -" - - -;; global_load function -;; Receives struct token_list* A in EAX -;; Returns nothing -;; Uses EBX to hold A->S -:global_load - PUSH_EBX ; Protect EBX - COPY_EAX_to_EBX ; Set as A - LOAD32_EBX_from_EBX_Immediate8 !8 ; Set as A->S - - LOAD32_EAX_from_EAX_Immediate8 !12 ; A->TYPE - STORE32_Absolute32_eax ¤t_target ; current_target = A->TYPE - - LOADI32_EAX &global_load_string_0 ; Using "LOAD_IMMEDIATE_eax &GLOBAL_" - CALL32 %emit_out ; Emit it - - COPY_EBX_to_EAX ; Using A->S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &global_load_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &equal ; "=" - CALL32 %match ; IF global_token->S == "=" - CMPI8_EAX !0 ; We need to skip for assignment - JE32 %global_load_done ; and be done - - ;; Otherwise we are loading the contents - LOADI32_EAX &global_load_string_2 ; Using "LOAD_INTEGER\n" - CALL32 %emit_out ; Emit it - -:global_load_done - POP_EBX ; Restore EBX - RETURN - -:global_load_string_0 "LOAD_IMMEDIATE_eax &GLOBAL_" -:global_load_string_1 " -" -:global_load_string_2 "LOAD_INTEGER -" - - -;; sym_lookup function -;; Receives char* S in EAX and struct token_list* symbol_list in EBX -;; Uses I->S in EAX, S in EBX and I in ECX -;; Returns match or NULL -:sym_lookup - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EBX_to_ECX ; I = symbol_list - COPY_EAX_to_EBX ; Put S in the right place -:sym_lookup_iter - CMPI8_ECX !0 ; IF NULL == I - JE32 %sym_lookup_done ; We failed to find match - - LOAD32_EAX_from_ECX_Immediate8 !8 ; Using I->S - CALL32 %match ; IF I->S == S - CMPI8_EAX !0 ; then be done - JE32 %sym_lookup_done ; Failed - - LOAD32_ECX_from_ECX ; I = I->NEXT - JMP32 %sym_lookup_iter ; otherwise keep looping - -:sym_lookup_done - COPY_ECX_to_EAX ; Return I - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; primary_expr_number function -;; Receives nothing -;; Returns nothing -;; Simply uses current global token to update output and then steps to next global_token -:primary_expr_number - LOADI32_EAX &primary_expr_number_string_0 ; Using "LOAD_IMMEDIATE_eax %" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %emit_out ; Emit it - - LOADI32_EAX &primary_expr_number_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - RETURN - -:primary_expr_number_string_0 "LOAD_IMMEDIATE_eax %" -:primary_expr_number_string_1 " -" - - -;; primary_expr_string function -;; receives nothing -;; Returns nothing -;; creates entries for string and calls to generate string output -;; uses ECX for char* number_string -:primary_expr_string - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_ebx ¤t_count ; Using current_count - COPY_EBX_to_EAX ; And putting it in the right place - CALL32 %numerate_number ; Get the string - COPY_EAX_to_ECX ; protect number_string - - ADDI8_EBX !1 ; current_count + 1 - STORE32_Absolute32_ebx ¤t_count ; current_count = current_count + 1 - - LOADI32_EAX &primary_expr_string_string_0 ; Using "LOAD_IMMEDIATE_eax &STRING_" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - COPY_ECX_to_EBX ; Put number_string in the right place - CALL32 %uniqueID_out ; Make it unique - - ;; Generate the target - LOADI32_EAX &primary_expr_string_string_1 ; Using ":STRING_" - LOAD32_Absolute32_ebx &strings_list ; Using strings_list - CALL32 %emit ; Emit it - COPY_EAX_to_EBX ; put new strings_list in place - - LOAD32_Absolute32_eax &function ; Using function - LOAD32_EAX_from_EAX_Immediate8 !8 ; function->S - CALL32 %uniqueID ; Make it unique - COPY_EAX_to_EBX ; put new strings_list in place - - ;; Parse the string - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %parse_string ; convert to useful form - CALL32 %emit ; Emit it - STORE32_Absolute32_eax &strings_list ; Update Strings _list - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:primary_expr_string_string_0 "LOAD_IMMEDIATE_eax &STRING_" -:primary_expr_string_string_1 ":STRING_" - - -;; primary_expr_char function -;; Receives nothing -;; Returns nothing -;; Updates output_list using global_token -:primary_expr_char - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOADI32_EAX &primary_expr_char_string_0 ; Using "LOAD_IMMEDIATE_eax %" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - ADDI8_EAX !1 ; global_token->S + 1 - CALL32 %escape_lookup ; Get the char - CALL32 %numerate_number ; Convert to string - CALL32 %emit_out ; emit it - - LOADI32_EAX &primary_expr_char_string_1 ; Using "\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:primary_expr_char_string_0 "LOAD_IMMEDIATE_eax %" -:primary_expr_char_string_1 " -" - - -;; primary_expr_failure function -;; Receives nothing -;; Does not return but aborts hard -;; Complains about the bad input -:primary_expr_failure -; CALL32 %line_error ; Get line of issue - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - LOADI32_EAX &primary_expr_failure_string_0 ; Using "Received " - CALL32 %File_Print ; Print it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %File_Print ; Print it - - LOADI32_EAX &primary_expr_failure_string_1 ; Using " in primary_expr\n" - CALL32 %File_Print ; Print it - JMP32 %Exit_Failure ; Abort Hard - -:primary_expr_failure_string_0 "Received " -:primary_expr_failure_string_1 " in primary_expr -" - - -;; general_recursion function -;; Receives FUNCTION F in EAX, char* S in EBX, char* name in ECX and FUNCTION iterate in EDX -;; Returns nothing -;; Uses ECX for char* S, EDX for FUNCTION iterate and EBP for FUNCTION F -;; But generally recurses a shitload -:general_recursion - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_EBP ; Protect EBP - COPY_EAX_to_EBP ; Protect F - COPY_ECX_to_EAX ; Put name in the right place - COPY_EBX_to_ECX ; Protect S - - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - CALL32 %match ; IF match(name, global_token->s) - CMPI8_EAX !0 ; If true we do - JNE32 %general_recursion_done ; Otherwise skip it - - ;; Deal with the recursion - COPY_EBP_to_EAX ; Put F in the right place - CALL32 %common_recursion ; Recurse - - COPY_ECX_to_EAX ; Put S in the right place - CALL32 %emit_out ; Emit it - - COPY_EDX_to_EAX ; Put iterate in the right place - CALL_EAX ; Down the rabbit hole - -:general_recursion_done - POP_EBP ; Restore EBP - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; promote_type function -;; Receives struct type* a in EAX and struct type* b in EBX -;; Returns the most recent type in EAX -;; Uses EAX for struct type* I, ECX for struct type* A and EDX for struct type* B -:promote_type - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - CMPI8_EBX !0 ; IF NULL == A - JE32 %promote_type_done ; Just return A - - COPY_EAX_to_ECX ; Put A in place - COPY_EBX_to_EDX ; Put B in place - COPY_EBX_to_EAX ; IF NULL == A - CMPI8_ECX !0 ; Then we just return B - JE32 %promote_type_done ; Be done - - ;; Looks like we need to walk the list - LOAD32_ECX_from_ECX_Immediate8 !24 ; A->NAME - LOAD32_EDX_from_EDX_Immediate8 !24 ; B->NAME - LOAD32_Absolute32_eax &global_types ; I = global_types -:promote_type_iter - CMPI8_EAX !0 ; IF NULL == I - JE32 %promote_type_done ; Just be done - - LOAD32_EBX_from_EAX_Immediate8 !24 ; I->NAME - CMP_ECX_EBX ; IF(A->NAME == I->NAME) - JE32 %promote_type_done ; Be done - - CMP_EBX_EDX ; IF(B->NAME == I->NAME) - JE32 %promote_type_done ; Be done - - LOAD32_EBX_from_EAX_Immediate8 !12 ; I->INDIRECT - LOAD32_EBX_from_EBX_Immediate8 !24 ; I->INDIRECT->NAME - - CMP_ECX_EBX ; IF(A->NAME == I->INDIRECT->NAME) - JE32 %promote_type_done ; Be done - - CMP_EBX_EDX ; IF(B->NAME == I->INDIRECT->NAME) - JE32 %promote_type_done ; Be done - - LOAD32_EAX_from_EAX ; I = I->NEXT - JMP32 %promote_type_iter ; Keep going - -:promote_type_done - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; common_recursion function -;; Receives FUNCTION F in EAX -;; Returns Nothing -;; Walks global_token list and update output_list -;; Updates current_target -;; Uses EBX to hold FUNCTION F and struct type* last_type -:common_recursion - PUSH_EBX ; Protect EBX - COPY_EAX_to_EBX ; Put FUNCTION F safely out of the way - LOADI32_EAX &common_recursion_string_0 ; Using "PUSH_eax\t#_common_recursion\n" - CALL32 %emit_out ; Emit it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - COPY_EBX_to_EAX ; Prepare for function call - LOAD32_Absolute32_ebx ¤t_target ; Get last type - CALL_EAX ; F(); - LOAD32_Absolute32_eax ¤t_target ; Get current_target - CALL32 %promote_type ; get the right type - STORE32_Absolute32_eax ¤t_target ; Set new current_target - - LOADI32_EAX &common_recursion_string_1 ; Using "POP_ebx\t# _common_recursion\n" - CALL32 %emit_out ; Emit it - POP_EBX ; Restore EBX - RETURN - -:common_recursion_string_0 "PUSH_eax #_common_recursion -" -:common_recursion_string_1 "POP_ebx # _common_recursion -" - - -;; require_match function -;; Receives char* message in EAX and char* required in EBX -;; Returns nothing -;; Uses ECX to hold message and updates global_token -:require_match - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; put the message somewhere safe - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %match ; IF required == global_token->S - CMPI8_EAX !0 ; we are fine - JE32 %require_match_good ; otherwise pain - - ;; Deal will bad times -; CALL32 %line_error ; Tell user what went wrong - LOADI32_EAX %2 ; Using standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - COPY_ECX_to_EAX ; using our message - CALL32 %File_Print ; Print it - JMP32 %Exit_Failure ; Abort HARD - -:require_match_good - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->next - STORE32_Absolute32_eax &global_token ; global_token = global_token->next - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; uniqueID Function -;; Receives char*S in EAX, struct token_list* l in EBX snd char* num in ECX -;; Returns updated struct token_list* L in EAX -:uniqueID - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - CALL32 %emit ; emit(s, l) - COPY_EAX_to_EBX ; Put L in correct place - LOADI32_EAX &underline ; Usinf "_" - CALL32 %emit ; emit("_", l) - COPY_EAX_to_EBX ; Put L in correct place - COPY_ECX_to_EAX ; Put num in correct place - CALL32 %emit ; emit(num, l) - COPY_EAX_to_EBX ; Put L in correct place - LOADI32_EAX &uniqueID_string_0 ; Using "\n" - CALL32 %emit ; emit("\n", l) - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:uniqueID_string_0 " -" - - -;; uniqueID_out function -;; Receives char* S in EAX and char* num in EBX -;; Returns nothing -:uniqueID_out - PUSH_EAX ; Protect EAX - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EBX_to_ECX ; Put num in right spot - LOAD32_Absolute32_ebx &output_list ; Using output_list - CALL32 %uniqueID ; Get updated list - STORE32_Absolute32_eax &output_list ; output_list = uniqueID(s, output_list, num) - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - POP_EAX ; Restore EAX - RETURN - - -;; emit_out function -;; Receives char* S in EAX -;; Returns nothing -;; Updates output_list -;; MUST NOT ALTER REGISTERS -:emit_out - PUSH_EAX ; Protect EAX - PUSH_EBX ; Protect EBX - LOAD32_Absolute32_ebx &output_list ; Using output_list - CALL32 %emit ; emit it - STORE32_Absolute32_eax &output_list ; update it - POP_EBX ; Restore EBX - POP_EAX ; Restore EAX - RETURN - - -;; emit function -;; Receives char *s in EAX and struct token_list* head in EBX -;; Returns struct token_list* T in EAX -:emit - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; put S out of the way - LOADI32_EAX %20 ; sizeof(struct token_list) - CALL32 %malloc ; get T - STORE32_EBX_into_EAX ; t->next = head; - STORE32_ECX_into_EAX_Immediate8 !8 ; t->s = s; - POP_ECX ; Restore ECX - RETURN - - -;; escape_lookup function -;; Receives char* c in EAX -;; Returns integer value of char in EAX -;; Aborts hard if unknown escape is received -;; Uses ECX to hold char* C -:escape_lookup - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; Put char* C in safe place - LOAD8_al_from_ECX ; Load c[0] - MOVZX_al ; make it useful - CMPI8_EAX !92 ; If '\\' != c[0] - JNE32 %escape_lookup_done ; Be done - - COPY_ECX_to_EBX ; Prepare for walk - ADDI8_EBX !1 ; increment - LOAD8_bl_from_EBX ; load c[1] - MOVZX_bl ; make it useful - - CMPI8_EBX !120 ; Check if \x?? - JE32 %escape_lookup_hex ; Deal with hex - - ;; Deal with \? escapes - LOADI32_EAX %10 ; Guess "\n" - CMPI8_EBX !110 ; If n - JE32 %escape_lookup_done ; Be done - - LOADI32_EAX %9 ; Guess "\t" - CMPI8_EBX !116 ; If t - JE32 %escape_lookup_done ; Be done - - COPY_EBX_to_EAX ; "\\", "'" and '\"' all encode as themselves - CMPI8_EBX !92 ; If "\\" - JE32 %escape_lookup_done ; Be done - CMPI8_EBX !39 ; IF "'" - JE32 %escape_lookup_done ; Be done - CMPI8_EBX !34 ; IF '\"' - JE32 %escape_lookup_done ; Be done - - LOADI32_EAX %13 ; Guess "\r" - CMPI8_EBX !114 ; IF r - JE32 %escape_lookup_done ; Be done - - ;; Looks like we have no clue what we are doing - ;; Aborting hard - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - LOADI32_EAX &escape_lookup_string_0 ; Using "Unknown escape received: " - CALL32 %File_Print ; Print it - COPY_ECX_to_EAX ; Using C - CALL32 %File_Print ; Print it - LOADI32_EAX &escape_lookup_string_1 ; Using " Unable to process\n" - CALL32 %File_Print ; Print it - JMP32 %Exit_Failure ; Abort Hard - -:escape_lookup_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:escape_lookup_hex - ;; Give up on C and just assume they know what they are doing - ADDI8_ECX !2 ; increment - LOAD8_al_from_ECX ; c[2] - MOVZX_al ; make it useful - ADDI8_ECX !1 ; increment - CALL32 %char2hex ; Get the hex value - SALI8_EAX !4 ; c << 4 - LOAD8_bl_from_ECX ; c[3] - MOVZX_bl ; make it useful - SWAP_EAX_EBX ; protect c << 4 - CALL32 %char2hex ; Get the hex value - ADD_ebx_into_eax ; hex(c[2]) << 4 + hex(c[3]) - JMP32 %escape_lookup_done ; Be done - -:escape_lookup_string_0 "Unknown escape received: " -:escape_lookup_string_1 " Unable to process -" - - -;; char2hex function -;; Receives char in EAX -;; Returns hex or aborts hard -:char2hex - SUBI8_EAX !48 ; Try 0-9 - CMPI8_EAX !10 ; Otherwise fun times - JL32 %char2hex_done ; Be done - - ;; Deal with A-F - ANDI32_EAX %0xDF ; Unset High bit turning a-f into A-F - SUBI8_EAX !7 ; Shift down into position - CMPI8_EAX !10 ; Everything below A is bad - JL32 %char2hex_fail ; And should fail - CMPI8_EAX !16 ; Make sure we are below F - JL32 %char2hex_done ; If so be done - -:char2hex_fail - ;; Time to fail hard - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - LOADI32_EAX &char2hex_string_0 ; Using "Tried to print non-hex number\n" - CALL32 %File_Print ; Print it - JMP32 %Exit_Failure ; Abort Hard - -:char2hex_done - RETURN - -:char2hex_string_0 "Tried to print non-hex number -" - - -;; parse_string function -;; Receives char* string in EAX -;; Returns cleaned up string -;; Protects char* string in EBX -:parse_string - PUSH_EBX ; Protect EBX - COPY_EAX_to_EBX ; Protect char* string - CALL32 %weird ; Determine if we have a weird string - CMPI8_EAX !0 ; If weird - JE32 %parse_string_weird ; Deal with it - - ;; Dealing with regular string - COPY_EBX_to_EAX ; Passing Char* string - CALL32 %collect_regular_string ; Collect it - JMP32 %parse_string_done ; Be done - -:parse_string_weird - COPY_EBX_to_EAX ; Passing Char* string - CALL32 %collect_weird_string ; Collect it - -:parse_string_done - POP_EBX ; Restore EBX - RETURN - - -;; weird function -;; Receives char* string in EAX -;; Returns true(0) or false(1) in EAX -;; Uses ECX to hold char* string -:weird - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EAX_to_ECX ; Place string in safe place - ADDI8_ECX !1 ; increment past the '\"' -:weird_reset - LOAD8_al_from_ECX ; Load a char - MOVZX_al ; Make it useful - CMPI8_EAX !0 ; IF NULL == C - JE32 %weird_false ; Nothing weird found - - CMPI8_EAX !92 ; IF '\\' - JNE32 %weird_escaped ; Deal with escaping - - ;; Deal with escape - COPY_ECX_to_EAX ; We are passing the string - CALL32 %escape_lookup ; to look it up - - ADDI8_ECX !1 ; string = string + 1 - LOAD8_bl_from_ECX ; get string[1] - MOVZX_bl ; make it useful - CMPI8_EBX !120 ; IF 'x' == string[1] - JNE32 %weird_escaped ; otherwise skip the gap - - ADDI8_ECX !2 ; string = string + 2 - -:weird_escaped - PUSH_EAX ; Protect C in case we need it - LOADI32_EBX &weird_string_0 ; Use "\t\n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" - CALL32 %In_Set ; To find if weird - CMPI8_EAX !1 ; IF TRUE - POP_EAX ; Restore C - JNE32 %weird_true ; Then not weird - - ADDI8_ECX !1 ; string = string + 1 - - ;; Last chance for weird - LOADI32_EBX &weird_string_1 ; Use "\t\n\r " - CALL32 %In_Set ; Check for special case - CMPI8_EAX !1 ; IF TRUE - JNE32 %weird_reset ; Otherwise not in the special case - - ;; Deal with possible special case - LOAD8_al_from_ECX ; Load string[1] - MOVZX_al ; Make it useful - CMPI8_EAX !58 ; IF string[1] == ":" - JE32 %weird_true ; Then we hit the special case - JMP32 %weird_reset ; Keep trying - -:weird_done - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:weird_true - LOADI32_EAX %0 ; Return true - JMP32 %weird_done ; Be done - -:weird_false - LOADI32_EAX %1 ; Return false - JMP32 %weird_done ; Be done - -:weird_string_0 " - !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" -:weird_string_1 '09 0A 0D 20' ; "\t\n\r " - - -;; collect_regular_string function -;; Receives char* string in EAX -;; Malloc and creates new string to return in EAX -;; Uses ECX for return string and EDX for passed string -:collect_regular_string - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - COPY_EAX_to_EDX ; Protect our passed string - LOADI32_EAX %256 ; We need 256bytes of storage - CALL32 %malloc ; Get our new pointer - COPY_EAX_to_ECX ; put it in place - PUSH_EAX ; protect until done -:collect_regular_string_reset - LOAD8_al_from_EDX ; string[0] - MOVZX_al ; Make it useful - CMPI8_EAX !0 ; See if we hit the end - JE32 %collect_regular_string_done ; And be done - - CMPI8_EAX !92 ; IF string[0] == '\\' - JE32 %collect_regular_string_escaped ; Deal with that mess - - ;; deal with boring char - STORE8_al_into_Address_ECX ; hold_string[index] = string[0] - ADDI8_ECX !1 ; Increment it - ADDI8_EDX !1 ; Increment it - JMP32 %collect_regular_string_reset ; And keep going - -:collect_regular_string_escaped - COPY_EDX_to_EAX ; Using string - CALL32 %escape_lookup ; Get the char - STORE8_al_into_Address_ECX ; hold_string[index] = escape_lookup(string) - ADDI8_EDX !1 ; Increment it - ADDI8_ECX !1 ; Increment it - LOAD8_al_from_EDX ; string[0] - MOVZX_al ; Make it useful - ADDI8_EDX !1 ; Increment it - CMPI8_EAX !120 ; IF 'x' == string[1] - JNE32 %collect_regular_string_reset ; Otherwise keep going - - ADDI8_EDX !2 ; Increment it - JMP32 %collect_regular_string_reset ; Keep going - -:collect_regular_string_done - LOADI32_EAX %34 ; Using '\"' - STORE8_al_into_Address_ECX ; hold_string[index] = '\"' - ADDI8_ECX !1 ; Increment it - LOADI32_EAX %10 ; Using "\n" - STORE8_al_into_Address_ECX ; hold_string[index] = '\n' - POP_EAX ; Return our new string - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; collect_weird_string function -;; Receives char* string in EAX -;; Mallocs and returns char* hold in EAX -;; Uses ECX for char* hold and EDX for char* string -:collect_weird_string - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - COPY_EAX_to_EDX ; Protect our passed string - LOADI32_EAX %512 ; We need 512bytes of storage - CALL32 %malloc ; Get our new pointer - COPY_EAX_to_ECX ; put it in place - PUSH_EAX ; protect until done - - LOADI32_EAX %39 ; Using "'" - STORE8_al_into_Address_ECX ; hold_string[index] = "'" - ADDI8_ECX !1 ; Increment it - ADDI8_EDX !1 ; Increment it -:collect_weird_string_reset - LOAD8_al_from_EDX ; Read a byte - MOVZX_al ; Make it useful - CMPI8_EAX !0 ; IF NULL == string[0] - JE32 %collect_weird_string_done ; Be done - - LOADI32_EAX %32 ; Using ' ' - STORE8_al_into_Address_ECX ; hold_string[index] = ' ' - ADDI8_ECX !1 ; Increment it - - COPY_EDX_to_EAX ; Using string - CALL32 %escape_lookup ; Get the char - CALL32 %hex8 ; Update ECX - - LOAD8_al_from_EDX ; Read a byte - MOVZX_al ; Make it useful - ADDI8_EDX !1 ; Increment it - CMPI8_EAX !92 ; IF string[0] == '\\' - JNE32 %collect_weird_string_reset ; Otherwise keep going - - LOAD8_al_from_EDX ; Read a byte - MOVZX_al ; Make it useful - ADDI8_EDX !1 ; Increment it - CMPI8_EAX !120 ; IF 'x' == string[1] - JNE32 %collect_weird_string_reset ; Otherwise keep going - - ADDI8_EDX !2 ; Increment it - JMP32 %collect_weird_string_reset ; Keep going - -:collect_weird_string_done - LOADI32_EAX %32 ; Using ' ' - STORE8_al_into_Address_ECX ; hold_string[index] = ' ' - ADDI8_ECX !1 ; Increment it - LOADI32_EAX %48 ; Using '0' - STORE8_al_into_Address_ECX ; hold_string[index] = '0' - ADDI8_ECX !1 ; Increment it - STORE8_al_into_Address_ECX ; hold_string[index] = '0' - ADDI8_ECX !1 ; Increment it - LOADI32_EAX %39 ; Using "'" - STORE8_al_into_Address_ECX ; hold_string[index] = "'" - ADDI8_ECX !1 ; Increment it - LOADI32_EAX %10 ; Using "\n" - STORE8_al_into_Address_ECX ; hold_string[index] = '\n' - POP_EAX ; Return our new string - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; HEX to ascii routine -;; Receives INT in EAX and CHAR* in ECX -;; Stores ascii of INT in CHAR* -;; Returns only modifying EAX and ECX -:hex8 - PUSH_EAX ; Protect bottom nibble - SHRI8_EAX !4 ; do high nibble first - CALL32 %hex4 ; Store it - POP_EAX ; do low nibble -:hex4 - ANDI32_EAX %0xF ; isolate nibble - ADDI8_EAX !48 ; convert to ascii - CMPI8_EAX !57 ; valid digit? - JBE8 !hex1 ; yes - ADDI8_EAX !7 ; use alpha range -:hex1 - STORE8_al_into_Address_ECX ; store result - ADDI8_ECX !1 ; next position - RETURN - - -;; type_name function -;; Receives nothing -;; Returns type_size in EAX -;; Uses ECX for STRUCT TYPE* RET -:type_name - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX_Immediate8 !8 ; global_token->S - LOADI32_EAX &struct ; Using "struct" - CALL32 %match ; IF global_token->S == "struct" - COPY_EAX_to_ECX ; Protect structure - CMPI8_EAX !0 ; need to skip over "struct" - JNE32 %type_name_native ; otherwise keep going - - ;; Deal with possible STRUCTs - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX ; global_token->next - STORE32_Absolute32_ebx &global_token ; global_token = global_token->next - LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S - LOAD32_Absolute32_ebx &global_types ; get all known types - CALL32 %lookup_type ; Find type if possible - COPY_EAX_to_ECX ; Set ret - - CMPI8_EAX !0 ; IF NULL == ret - JNE32 %type_name_common ; We have to create struct - - ;; Create a struct - CALL32 %create_struct ; Create a new struct - LOADI32_ECX %0 ; We wish to return NULL - JMP32 %type_name_done ; be done - -:type_name_native - ;; Deal only with native types - COPY_EBX_to_EAX ; Put global_token->S in the right place - LOAD32_Absolute32_ebx &global_types ; get all known types - CALL32 %lookup_type ; Find the type if possible - COPY_EAX_to_ECX ; Set ret - - CMPI8_EAX !0 ; IF NULL == ret - JNE32 %type_name_common ; We need to abort hard - - ;; Aborting hard - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - LOADI32_EAX &type_name_string_0 ; Print header - CALL32 %File_Print ; Print it - - LOAD32_Absolute32_eax &global_token ; Using global token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %File_Print ; Print it - - LOADI32_EAX &type_name_string_1 ; Print footer - CALL32 %File_Print ; Print it - -; CALL32 %line_error ; Give details - JMP32 %Exit_Failure ; Abort - -:type_name_common - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX ; global_token->next - STORE32_Absolute32_ebx &global_token ; global_token = global_token->next - -:type_name_iter - LOAD32_EAX_from_EBX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; make it useful - CMPI8_EAX !42 ; IF global_token->S[0] == '*' - JNE32 %type_name_done ; recurse - - ;; Deal with char** - LOAD32_ECX_from_ECX_Immediate8 !12 ; ret = ret->indirect - LOAD32_Absolute32_ebx &global_token ; Using global_token - LOAD32_EBX_from_EBX ; global_token->next - STORE32_Absolute32_ebx &global_token ; global_token = global_token->next - JMP32 %type_name_iter ; keep looping - -:type_name_done - COPY_ECX_to_EAX ; put ret in the right place - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:type_name_string_0 "Unknown type " -:type_name_string_1 " -" - - -;; lookup_type function -;; Receives char* s in EAX and struct type* start in EBX -;; Returns struct type* in EAX -;; Uses EBX for S and ECX for I -:lookup_type - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - COPY_EBX_to_ECX ; I = Start - COPY_EAX_to_EBX ; Put S in place -:lookup_type_iter - CMPI8_ECX !0 ; Check if I == NULL - JE32 %lookup_type_done ; return NULL - - LOAD32_EAX_from_ECX_Immediate8 !24 ; I->NAME - CALL32 %match ; Check if matching - CMPI8_EAX !0 ; IF I->NAME == S - JE32 %lookup_type_done ; return it - - LOAD32_ECX_from_ECX ; Otherwise I = I->NEXT - JMP32 %lookup_type_iter ; And keep looping - -:lookup_type_done - COPY_ECX_to_EAX ; return either I or NULL - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; create_struct function -;; Receives nothing -;; Returns nothing -;; Uses global_token to malloc a struct's definition -;; Uses ECX for int OFFSET, EDX for struct type* head, EBP for struct type* I, -;; EDI for member_size (Which is passed) and ESI for LAST -;; EAX and EBX are used for scratch -:create_struct - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_EBP ; Protect EBP - PUSH_EDI ; Protect EDI - PUSH_ESI ; Protect ESI - LOADI32_ECX %0 ; OFFSET = 0 - LOADI32_EDI %0 ; member_size = 0 - - LOADI32_EAX %28 ; sizeof(struct type) - CALL32 %malloc ; malloc(sizeof(struct type)) - COPY_EAX_to_EDX ; Set HEAD - - LOADI32_EAX %28 ; sizeof(struct type) - CALL32 %malloc ; malloc(sizeof(struct type)) - COPY_EAX_to_EBP ; Set I - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - STORE32_EAX_into_EDX_Immediate8 !24 ; HEAD->NAME = global_token->S - STORE32_EAX_into_EBP_Immediate8 !24 ; I->NAME = global_token->S - - STORE32_EBP_into_EDX_Immediate8 !12 ; HEAD->INDIRECT = I - STORE32_EDX_into_EBP_Immediate8 !12 ; I->INDIRECT = HEAD - - LOAD32_Absolute32_eax &global_types ; Using global_types - STORE32_EAX_into_EDX ; HEAD->NEXT = global_types - STORE32_Absolute32_edx &global_types ; global_types = HEAD - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX %4 ; Using register size - STORE32_EAX_into_EBP_Immediate8 !4 ; I->SIZE = register size - - LOADI32_EAX &create_struct_string_0 ; Using "ERROR in create_struct\n Missing {\n" - LOADI32_EBX &open_curly_brace ; Using "{" - CALL32 %require_match ; Make sure we have it - - LOADI32_ESI %0 ; LAST = NULL - -:create_struct_iter - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; Make it useful - CMPI8_EAX !125 ; IF global_token->S[0] == "}" - JE32 %create_struct_done ; be done - - ;; Looks like we are adding members - ;; Lets see if it is a union - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EBX &union ; Using "union" - CALL32 %match ; IF match(global_token->s, "union") - CMPI8_EAX !0 ; Deal with union - JNE32 %create_struct_single ; Otherwise deal with singles - - ;; Deal with union - COPY_ESI_to_EAX ; Put last in right place - COPY_ECX_to_EBX ; put offset in right place - CALL32 %build_union ; ASSEMBLE - COPY_EAX_to_ESI ; last = build_union(last, offset) - ADD_edi_into_ecx ; offset = offset + member_size - - LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - JMP32 %create_struct_iter ; keep going - -:create_struct_single - ;; deal with singles - COPY_ESI_to_EAX ; Put last in right place - COPY_ECX_to_EBX ; put offset in right place - CALL32 %build_member ; ASSEMBLE - COPY_EAX_to_ESI ; last = build_union(last, offset) - ADD_edi_into_ecx ; offset = offset + member_size - - LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - JMP32 %create_struct_iter ; keep going - -:create_struct_done - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &create_struct_string_1 ; Using "ERROR in create_struct\n Missing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - - STORE32_ECX_into_EDX_Immediate8 !4 ; HEAD->SIZE = OFFSET - STORE32_ESI_into_EDX_Immedate8 !16 ; HEAD->MEMBERS = LAST - STORE32_ESI_into_EBP_Immedate8 !16 ; I->MEMBERS = LAST - - POP_ESI ; Restore ESI - POP_EDI ; Restore EDI - POP_EBP ; Restore EBP - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:create_struct_string_0 "ERROR in create_struct - Missing { -" -:create_struct_string_1 "ERROR in create_struct - Missing ; -" - - -;; lookup_member function -;; Receives struct type* parent in EAX and char* name in EBX -;; Returns struct type* I in EAX -;; Uses char* NAME in EBX, ECX for struct type* I and EDX to hold parent for errors -;; Aborts hard if not found -:lookup_member - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - COPY_EAX_to_EDX ; Protect Parent - LOAD32_ECX_from_EAX_Immediate8 !16 ; struct type* I = parent->MEMBERS -:lookup_member_iter - CMPI8_ECX !0 ; IF I == NULL - JE32 %lookup_member_fail ; Abort HARD - - LOAD32_EAX_from_ECX_Immediate8 !24 ; Using I->NAME - CALL32 %match ; IF I->NAME == NAME - CMPI8_EAX !0 ; Then we have found the member - COPY_ECX_to_EAX ; Prepare for return - LOAD32_ECX_from_ECX_Immediate8 !16 ; Prepare for loop I = I->MEMBERS - JNE32 %lookup_member_iter ; Looks like we are looping - - ;; I is already in EAX - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:lookup_member_fail - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - LOADI32_EAX &lookup_member_string_0 ; Using "ERROR in lookup_member " - CALL32 %File_Print ; print it - - LOAD32_EAX_from_EDX_Immediate8 !24 ; PARENT->NAME - CALL32 %File_Print ; print it - - LOADI32_EAX &arrow_string ; Using "->" - CALL32 %File_Print ; print it - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %File_Print ; print it - - LOADI32_EAX &lookup_member_string_1 ; Using " does not exist\n" - CALL32 %File_Print ; print it - -; CALL32 %line_error ; Write useful debug info - - LOADI32_EAX &lookup_member_string_2 ; Using "\n" - CALL32 %File_Print ; print it - JMP32 %Exit_Failure ; Abort Hard - -:lookup_member_string_0 "ERROR in lookup_member " -:lookup_member_string_1 " does not exist -" -:lookup_member_string_2 " -" - - -;; build_member function -;; Receives struct type* last in EAX, int offset in EBX and global member_size in EDI -;; Updates member_size in EDI and returns struct type* I in EAX -;; Uses ECX for struct type* member_type and EDX for struct type* I -:build_member - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - COPY_EAX_to_EDX ; Put last out of the way - LOADI32_EAX %28 ; Allocate type - CALL32 %malloc ; Get I - STORE32_EDX_into_EAX_Immediate8 !16 ; I->MEMBERS = LAST - STORE32_EBX_into_EAX_Immediate8 !8 ; I->OFFSET = OFFSET - COPY_EAX_to_EDX ; Put I in place - - CALL32 %type_name ; Get member_type - COPY_EAX_to_ECX ; Put in place - STORE32_ECX_into_EDX_Immediate8 !20 ; I->TYPE = MEMBER_TYPE - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S - STORE32_EBX_into_EDX_Immediate8 !24 ; I->NAME = global_token->S - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - ;; Check if we have an array - LOAD32_EBX_from_EAX_Immediate8 !8 ; global_token->S - LOADI32_EAX &open_bracket ; Using "[" - CALL32 %match ; IF global_token->S == "[" - CMPI8_EAX !0 ; Then we have to deal with arrays in our structs - JE32 %build_member_array ; So deal with that pain - - ;; Deal with non-array case - LOAD32_EAX_from_ECX_Immediate8 !4 ; member_type->SIZE - STORE32_EAX_into_EDX_Immediate8 !4 ; I->SIZE = member_type->SIZE - JMP32 %build_member_done ; Be done - -:build_member_array - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - CALL32 %numerate_string ; convert number - LOAD32_EBX_from_ECX_Immediate8 !20 ; member_type->TYPE - LOAD32_EBX_from_EBX_Immediate8 !4 ; member_type->TYPE->SIZE - IMUL_EAX_by_EBX ; member_type->type->size * numerate_string(global_token->s) - STORE32_EAX_into_EDX_Immediate8 !4 ; I->SIZE = member_type->type->size * numerate_string(global_token->s) - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &build_member_string_0 ; Using "Struct only supports [num] form\n" - LOADI32_EBX &close_bracket ; Using "]" - CALL32 %require_match ; Make sure we have it - -:build_member_done - LOAD32_EDI_from_EDX_Immediate8 !4 ; MEMBER_SIZE = I->SIZE - STORE32_ECX_into_EDX_Immediate8 !20 ; I->TYPE = MEMBER_TYPE - COPY_EDX_to_EAX ; Return I - - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:build_member_string_0 "Struct only supports [num] form -" - - -;; build_union function -;; Receives struct type* last in EAX, int offset in EBX and global member_size in EDI -;; Updates member_size in EDI and returns struct type* LAST in EAX -;; Uses ECX for struct type* last, EDX for int offset, ESI for int size and EDI for int member_size -:build_union - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_ESI ; Protect ESI - COPY_EAX_to_ECX ; Put LAST in right spot - COPY_EBX_to_EDX ; Put OFFSET in right spot - LOADI32_ESI %0 ; SIZE = 0 - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - LOADI32_EAX &build_union_string_0 ; Using "ERROR in build_union\nMissing {\n" - LOADI32_EBX &open_curly_brace ; Using "{" - CALL32 %require_match ; Make sure we have it - -:build_union_iter - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX_Immediate8 !8 ; global_token->S - LOAD8_al_from_EAX ; global_token->S[0] - MOVZX_al ; make it useful - CMPI8_EAX !125 ; IF global_token->S[0] == "}" - JE32 %build_union_done ; Be done - - ;; Collect union member - COPY_ECX_to_EAX ; Passing LAST - COPY_EDX_to_EBX ; Passing offset - CALL32 %build_member ; build_member(last, offset) - COPY_EAX_to_ECX ; last = build_member(last, offset) - - CMP_EDI_ESI ; IF member_size > size - JG32 %build_union_size ; Then update size - - ;; deal with member_size > size - COPY_EDI_to_ESI ; SIZE = MEMBER_SIZE - -:build_union_size - LOADI32_EAX &build_union_string_1 ; Using "ERROR in build_union\nMissing ;\n" - LOADI32_EBX &semicolon ; Using ";" - CALL32 %require_match ; Make sure we have it - JMP32 %build_union_iter ; Keep going - -:build_union_done - COPY_ESI_to_EDI ; MEMBER_SIZE = SIZE - - LOAD32_Absolute32_eax &global_token ; Using global_token - LOAD32_EAX_from_EAX ; global_token->NEXT - STORE32_Absolute32_eax &global_token ; global_token = global_token->NEXT - - COPY_ECX_to_EAX ; Return last - - POP_ESI ; Restore ESI - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:build_union_string_0 "ERROR in build_union -Missing { -" -:build_union_string_1 "ERROR in build_union -Missing ; -" - - -;; sym_declare function -;; Receives char *s in EAX, struct type* t in EBX, and struct token_list* list in ECX -;; Returns struct token_list* in EAX -;; Uses EAX for A -:sym_declare - PUSH_EDX ; Protect EDX - COPY_EAX_to_EDX ; Get char *S safely out of the way - LOADI32_EAX %20 ; Using sizeof(struct token_list) - CALL32 %malloc ; Get pointer to A - STORE32_ECX_into_EAX ; A->NEXT = LIST - STORE32_EDX_into_EAX_Immediate8 !8 ; A->S = S - STORE32_EBX_into_EAX_Immediate8 !12 ; A->TYPE = T - POP_EDX ; Restore EDX - RETURN - - -;; match function -;; Receives CHAR* in EAX and CHAR* in EBX -;; Returns 0 (TRUE) or 1 (FALSE) in EAX -:match - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - COPY_EAX_to_ECX ; S1 in place - COPY_EBX_to_EDX ; S2 in place -:match_Loop - LOAD8_al_from_ECX ; S1[0] - MOVZX_al ; Make it useful - LOAD8_bl_from_EDX ; S2[0] - MOVZX_bl ; Make it useful - CMP_EAX_EBX ; See if they match - JNE32 %match_False ; If not - - ADDI8_ECX !1 ; S1 = S1 + 1 - ADDI8_EDX !1 ; S2 = S2 + 1 - CMPI8_EAX !0 ; If reached end of string - JE32 %match_Done ; Perfect match - JMP32 %match_Loop ; Otherwise keep looping - -:match_False - LOADI32_EAX %1 ; Return false -:match_Done - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; numerate_number function -;; Receives an INT A in EAX -;; Returns char* result in EAX -;; Allocates 16 bytes of memory -;; Behaves badly when given a negative number too large -;; Uses EAX for temp, EBX for DIVISOR, EDX for mod/0, ESI for result[i] and EBP for A -:numerate_number - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_ESI ; Protect ESI - PUSH_EBP ; Protect EBP - COPY_EAX_to_EBP ; Protect A - - LOADI32_EAX %16 ; 16bytes - CALL32 %malloc ; Get our pointer - PUSH_EAX ; Protect our pointer - COPY_EAX_to_ESI ; put pointer in right place - LOADI32_EBX %0x3B9ACA00 ; Set divisor to largest positive number that fits in 32bits - - CMPI8_EBP !0 ; Deal with 0 case - JE32 %numerate_number_ZERO ; If it is - JG32 %numerate_number_positive ; If it is positive - - ;; Deal with negative case - LOADI32_EAX %45 ; Using "-" - STORE8_al_into_Address_ESI ; Write it - ADDI8_ESI !1 ; increment - IMULI8_EBP !-1 ; A = A * -1 - -:numerate_number_positive - LOADI32_EDX %0 ; Set top to 0 - COPY_EBP_to_EAX ; Using A as bottom - IDIV_EBX ; edx:eax % ebx -> edx + edx:eax / ebx -> eax [Even if we don't want it] - CMPI8_EAX !0 ; IF 0 == (a / divisor) - JNE32 %numerate_number_iter ; Clean up those leading Zeros - - LOADI32_EDX %0 ; Set top to 0 - COPY_EBX_to_EAX ; Using Divisor for bottom - LOADI32_EBX %10 ; Make this shit work because idiv 10 doesn't work - IDIV_EBX ; edx:eax % 10 -> edx + edx:eax / 10 -> eax [Even if we don't want it] - COPY_EAX_to_EBX ; Update divisor - JMP32 %numerate_number_positive ; Keep collecting - -:numerate_number_iter - CMPI8_EBX !0 ; IF DIVISOR < 0 - JLE32 %numerate_number_done ; Be done - - LOADI32_EDX %0 ; Set top to 0 - COPY_EBP_to_EAX ; Using A as bottom - IDIV_EBX ; edx:eax % ebx -> edx + edx:eax / ebx -> eax [Even if we don't want it] - ADDI8_EAX !48 ; ((a / divisor) + 48) - STORE8_al_into_Address_ESI ; Write it - COPY_EDX_to_EBP ; a = a % divisor - - LOADI32_EDX %0 ; Set top to 0 - COPY_EBX_to_EAX ; Using Divisor for bottom - LOADI32_EBX %10 ; Make this shit work because idiv 10 doesn't work - IDIV_EBX ; edx:eax % 10 -> edx + edx:eax / 10 -> eax [Even if we don't want it] - COPY_EAX_to_EBX ; Update divisor - - ADDI8_ESI !1 ; increment - JMP32 %numerate_number_iter ; Keep going - -:numerate_number_done - POP_EAX ; Restore our result - POP_EBP ; Restore EBP - POP_ESI ; Restore ESI - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - -:numerate_number_ZERO - LOADI32_EAX %48 ; Using '0' - STORE8_al_into_Address_ESI ; Write it - ADDI8_ESI !1 ; increment - JMP32 %numerate_number_done ; Be done - - -;; numerate_string function -;; Receives CHAR* in EAX -;; Returns value of CHAR* in EAX -;; Uses EAX for VALUE, EBX for S, ECX for CH and ESI for NEGATIVE? -:numerate_string - PUSH_EBX ; Protect EBX - PUSH_ECX ; Protect ECX - PUSH_EDX ; Protect EDX - PUSH_ESI ; Protect ESI - COPY_EAX_to_EBX ; put S in correct place - LOADI32_EAX %0 ; Initialize to Zero -:numerate_string_loop - LOAD8_cl_from_EBX_Immediate8 !1 ; S[1] - MOVZX_cl ; make it useful - CMPI8_ECX !120 ; IF 'x' == S[1] - JE32 %numerate_hex ; Deal with hex input - - ;; Assume decimal input - LOADI32_ESI %0 ; Assume no negation - LOAD8_cl_from_EBX ; S[0] - MOVZX_cl ; make it useful - CMPI8_ECX !45 ; IF '-' == S[0] - JNE32 %numerate_decimal ; Skip negation - - LOADI32_ESI %1 ; Set FLAG - ADDI8_EBX !1 ; S = S + 1 - -:numerate_decimal - LOAD8_cl_from_EBX ; S[0] - MOVZX_cl ; make it useful - CMPI8_ECX !0 ; IF NULL == S[0] - JE32 %numerate_decimal_done ; We are done - - IMULI8_EAX !10 ; VALUE = VALUE * 10 - SUBI8_ECX !48 ; CH = CH - '0' - CMPI8_ECX !9 ; Check for illegal - JG32 %numerate_string_fail ; If CH > '9' - CMPI8_ECX !0 ; Check for illegal - JL32 %numerate_string_fail ; IF CH < 0 - ADD_ecx_into_eax ; VALUE = VALUE + CH - ADDI8_EBX !1 ; S = S + 1 - JMP32 %numerate_decimal ; Keep looping - -:numerate_decimal_done - CMPI8_ESI !1 ; Check if need to negate - JNE32 %numerate_string_done ; Nope - - IMULI8_EAX !-1 ; VALUE = VALUE * -1 - JMP32 %numerate_string_done ; Done - -:numerate_hex - ADDI8_EBX !2 ; S = S + 2 -:numerate_hex_loop - LOAD8_cl_from_EBX ; S[0] - MOVZX_cl ; make it useful - CMPI8_ECX !0 ; IF NULL == S[0] - JE32 %numerate_string_done ; We are done - - SALI8_EAX !4 ; VALUE = VALUE << 4 - SUBI8_ECX !48 ; CH = CH - '0' - CMPI8_ECX !10 ; IF 10 >= CH - JL32 %numerate_hex_digit ; NO - SUBI8_ECX !7 ; Push A-F into range -:numerate_hex_digit - CMPI8_ECX !15 ; Check for illegal - JG32 %numerate_string_fail ; If CH > 'F' - CMPI8_ECX !0 ; Check for illegal - JL32 %numerate_string_fail ; IF CH < 0 - ADD_ecx_into_eax ; VALUE = VALUE + CH - ADDI8_EBX !1 ; S = S + 1 - JMP32 %numerate_hex_loop ; Keep looping - -:numerate_string_fail - LOADI32_EAX %0 ; return ZERO - -:numerate_string_done - POP_ESI ; Restore ESI - POP_EDX ; Restore EDX - POP_ECX ; Restore ECX - POP_EBX ; Restore EBX - RETURN - - -;; Exit_Failure function -;; Receives nothing -;; And aborts hard -;; Does NOT return -:Exit_Failure - LOADI32_EBX %1 ; All is wrong - LOADI32_EAX %1 ; put the exit syscall number in eax - INT_80 ; Call it a bad day - -;; Keywords -:union "union" -:struct "struct" -:constant "CONSTANT" -:main_string "main" -:argc_string "argc" -:argv_string "argv" -:if_string "if" -:else_string "else" -:do_string "do" -:while_string "while" -:for_string "for" -:asm_string "asm" -:goto_string "goto" -:return_string "return" -:break_string "break" -:continue_string "continue" -:sizeof_string "sizeof" -:plus_string "+" -:minus_string "-" -:multiply_string "*" -:divide_string "/" -:modulus_string "%" -:left_shift_string "<<" -:right_shift_string ">>" -:less_than_string "<" -:less_than_equal_string "<=" -:greater_than_equal_string ">=" -:greater_than_string ">" -:equal_to_string "==" -:not_equal_string "!=" -:bitwise_and "&" -:logical_and "&&" -:bitwise_or "|" -:logical_or "||" -:bitwise_xor "^" -:arrow_string "->" - - -;; Frequently Used strings -;; Generally used by require_match -:open_curly_brace "{" -:close_curly_brace "}" -:open_paren "(" -:close_paren ")" -:open_bracket "[" -:close_bracket "]" -:comma "," -:semicolon ";" -:equal "=" -:percent "%" -:newline "\n" -:underline "_" - - -:prim_types -:type_void - &type_int ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_void ; INDIRECT - %0 ; MEMBERS - &type_void ; TYPE - &type_void_name ; NAME -:type_void_name "void" - -:type_int - &type_char ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_int ; INDIRECT - %0 ; MEMBERS - &type_int ; TYPE - &type_int_name ; NAME -:type_int_name "int" - -:type_char - &type_file ; NEXT - %1 ; SIZE - %0 ; OFFSET - &type_char_indirect ; INDIRECT - %0 ; MEMBERS - &type_char ; TYPE - &type_char_name ; NAME -:type_char_name "char" - -:type_char_indirect - &type_file ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_char_double_indirect ; INDIRECT - %0 ; MEMBERS - &type_char_indirect ; TYPE - &type_char_indirect_name ; NAME -:type_char_indirect_name "char*" - -:type_char_double_indirect - &type_file ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_char_double_indirect ; INDIRECT - %0 ; MEMBERS - &type_char_indirect ; TYPE - &type_char_double_indirect_name ; NAME -:type_char_double_indirect_name "char**" - -:type_file - &type_function ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_file ; INDIRECT - %0 ; MEMBERS - &type_file ; TYPE - &type_file_name ; NAME -:type_file_name "FILE" - -:type_function - &type_unsigned ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_function ; INDIRECT - %0 ; MEMBERS - &type_function ; TYPE - &type_function_name ; NAME -:type_function_name "FUNCTION" - -:type_unsigned - %0 ; NEXT - %4 ; SIZE - %0 ; OFFSET - &type_unsigned ; INDIRECT - %0 ; MEMBERS - &type_unsigned ; TYPE - &type_unsigned_name ; NAME -:type_unsigned_name "unsigned" - - -;; debug_list function -;; Receives struct token_list* in EAX -;; Prints contents of list and exits -;; Does NOT return -:debug_list - COPY_EAX_to_EBP ; Protect the list pointer - LOADI32_EAX %2 ; Using Standard error - STORE32_Absolute32_eax &Output_file ; write to standard error - -:debug_list_iter - ;; Header - LOADI32_EAX &debug_list_string0 ; Using our first string - CALL32 %File_Print ; Print it - COPY_EBP_to_EAX ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - ;; NEXT - LOADI32_EAX &debug_list_string1 ; Using our second string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !0 ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - ;; PREV - LOADI32_EAX &debug_list_string2 ; Using our third string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !4 ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - ;; S - LOADI32_EAX &debug_list_string3 ; Using our fourth string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !8 ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - ;; S Contents - LOADI32_EAX &debug_list_string4 ; Using our fifth string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !8 ; Use address of string - CMPI8_EAX !0 ; IF NULL Pointer - JNE32 %debug_list_null ; otherwise display - LOADI32_EAX &debug_list_string_null ; Give meaningful message instead -:debug_list_null - CALL32 %File_Print ; Print it - - ;; TYPE - LOADI32_EAX &debug_list_string5 ; Using our sixth string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !12 ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - ;; ARGS/DEPTH - LOADI32_EAX &debug_list_string6 ; Using our third string - CALL32 %File_Print ; Print it - LOAD32_EAX_from_EBP_Immediate8 !16 ; Use address of pointer - CALL32 %numerate_number ; Convert it into string - CALL32 %File_Print ; Print it - - LOADI32_EAX %10 ; Add "\n" - CALL32 %fputc ; print it - CALL32 %fputc ; print it - - LOAD32_EBP_from_EBP ; TOKEN = TOKEN->NEXT - CMPI8_EBP !0 ; Check if NULL - JNE32 %debug_list_iter ; iterate otherwise - - LOADI32_EBX %666 ; All is HELL - LOADI32_EAX %1 ; put the exit syscall number in eax - INT_80 ; Call it a bad day - -:debug_list_string0 "Token_list node at address: " -:debug_list_string1 " -NEXT address: " -:debug_list_string2 " -PREV address: " -:debug_list_string3 " -S address: " -:debug_list_string4 " -The contents of S are: " -:debug_list_string5 " -TYPE address: " -:debug_list_string6 " -ARGUMENTS address: " -:debug_list_string_null ">::::<" - - -:Address_of - NULL -:C - NULL -:Input_file - NULL -:MALLOC - NULL -:Output_file - NULL -:Token - NULL -:break_frame - NULL -:break_target_func - NULL -:break_target_head - NULL -:break_target_num - NULL -:current_count - NULL -:current_target - NULL -:function - NULL -:global_constant_list - NULL -:global_function_list - NULL -:global_symbol_list - NULL -:global_token - NULL -:global_types - &prim_types -:globals_list - NULL -:output_list - NULL -:string_index - NULL -:strings_list - NULL - -:ELF_end diff --git a/cc.h b/cc.h index 685f967..c7a1696 100644 --- a/cc.h +++ b/cc.h @@ -49,6 +49,7 @@ struct type struct type* next; int size; int offset; + int SIGNED; struct type* indirect; struct type* members; struct type* type; diff --git a/cc_types.c b/cc_types.c index 8860db0..d938e4f 100644 --- a/cc_types.c +++ b/cc_types.c @@ -29,84 +29,100 @@ void initialize_types() /* Define void */ global_types = calloc(1, sizeof(struct type)); global_types->name = "void"; + global_types->SIGNED = FALSE; global_types->size = register_size; global_types->type = global_types; /* void* has the same properties as void */ global_types->indirect = global_types; - /* Define int */ + /* Define UNSIGNED LONG */ struct type* a = calloc(1, sizeof(struct type)); - a->name = "int"; + a->name = "SCM"; + a->SIGNED = FALSE; a->size = register_size; - /* int* has the same properties as int */ a->indirect = a; a->type = a; - /* Define char* */ + /* Define LONG */ struct type* b = calloc(1, sizeof(struct type)); - b->name = "char*"; + b->name = "long"; + b->SIGNED = TRUE; b->size = register_size; + b->indirect = b; b->type = b; - /* Define char */ + /* Define UNSIGNED */ struct type* c = calloc(1, sizeof(struct type)); - c->name = "char"; - c->size = 1; + c->name = "unsigned"; + c->SIGNED = FALSE; + c->size = register_size; c->type = c; + /* unsigned* has the same properties as unsigned */ + c->indirect = c; - /* Define char** */ + /* Define int */ struct type* d = calloc(1, sizeof(struct type)); - d->name = "char**"; + d->name = "int"; + d->SIGNED = TRUE; d->size = register_size; - d->type = b; + /* int* has the same properties as int */ d->indirect = d; + d->type = d; - /*fix up indrects for chars */ - c->indirect = b; - b->indirect = d; - - /* Define FILE */ + /* Define char* */ struct type* e = calloc(1, sizeof(struct type)); - e->name = "FILE"; + e->name = "char*"; + e->SIGNED = FALSE; e->size = register_size; e->type = e; - /* FILE* has the same properties as FILE */ - e->indirect = e; - /* Define FUNCTION */ + /* Define char */ struct type* f = calloc(1, sizeof(struct type)); - f->name = "FUNCTION"; - f->size = register_size; + f->name = "char"; + f->SIGNED = FALSE; + f->size = 1; f->type = f; - /* FUNCTION* has the same properties as FUNCTION */ - f->indirect = f; - /* Define UNSIGNED */ + /* Define char** */ struct type* g = calloc(1, sizeof(struct type)); - g->name = "unsigned"; + g->name = "char**"; + g->SIGNED = FALSE; g->size = register_size; - g->type = g; - /* unsigned* has the same properties as unsigned */ + g->type = e; g->indirect = g; - /* Custom type for mescc*/ + /*fix up indrects for chars */ + f->indirect = e; + e->indirect = g; + + /* Define FILE */ struct type* h = calloc(1, sizeof(struct type)); - h->name = "SCM"; + h->name = "FILE"; + h->SIGNED = FALSE; h->size = register_size; + h->type = h; + /* FILE* has the same properties as FILE */ h->indirect = h; + /* Define FUNCTION */ struct type* i = calloc(1, sizeof(struct type)); - i->name = "long"; + i->name = "FUNCTION"; + i->SIGNED = FALSE; i->size = register_size; + i->type = i; + /* FUNCTION* has the same properties as FUNCTION */ i->indirect = i; + /* Primitives mes.c wanted */ struct type* j = calloc(1, sizeof(struct type)); j->name = "size_t"; + j->SIGNED = FALSE; j->size = register_size; j->indirect = j; struct type* k = calloc(1, sizeof(struct type)); k->name = "ssize_t"; + k->SIGNED = FALSE; k->size = register_size; k->indirect = k; @@ -116,10 +132,10 @@ void initialize_types() h->next = i; g->next = h; f->next = g; - e->next = f; - d->next = e; - c->next = e; - a->next = c; + d->next = f; + c->next = d; + b->next = c; + a->next = b; global_types->next = a; prim_types = global_types; } diff --git a/test/test.answers b/test/test.answers index d55ac24..4f5794f 100644 --- a/test/test.answers +++ b/test/test.answers @@ -53,10 +53,10 @@ a9cf4422e05075395ad75bbfe4b2659aec4541edd46d8c6b5064d3496b06a0b6 test/results/t 1154f39f25dcd6d914e9a542306f95280926baf985d011b2152c7ea0b87ab42d test/results/test10-knight-native-binary c1b5a2a3cd46c5e95e5540e871c2a916e028684ca80f51c001ef489342e27625 test/results/test10-knight-posix-binary b3e13d54aab689137628fb9c4487bfd8288f9bd18bef8fe756577c8d2dce1f1f test/results/test10-x86-binary -67fe5708ecb58ff63262d002c81e007177395613166649c23119c154cd347254 test/results/test100-amd64-binary -057cbf1a026f80c6f377af1eeeba6e38007697e8c12546ec853a4ca68f7869ce test/results/test100-armv7l-binary -0c563f8028cc93be2091992ef1210cd1a25e006680ec3b1bac5ecc61370c9258 test/results/test100-knight-posix-binary -84db585b6a8f51151c658ecbbcbd97a411d88d7379d5e416841ca616cf723374 test/results/test100-x86-binary +4d41cd9cc1ac08bda0372a1e7be17965b7a6f3bc77f87ca024bc4cc7948aedf5 test/results/test100-amd64-binary +a157f35aa2acf791464b242fe36f69816e1b91dd5559bca6a5bab1ad8ddcfbac test/results/test100-armv7l-binary +1ce45071c156ce9f012b9cc8b179205c3948405b252c29db1f036c097f22947f test/results/test100-knight-posix-binary +5e9e50ee0ca2c0cd290c4c764dfd1329baa563e078247b93754500543cb24c2e test/results/test100-x86-binary 34e6d535e30ef8826a4ad1a4d08b76cfa370c54595599ad3be784b64c9cd8ec5 test/results/test11-amd64-binary d9d465340abbce2d5964a6bc58e6cdd0ef93fb3d0199eaa823c86ec6abd0452a test/results/test11-armv7l-binary 955b564d2c89abf2cfc6c80d766cd11479d146b828dec69e654b0958a62d5e6e test/results/test11-knight-native-binary diff --git a/test/test100/proof.answer b/test/test100/proof.answer index bc33ff4..93bc1b0 100644 --- a/test/test100/proof.answer +++ b/test/test100/proof.answer @@ -1 +1 @@ -d37c7ede25b79a5ba457fd80aec9f4a21df5a8c3d467e52c4f1d7146d83d2d64 test/test100/proof +857519b111433c1cc3fd2f9fa60e86222e4227e9fce1601d08ceec6dfd7160e9 test/test100/proof