; Goku Programming language for the 80386 (and later) CPU's ; version 1.32 Dec 2nd, 1998 ; Copyright (c) 1998 by Lutz Mueller, lutz@nuevatec.com ; ; ; REGISTER USAGE ; ESI,EDI,EBX must be preserved for Win32 ; EBX is Goku Data stack ; ; every Goku word called from other 'core' Goku words ; must preserve ESI,EDI,EAX,ECX,EDX,EBP ; 'core' words are words not defined by Goku compile ; but delivered in handcode assembly ; %define offset %define ptr %define even align 2 %define PUBLIC global BITS 32 ;----------------- external functions ----------------------------------------- extern printf ;void printf(char * string) extern getConsoleInput ;char * getConsoleInput(char * addr, int n) extern calloc ;void * calloc(int size, int numBytes) extern free ;int free(void *) extern strcmp ;char * strcmp(char * str, char * str) extern strcpy ;char * strcpy(char * dest, char * src) extern strcat ;char * strcat(char * dest, char * src) extern strlen ;char * strlen(char * str) extern strstr ;char * strstr(char * string, char * key) extern exit ;void exit(int) extern system ;DWORD system(char * cmd); ; extern open ;int open(char * pathFileName, int mode) extern read ;int read(handle,ptr, size) extern write ;int write(handle, ptr, size) extern lseek ;int lseek(handle, amount, method) extern close ;int close(handle) extern getenv ;char * getenv(char * ) extern time ;int time(0); extern sleep ;int sleep(int seconds) extern date ;char * date(int time) extern loadLibrary ;DWORD loadLibrary(char * libName) extern loadFunction ;DWORD loadFunction(DWORD lib, char * func) ;---------------------------- Macros ------------------------------------------ %macro pushm 1 sub ebx,4 mov [ebx],%1 %endmacro %macro pushe 1 mov eax,%1 sub ebx,4 mov [ebx],eax %endmacro %macro popm 1 mov %1,[ebx] add ebx,4 %endmacro ;---------------- Dictionary ORB Record Types ------------------------------- TYP_MEM equ 0 TYP_MEMIND equ 1 TYP_CODE equ 2 TYP_INLINE equ 3 TYP_DICTIONARY equ 4 TYP_COMPILE equ 127 TYP_CORE_START equ -2 ;---------------- FLOW TYPE -------------------------------------------------- FLOW_IF equ 1 FLOW_THEN equ 2 FLOW_ELSE equ 3 FLOW_WHILE equ 4 FLOW_DO equ 5 FLOW_BREAK equ 6 FLOW_CONTINUE equ 7 FLOW_RECURSE equ 8 FLOW_EXIT equ 9 FLOW_END equ 10 FLOW_GET equ 11 FLOW_PUT equ 12 FLOW_LOCAL equ 13 FLOW_SEMICOLON equ 15 ;---------------- Tokenizer Token Types ------------------------------------- TKN_NULL equ 0 TKN_IDENT equ 1 TKN_STRING equ 2 TKN_FLOAT equ 3 TKN_INT equ 4 TKN_HEX equ 5 TKN_CHAR equ 6 ;---------------- ASCII ISO Characters -------------------------------------- CTL_C equ 3 TAB equ 9 LF equ 10 FF equ 12 CR equ 13 ESCAPE equ 27 SPACE equ 32 EXCLAMATION equ 33 QUOTATION equ 34 PERCENTS equ 37 AMPERSAND equ 38 SQUOTE equ 39 LEFT_PAR equ 40 RIGHT_PAR equ 41 ASTERISK equ 42 PLUS equ 43 COMMA equ 44 HYPHEN equ 45 PERIOD equ 46 SLASH equ 47 COLON equ 58 SEMICOLON equ 59 LESS_THAN equ 60 EQUAL equ 61 GREATER_THAN equ 62 ATSIGN equ 64 CARET equ 94 LEFT_BRACKET equ 91 BACKSLASH equ 92 RIGHT_BRACKET equ 93 UNDERSCORE equ 95 ; section .data ;------------------- constant data ------------------------------------------ copyright db 'Goku - Copyright 1998 Lutz Mueller',0 ;---------------- Error Messages -------------------------------------------- E_NULL db 0,0 E_SPACE db ' ',0 E_LINE_FULL db 'Line full ->',0 E_NOWORD db 'Word not found ->',0 E_MISSQU db 'Missing closing quote ->',0 E_LONGSTR db 'String or token too long ->',0 E_STUNDER db 'Data stack underflow',0 E_STOVER db 'Data stack overflow',0 E_NODEND db 'No end in definition',0 E_NOAEND db 'No end in alloc',0 E_NONAME db 'Name expected ->',0 E_NOINT db 'Int expected ->',0 E_DDOUBLE db 'Name already defined ->',0 E_UNKNOWN db 'Syntax error in compile ->',0 E_FLOWSTK db 'Unbalanced program flow ->',0 E_COMPILE db 'Use only in define/compile ->',0 E_SCRFULL db 'Scratch buffer full ->',0 E_NUMEXP db 'Number expected ->',0 E_EVALOVR db 'Eval: too much nesting levels->',0 E_NOMEMORY db 'Out of memory',0 E_LOOPTOOBIG db 'Loop too big',0 E_DOUBLENAME db 'Name already exists ->',0 E_TOOBIG db 'Orb too big for dictionary',0 E_DICFULL db 'Dictionary full',0 E_ONELOCAL db 'Only one local statement allowed',0 E_LOCALOVR db 'Too much locals used ->',0 ;----------------- MISC GLOBALS --------------------------------------------- align 4 DUMMY dd 0 ;dummy ACHAR dd 0 ;in 'atoi' and 'itoa' TOKEN_ADDR dd 0 ;in 'token' TOKEN_TYPE dd 0 ;in 'token' TOKEN_SPACE dd 0 ;token buffer for user STACK_PTR dd 0 ;in GokuEval GETPUT_FLAGS: GET_FLAG dw 0 ;in 'compile' und 'eval' PUT_FLAG dw 0 ;in 'compile' und 'eval' DICT_LAST_SAVE dd 0 ;in 'compile' LOCAL_TABLE dd 0 ;in 'compile' LOCAL_PTR dd 0 ;in 'compile' LOCAL_COUNT dd 0 ;in 'compile' ;------------------SYSTEM GLOBALS ACCESSIBLE BY USER ------------------------ align 4 global SYSTEM_RECORD SYSTEM_RECORD: GOKU_VERSION dd 1322 ;version 1.30 Linux Console DICT_SIZE dd 4096 ;size of a dictionary DATA_STK_SIZE dd 512 ;size of Goku data stack CODE_PAD_SIZE dd 2048 ;size for compiled code LOCAL_SIZE dd 256 ;no of times locals are used STR_CLEAN_SIZE dd 1024 ;size for constant strings ERRMSG_SIZE dd 256 ;error message size TOKEN_SIZE dd 1024 ;max token circular buffer CORE_DICT dd LEXICON ;address of core dictionary CURRNT_DICT dd 0 ;address of current dictionary ACTIVE_DICT dd 0 ;address of active dictionary DICT_LAST dd 0 ;ptr to last symbol in dictionary DICT_END dd 0 ;ptr to end of dictionary DATA_BTTM dd 0 ;bottom of stack DATA_STK dd 0 ;top of stack DATA_PTR dd 0 ;current stack pointer EVENT_MSG dd 0 ;event message no EVENT_DATA dd 0 ;event data EVENT_NO dd 0 ;N of events before getEvent ERRMSG_BUFF dd 0 ;address of errmsg buffer TOKEN_BUFFER dd 0 ;address of token buffer for 'eval','compile' MAIN_DICT dd 0 ;1st allocated dictionary MEM_ALLOCED dd 0 ;accumulated memory allocated MEM_FREED dd 0 ;memory freed DEBUG_FLAG dw 0 ;set by user if debug mode DEBUG_EMIT dw 0 ;set bei 'compile' if emit debug code DEBUG_PROC dd offset CODE_EXIT DEBUG_LINE dd 0 ;----------------- COMPILER STACKS AND GLOBALS ------------------------------ STR_CLEAN dd 0 ;start of clean string area in 'token' CP_PTR dd 0 ;pointer in to code pad CP_START dd 0 ;start of code pad FLOW_BTTM times 96 dd 0 FLOW_STK: FLOW_PTR dd FLOW_STK WHD_BTTM times 32 dd 0 WHD_STK: WHD_PTR dd WHD_STK PRE_SRC_PTR dd 0 ;in 'compile' WHILE_ADDR dd 0 ;in 'compile' LAST_CONSTANT dd 0 ;last constant LAST_TKN dw 0 ;last token type in 'compile' CURRNT_TKN dw 0 ;current token type in 'compile' ARG_COUNT dd 0 ;in callLib ;----------------- EVALUTOR GLOBLAS ----------------------------------------- align 4 SSTK_BTTM times 16 dd 0 SSTK_STK: SSTK_PTR dd SSTK_STK OLD_SRC_PTR dd 0 ;------------------------ COMPILER DATA ------------------------------------- even CODE_JSR: mov eax,0 call eax even CODE_ADDR: sub ebx, byte 4 mov dword ptr[ebx],0 even CODE_ADDR_FETCH: mov eax,[DUMMY] sub ebx, byte 4 mov [ebx],eax even CODE_ADDR_STORE: mov eax,[ebx] mov [DUMMY],eax add ebx, byte 4 even CODE_CONST: sub ebx, byte 4 mov dword ptr[ebx],0 even CODE_CONST_ADDS: add dword ptr[ebx],0ababababh even CODE_CONST_SUBS: sub dword ptr[ebx],0ababababh even CODE_THEN: add ebx, byte 4 cmp dword ptr[ebx-4], byte 0 db 0Fh,84h,0,0,0,0 ;je target even CODE_DO: add ebx, byte 4 cmp dword ptr[ebx-4], byte 0 db 0Fh,84h,0,0,0,0 ;je target even CODE_BRANCH: db 0E9h,0,0,0,0 ;jmp target even CODE_RECURSE: db 0E8h,0,0,0,0 ;call target even CODE_EXIT: ret even CODE_TRACE: mov dword ptr[DEBUG_LINE],0 mov eax,[DEBUG_PROC] call eax even ;----------------- Main Entry Point called from the Windows Shell ----------- ; section .code ;ASSUME cs:@data ;---------------------------------------------------------------------------- global GokuEval GokuEval: ;void GokuEval(char * ) push ebp mov ebp,esp pushad mov [STACK_PTR],esp ;save for error routine was esp mov ebx,[DATA_PTR] ;was ebx cld mov eax,dword ptr[ebp+8] sub ebx, byte 4 mov [ebx],eax call eval mov [DATA_PTR],ebx gogo: popad pop ebp ret global GokuInit ;happens once on startup GokuInit: ;int GokuInit() ; allocate data-stack mov eax,[DATA_BTTM] cmp eax, byte 0 je allocStackGo ; sub eax, byte 36 mov eax,[eax] add [MEM_FREED],eax mov eax,[DATA_BTTM] sub eax, byte 32 push eax ;push address of old stack call free ;free memory of old stack add esp, byte 4 ; allocStackGo: mov eax,[DATA_STK_SIZE] ;data stack plus headroom add eax, byte 64 ;head room on both sides add eax,[CODE_PAD_SIZE] ;for compiled code add eax,[LOCAL_SIZE] ;for local table in 'compile' add eax,[STR_CLEAN_SIZE] ;for strings in 'token' add eax,[ERRMSG_SIZE] ;for error msg buffer add eax,[TOKEN_SIZE] ;for buffer in 'token' add eax,[DICT_SIZE] ; add [MEM_ALLOCED],eax push dword ptr 1 push eax call calloc add esp, byte 8 cmp eax,0 jne allocGo ret ;return 0 for failure of gokuInit ; allocGo: add eax, byte 32 mov [DATA_BTTM],eax add eax,[DATA_STK_SIZE] mov [DATA_STK],eax ;end/top of stack mov [DATA_PTR],eax ;init data stack add eax, byte 32 ;headroom data stack mov [CP_START],eax ;start of code pad add eax,[CODE_PAD_SIZE] mov [LOCAL_TABLE],eax ;start of localstable in 'compile' add eax,[LOCAL_SIZE] mov [STR_CLEAN],eax ;start of string clean add eax,[STR_CLEAN_SIZE] mov [ERRMSG_BUFF],eax ;start of keyboard buffer add eax,[ERRMSG_SIZE] mov [TOKEN_BUFFER],eax ;start of token buffer add eax,[TOKEN_SIZE] mov [ACTIVE_DICT],eax mov [CURRNT_DICT],eax mov [MAIN_DICT],eax mov ecx,eax add ecx,byte 8 mov [DICT_LAST],ecx mov [eax],ecx mov ecx,eax add ecx,[DICT_SIZE] mov [DICT_END],ecx mov [eax+4],ecx GokuInitEnd: ret PUBLIC GokuReset ;on startup and after errors GokuReset: ;void GokuReset() mov eax,offset FLOW_STK ;init control flow stack mov [FLOW_PTR],eax mov eax,offset WHD_STK ;init break/continue in while/do syack mov [WHD_PTR],eax mov eax,offset SSTK_STK ;init eval source ptr stack mov [SSTK_PTR],eax ret ;----------------- Error and stack check subroutines ------------------------ exitProc: call GokuReset mov esp,[STACK_PTR] ;return from call to _GokuEval() popad pop ebp ret ;---------------------------------------------------------------------- errorProc: call GokuReset pushe E_SPACE call errorProcPrint call errorProcPrint call errorProcPrint mov esp,[STACK_PTR] ;return from call to _GokuEval() popad pop ebp ret stackCheck: mov eax,ebx cmp eax,[DATA_STK] jg stUError cmp eax,[DATA_BTTM] jl stOError ret stOError: call clear pushe E_NULL pushe E_STOVER jmp errorProc stUError: call clear pushe E_NULL pushe E_STUNDER jmp errorProc ;---------------------------------------------------------------------- errorProcPrint: sub ebx, byte 8 mov eax,[ERRMSG_BUFF] mov [ebx+4],eax mov dword ptr[ebx],80 call gmemcpy popm eax mov byte ptr[eax+80],0 push eax call printf add sp, byte 4 ret ;---------------------------------------------------------------------------- ; Core Dictionary Orbs ;---------------------------------------------------------------------------- align 4 ;---------------------------------------------------------------------------- LEXICON: db TYP_CORE_START,0FFh db 0,0 dd 0 ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 2,0 dd FLOW_PUT db '!',0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd percent db '%',0 ;(dividend divisorr -- qotient remainder) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd adds db '+',0 ;(number1 nunber2 -- sum) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd subs db '-',0 ;(number1 number2 -- difference) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd noop db '(',0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd rightpar db ')',0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd smultiply db '*',0 ;(multiplicand multiplicator -- result) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd sdivide db '/',0 ;(dividend divisor -- result) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd noop db ':',0 ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 2,2 dd FLOW_SEMICOLON db ';',0 ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd binand db '&',0 ;(number1 number2 -- result) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd binor db '|',0 ;(number1 number2 -- result) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd less db '<',0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,2 dd lessEqual db '<=',0,0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,4 dd notEqual db '<>',0,0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 4,4 dd shiftl db '<<',0,0 ;(number count -- result) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,4 dd equl db '=',0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 2,2 dd greater db '>',0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,2 dd gtrEqual db '>=',0,0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 4,4 dd shiftr db '>>',0,0 ;(number count -- result) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 2,4 dd FLOW_GET db '@',0 ;( -- value) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd noop db '[',0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 2,2 dd adds db ']',0 ;(number1 number2 -- sum) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,2 dd accept db 'accept',0,0 ;(address length -- address) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,8 dd andLog db 'and',0 ;(number1 number2 -- boolean) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd atoi db 'atoi',0,0 ;(address -- number) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd atof db 'atof',0,0 ;(address -- float) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 6,6 dd FLOW_BREAK db 'break',0 ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd callsub db 'call',0,0 ;( address -- ??) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd callLib db 'callLib',0 ;( p1 [p2 ... pn] pCnt addr -- eax) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,8 dd catch db 'catch',0 ; ( address -- ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd clear db 'clear',0 ; ( xxx -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gclose db 'close',0 ;(handle memPtr size -- sizeWritten) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd gstrcmp db 'compare',0 ; (address address -- result) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,8 dd compile db 'compile',0 ;(address -- codeAddr newSrcAddress) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,8 dd gstrcat db 'concat',0,0 ;(destAddr srcAddr -- destAddr) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 10,8 dd FLOW_CONTINUE db 'continue',0,0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,10 dd gstrcpy db 'copy',0,0 ;(fromAddress toAddress -- toAddress) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd create db 'create',0,0 ;(address type -- contentsAddress) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,8 dd gdate db 'date',0,0 ;( -- seconds ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 4,6 dd decrement db 'dec',0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd depth db 'depth',0 ;( -- number) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd disp db 'disp',0,0 ;( number -- ) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 4,6 dd FLOW_DO db 'do',0,0 ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,4 dd drop db 'drop',0,0 ;(p1 .. pn -- p1 .. pn-1) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 4,6 dd dups db 'dup',0 ;(value -- value value) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 6,4 dd FLOW_ELSE db 'else',0,0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd emit db 'emit',0,0 ;(AsciiNumber -- ) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 4,6 dd FLOW_END db 'end',0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd eval db 'eval',0,0 ;(address -- ???) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd exitEval db 'exit',0,0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gmemset db 'fill',0,0 ;(address byte length -- address) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gstrstr db 'find',0,0 ;(key string -- position) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gfree db 'free',0,0 ;(memPtr -- ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd getb db 'getb',0,0 ;(address -- char) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd getc db 'getc',0,0 ;(address -- unsignedChar) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd getEnv db 'getenv',0,0 ;(address -- address) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,8 dd getw db 'getw',0,0 ;(address -- word) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd getu db 'getu',0,0 ;(address -- unsignedWord) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd getl db 'getl',0,0 ;(address -- char) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd htoi db 'htoi',0,0 ;(stringAddress -- number) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 4,6 dd FLOW_IF db 'if',0,0 ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 4,4 dd increment db 'inc',0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd init db 'init',0,0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd itoa db 'itoa',0,0 ;(number address -- address) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd gstrlen db 'length',0,0 ;(strAddress -- length) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,8 dd loadLib db 'loadLib',0 ;(libName -- libHandle) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 10,8 dd loadFunc db 'loadFunc',0,0 ;(libHandle funcName -- callCaddress) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 6,10 dd FLOW_LOCAL db 'local',0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd lookup db 'lookup',0,0 ;(strAaddress -- symbolAddress) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,8 dd gmalloc db 'malloc',0,0 ;(size -- memPtr) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,8 dd max db 'max',0 ;(number1 number2 -- maximum) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd gmemcpy db 'mcopy',0 ;(destAddr sourceAddr -- destAddr) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,6 dd min db 'min',0 ;(number1 number2 -- minimum) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,4 dd notLog db 'not',0 ;(logValue -- notLogValue) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,4 dd gopen db 'open',0,0 ;(filePathName mode -- handle) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 4,6 dd orLog db 'or',0,0 ;(number number -- logValue) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,4 dd putb db 'putb',0,0 ;(char address -- ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd putw db 'putw',0,0 ;(number address -- ) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,6 dd putl db 'putl',0,0 ;(number address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd quit db 'quit',0,0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gread db 'read',0,0 ;(handle memPtr size -- sizeRead) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 8,6 dd FLOW_RECURSE db 'recurse',0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 8,8 dd FLOW_EXIT db 'return',0,0 ;( -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,8 dd gseek db 'seek',0,0 ;(handle amount method -- position) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gsleep db 'sleep',0 ;( seconds -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 10,6 dd sourcePtr db 'sourcePtr',0 ;( -- address) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,10 dd stack db 'stack',0 ;(p1 .. pn stack -- p1 .. pn stackp) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,6 dd gsystem db 'system',0,0 ;(command -- result ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 8,8 dd sysvar db 'sysvar',0,0 ;( -- address) ;---------------------------------------------------------------------------- db TYP_INLINE,0 db 6,8 dd swap db 'swap',0,0 ;(xx yy -- yy xx) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 6,6 dd FLOW_THEN db 'then',0,0 ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd token db 'token',0 ;(address -- newAddr tokenAddr type) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd throw db 'throw',0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd gtime db 'time',0,0 ;( -- seconds ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 6,6 dd ptype db 'type',0,0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_CODE,0 db 10,6 dd updatePtr db 'updatePtr',0 ;(address -- ) ;---------------------------------------------------------------------------- db TYP_COMPILE,0 db 6,10 dd FLOW_WHILE db 'while',0 ;---------------------------------------------------------------------------- lastCoreEntry: db TYP_CODE,0 db 6,6 dd gwrite db 'write',0 ;(handle memPtr size -- sizeWritten) ;---------------------------------------------------------------------------- dd 0FFFFFFFEh ;---------------------------------------------------------------------------- ; CODE FOR CORE WORDS ;---------------------------------------------------------------------------- dd percentFin-percent percent: xor edx,edx mov eax,[ebx+4] idiv dword ptr[ebx] mov [ebx+4],eax mov [ebx],edx ret align 4 percentFin: ;---------------------------------------------------------------------------- dd addsFin-adds adds: mov eax,[ebx+4] add eax,[ebx] add ebx, byte 4 mov [ebx],eax align 2 ret nop ;guarantee align 2 length with 'ret' in fixed position addsFin: ;so it can be taken off when doing inline-compile ;---------------------------------------------------------------------------- dd subsFin-subs subs: mov eax,[ebx+4] sub eax,[ebx] add ebx, byte 4 mov [ebx],eax align 2 ret nop subsFin: ;---------------------------------------------------------------------------- dd rightparFin-rightpar rightpar: mov eax,[ebx] shl eax,2 add eax,[ebx+4] add ebx, byte 4 mov [ebx],eax ret align 2 rightparFin: ;---------------------------------------------------------------------------- dd smultiplyFin-smultiply smultiply: mov eax,[ebx+4] imul eax,[ebx] add ebx, byte 4 mov [ebx],eax ret align 2 smultiplyFin: ;---------------------------------------------------------------------------- dd sdivideFin-sdivide sdivide: mov eax,[ebx+4] cdq idiv dword ptr[ebx] add ebx, byte 4 mov [ebx],eax ret align 2 sdivideFin: ;---------------------------------------------------------------------------- dd binandFin-binand binand: mov eax,[ebx] and eax,[ebx+4] add ebx, byte 4 mov [ebx],eax align 2 ret nop binandFin: ;---------------------------------------------------------------------------- dd binorFin-binor binor: mov eax,[ebx] or eax,[ebx+4] add ebx, byte 4 mov [ebx],eax align 2 ret nop binorFin: ;---------------------------------------------------------------------------- dd lessFin-less less: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] jl trueLess mov dword ptr[ebx],0 ret trueLess: mov dword ptr[ebx],1 ret align 2 lessFin: ;---------------------------------------------------------------------------- dd lessEqualFin-lessEqual lessEqual: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] jle trueLessE mov dword ptr[ebx],0 ret trueLessE: mov dword ptr[ebx],1 ret align 2 lessEqualFin: ;---------------------------------------------------------------------------- dd notEqualFin-notEqual notEqual: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] jne trueNotE mov dword ptr[ebx],0 ret trueNotE: mov dword ptr[ebx],1 ret align 2 notEqualFin: ;---------------------------------------------------------------------------- dd shiftlFin-shiftl shiftl: mov ecx,[ebx] add ebx, byte 4 shl dword ptr[ebx],cl align 2 ret nop shiftlFin: ;---------------------------------------------------------------------------- dd equlFin-equl equl: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] je trueEqual mov dword ptr[ebx],0 ret trueEqual: mov dword ptr[ebx],1 ret align 2 equlFin: ;---------------------------------------------------------------------------- dd greaterFin-greater greater: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] jg NEAR trueLess mov dword ptr[ebx],0 ret trueGreater: mov dword ptr[ebx],1 ret align 2 greaterFin: ;---------------------------------------------------------------------------- dd gtrEqualFin-gtrEqual gtrEqual: add ebx, byte 4 mov eax,[ebx] cmp eax,[ebx-4] jge trueGtrE mov dword ptr[ebx],0 ret trueGtrE: mov dword ptr[ebx],1 ret align 2 gtrEqualFin: ;---------------------------------------------------------------------------- dd shiftrFin-shiftr shiftr: mov ecx,[ebx] add ebx, byte 4 shr dword ptr[ebx],cl align 2 ret nop shiftrFin: ;---------------------------------------------------------------------------- dd noopFin-noop noop: align 2 ret nop noopFin: ;---------------------------------------------------------------------------- dd acceptFin-accept accept: push dword ptr[ebx] ; address push dword ptr[ebx+4] ; length add ebx, byte 4 call getConsoleInput add esp, byte 8 mov [ebx], eax ret align 2 acceptFin: ;---------------------------------------------------------------------------- dd andLogFin-andLog andLog: add ebx, byte 4 xor eax,eax cmp eax,[ebx] je andFalse cmp eax,[ebx-4] je andFalse mov dword ptr[ebx],1 ret andFalse: mov dword ptr[ebx],0 ret align 2 andLogFin: ;---------------------------------------------------------------------------- dd atoiFin-atoi atoi: push ecx push edx push esi mov byte ptr[ACHAR],' ' xor eax,eax xor edx,edx ;zero result mov esi,[ebx] ;pointer ascii lodsb cmp al,'-' jne atoiGo1 mov byte ptr[ACHAR],'-' atoiGo: lodsb atoiGo1: cmp al,'0' jl atoiEnd cmp al,'9' jg atoiEnd mov ecx,edx ;mutiply edx/result by 10 shl edx,2 add edx,ecx shl edx,1 sub al,'0' add edx,eax jmp atoiGo atoiEnd: cmp byte ptr[ACHAR],'-' jne atoiEndGo neg edx atoiEndGo: mov [ebx],edx pop esi pop edx pop ecx ret align 2 atoiFin: ;---------------------------------------------------------------------------- dd atofFin-atof atof: ret align 2 atofFin: ;---------------------------------------------------------------------------- dd callsubFin-callsub callsub: mov eax,[ebx] add ebx, byte 4 call eax align 2 ret nop callsubFin: ;---------------------------------------------------------------------------- dd catchFin-catch catch: pop eax ;get return address push eax push ecx mov ecx,[ebx] ;get jumpbuff address add ebx, byte 4 mov [ecx],eax ;save return address mov eax,esp add eax, byte 8 ;sp before calling catch mov [ecx+4],eax pop ecx ret align 2 catchFin: ;---------------------------------------------------------------------------- dd clearFin-clear clear: mov ebx,[DATA_STK] ;init data stack mov [DATA_PTR],ebx align 2 ret nop clearFin: ;---------------------------------------------------------------------------- dd gstrcmpFin-gstrcmp gstrcmp: push dword ptr [ebx] ;source push dword ptr [ebx+4] ;destination add ebx, byte 4 call strcmp add esp, byte 8 mov [ebx], eax ret align 2 gstrcmpFin: ;---------------------------------------------------------------------------- dd compileFin-compile compile: push ecx push edx push esi push edi push ebp ; init for constant optimization mov word ptr[CURRNT_TKN],0 mov word ptr[LAST_TKN],0 mov dword ptr[LAST_CONSTANT],0 ; init for locals mov dword ptr[LOCAL_COUNT],0 mov eax,[DICT_LAST] mov [DICT_LAST_SAVE],eax mov eax,[LOCAL_TABLE] mov [LOCAL_PTR],eax ; init compile pad mov eax,[CP_START] mov dword ptr[CP_PTR],eax compGo1: mov eax,[ebx] ;save previous source ptr mov dword ptr[PRE_SRC_PTR],eax mov ax,[CURRNT_TKN] mov [LAST_TKN],ax mov word ptr[DEBUG_EMIT],0 call token mov eax,[ebx] ;type of token mov [CURRNT_TKN],ax ;save for constant optimization mov ecx,[ebx+4] ;address of token mov ebp,[ebx+8] ;save new source ptr add ebx, byte 12 ;pop args cmp al,TKN_NULL jne compGo2 jmp compileEnd compGo2: cmp al,TKN_IDENT je compLookup mov dword ptr[GETPUT_FLAGS],0 cmp al,TKN_STRING je NEAR emitString cmp al,TKN_INT je NEAR emitInt cmp al,TKN_HEX je NEAR emitHex cmp al,TKN_FLOAT je NEAR emitFloat cmp al,TKN_CHAR je NEAR emitChar jmp compSyntax ;-------------------- lookup up orb in lex ---------------------------------- compLookup: sub ebx, byte 4 mov [ebx],ecx ;address call lookup popm esi ;get orb address cmp esi, byte 0 je NEAR compNoMatch mov al,[esi] ;get type add esi, byte 4 ;get address cmp al,TYP_CODE je NEAR emitCall cmp al,TYP_INLINE je NEAR emitInline cmp al,TYP_MEM je NEAR emitAddrVar cmp al,TYP_MEMIND je NEAR emitAddrInd ;--------------------- flow directives -------------------------------------- cmp al,TYP_COMPILE je compileFlow cmp al,TYP_DICTIONARY jne NEAR emitAddrVar compChgActDict: mov esi,[esi] mov [ACTIVE_DICT],esi mov eax,[esi] mov [DICT_LAST],eax mov eax,[esi+4] mov [DICT_END],eax jmp compGo4 compileFlow: mov esi,[esi] cmp esi,FLOW_GET je NEAR compGet cmp esi,FLOW_PUT je NEAR compPut cmp esi,FLOW_IF je NEAR compIf cmp esi,FLOW_THEN je NEAR compThen cmp esi,FLOW_ELSE je NEAR compElse cmp esi,FLOW_WHILE je NEAR compWhile cmp esi,FLOW_DO je NEAR compDo cmp esi,FLOW_BREAK je NEAR compBreak cmp esi,FLOW_CONTINUE je NEAR compContinue cmp esi,FLOW_RECURSE je NEAR compRecurse cmp esi,FLOW_EXIT je NEAR compExit cmp esi,FLOW_END je NEAR compEnd cmp esi,FLOW_LOCAL je NEAR compLocals cmp esi,FLOW_SEMICOLON je NEAR compileEnd jmp compSyntax compIf: mov eax, FLOW_IF call pushFstack jmp compGo3 compThen: call popFstack cmp eax,FLOW_IF ;THEN must follow IF jne NEAR compSyntax mov eax,[CP_PTR] add eax, byte 9 ;offset for je addr in CODE_THEN call pushFstack mov eax,FLOW_THEN call pushFstack mov esi,offset CODE_THEN mov ecx,13 ;length of CODE_THEN jmp emitCpy compElse: call popFstack cmp eax,FLOW_THEN ;ELSE must follow THEN jne NEAR compSyntax call popFstack ;get je address in eax mov edi,eax mov eax,[CP_PTR] sub eax,edi inc eax ;pos after jmp et and of THEN body stosd mov eax,[CP_PTR] inc eax ;move after jmp for jmp to endif call pushFstack mov eax,FLOW_ELSE call pushFstack mov esi,offset CODE_BRANCH mov ecx,5 jmp emitCpy compWhile: mov eax,[CP_PTR] call pushFstack mov eax,FLOW_WHILE call pushFstack jmp compGo3 compDo: call popFstack cmp eax,FLOW_WHILE jne NEAR compSyntax ;missing WHILE for DO mov eax,[CP_PTR] add eax, byte 9 ;addr of je offset in CODE_DO call pushFstack mov eax,FLOW_DO call pushFstack mov esi,offset CODE_DO mov ecx,13 ;length of code jmp emitCpy compEnd: call popFstack cmp eax,FLOW_THEN je endIf_ cmp eax,FLOW_ELSE je endIf_ cmp eax,FLOW_DO je endDo jmp compSyntax ;missing THEN/ELSE/DO before END compGet: mov word ptr[GET_FLAG],1 jmp compGo3 compPut: mov word ptr[PUT_FLAG],1 jmp compGo3 endIf_: call popFstack ;get address for IF NOT/ELSE offset mov edi,eax mov eax,[CP_PTR] sub eax,edi sub eax, byte 4 stosd jmp compGo3 endDo: call popFstack ;pop address for skip je offset mov edi,eax mov eax,[CP_PTR] sub eax,edi ;pos after jmp at end of WHILE body inc eax stosd mov edi,[CP_PTR] mov al,byte ptr[CODE_BRANCH] ;emit code for jmp stosb call popFstack ;addr beginning of WHILE loop mov [WHILE_ADDR],eax ;save it for 'continue' sub eax,edi sub eax, byte 4 stosd ;emit code for jmp offset mov [CP_PTR],edi call endBC jmp compGo3 ;----------------------------- parse local statement --------------------------------- compLocals: mov edx,[LOCAL_COUNT] cmp edx,0 jne compLocalsError compLocGet: pushm ebp call token mov eax,[ebx] ;type of token mov ecx,[ebx+4] ;address of token mov ebp,[ebx+8] ;save new source ptr add ebx, byte 12 ;pop args cmp al,TKN_IDENT jne NEAR compSyntax cmp byte ptr[ecx],';' je compLocalsEnd sub ebx, byte 8 mov [ebx+4],ecx mov dword ptr[ebx],TYP_MEM call create popm ecx mov [ecx],edx inc edx jmp compLocGet compLocalsEnd: mov [LOCAL_COUNT],edx jmp compGo3 compLocalsError: pushe E_NULL pushe E_ONELOCAL jmp errorProc ;-------------------------------------------------------------------------------------- compGo3: cmp word ptr[DEBUG_EMIT], byte 0 ;emit debug code je compGo4 mov edi,[CP_PTR] mov esi,offset CODE_TRACE mov eax,[DEBUG_LINE] mov [esi+6],eax mov ecx,17 rep movsb mov [CP_PTR],edi compGo4: pushm ebp jmp compGo1 ;--------------------- break and continue ----------------------------------- ;--------------------- recurse and exit ------------------------------------- ; ---- only allowed in the looping part 'do ... end' ------------------------ compBreak: mov ecx,FLOW_BREAK jmp BCREnd compContinue: mov ecx,FLOW_CONTINUE BCREnd: mov eax,[CP_PTR] add eax, byte 1 call pushWstack mov eax,ecx call pushWstack mov esi,offset CODE_BRANCH mov ecx,5 ;length of CODE_BRANCH jmp emitCpy compRecurse: mov edi,[CP_PTR] xor eax,eax mov al,byte ptr[CODE_RECURSE] stosb mov eax,[CP_START] sub eax,edi sub eax, byte 4 stosd mov [CP_PTR],edi jmp compGo3 compExit: mov edi,[CP_PTR] mov al,byte ptr[CODE_EXIT] stosb mov [CP_PTR],edi jmp compGo3 ;----------- process all break,continue on loop end ------------------------- endBC: call popWstack cmp eax, byte 0 je endBCEnd ;stack is empty cmp eax,FLOW_BREAK je endBreak cmp eax,FLOW_CONTINUE je endCont endBCEnd: ret endBreak: call popWstack ;pop address for jmp offset mov edi,eax mov eax,[CP_PTR] sub eax,edi sub eax, byte 4 stosd jmp endBC endCont: call popWstack mov edi,eax mov eax,[WHILE_ADDR] sub eax,edi sub eax, byte 4 stosd jmp endBC ;----------------------- Flow Stacks ---------------------------------------- pushFstack: push ecx mov ecx,[FLOW_PTR] sub ecx, byte 4 mov [ecx],eax mov [FLOW_PTR],ecx cmp ecx,offset FLOW_BTTM jne pushFEnd fstackError: jmp progFlowError pushFEnd: pop ecx ret popFstack: push ecx mov ecx,[FLOW_PTR] cmp ecx,offset FLOW_STK je fstackError mov eax,[ecx] add ecx, byte 4 mov [FLOW_PTR],ecx pop ecx ret ;--------------------------------------------- pushWstack: push ecx mov ecx,[WHD_PTR] sub ecx, byte 4 mov [ecx],eax mov [WHD_PTR],ecx cmp ecx,offset WHD_BTTM jne pushWEnd wstackError: jmp progFlowError pushWEnd: pop ecx ret popWstack: push ecx mov ecx,[WHD_PTR] cmp ecx,offset WHD_STK je wstkEmpty mov eax,[ecx] add ecx, byte 4 mov [WHD_PTR],ecx pop ecx ret wstkEmpty: xor eax,eax pop ecx ret checkFlowStacks: cmp dword ptr [FLOW_PTR],offset FLOW_STK jne progFlowError cmp dword ptr [WHD_PTR],offset WHD_STK jne progFlowError ret progFlowError: sub ebx, byte 8 mov eax,[PRE_SRC_PTR] mov [ebx+4],eax mov dword ptr[ebx],offset E_FLOWSTK jmp errorProc ;---------------------- emit code ------------------------------------------- emitCall: mov ax,[DEBUG_FLAG] mov [DEBUG_EMIT],ax cmp word ptr[GET_FLAG],1 je NEAR emitAddrInd cmp word ptr[PUT_FLAG],1 je NEAR emitAddrPut mov ecx,offset CODE_JSR mov esi,[esi] mov [ecx+1],esi mov ecx,7 ;length of CODE_JSR mov esi,offset CODE_JSR jmp emitCpy emitInline: mov ax,[DEBUG_FLAG] mov [DEBUG_EMIT],ax cmp word ptr[GET_FLAG],1 je NEAR emitAddrInd cmp word ptr[PUT_FLAG],1 je NEAR emitAddrPut cmp word ptr[LAST_TKN],TKN_INT jl emitInlineGo cmp dword ptr[esi],offset adds je emitConstAdds cmp dword ptr[esi],offset subs je emitConstSubs emitInlineGo: mov esi,[esi] ;address of code mov ecx,[esi-4] ;length sub ecx, byte 2 ;without ret and nop's jmp emitCpy emitConstAdds: mov edi,[CP_PTR] sub edi, byte 9 ;go back before CODE_CONST mov ax,word ptr[CODE_CONST_ADDS] jmp emitConstAddsSubs emitConstSubs: mov edi,[CP_PTR] sub edi,byte 9 ;go back before CODE_CONST mov ax,word ptr[CODE_CONST_SUBS] emitConstAddsSubs: mov [edi],ax mov eax,[LAST_CONSTANT] mov [edi+2],eax add edi, byte 6 mov [CP_PTR],edi jmp compGo3 emitAddrVar: call emitCheckLocal emitAddr: cmp word ptr[GET_FLAG],1 je emitAddrInd cmp word ptr[PUT_FLAG],1 je emitAddrPut mov ecx,offset CODE_ADDR mov [ecx+5],esi mov esi,offset CODE_ADDR mov ecx,9 jmp emitCpy emitAddrInd: mov dword ptr[GETPUT_FLAGS],0 mov ecx,offset CODE_ADDR_FETCH mov [ecx+1],esi mov esi,offset CODE_ADDR_FETCH mov ecx,10 jmp emitCpy emitAddrPut: mov dword ptr[GETPUT_FLAGS],0 mov ecx,offset CODE_ADDR_STORE mov [ecx+3],esi mov esi,offset CODE_ADDR_STORE mov ecx,10 jmp emitCpy emitString: mov esi,ecx ;address xor ecx,ecx mov cx,[esi-2] ;length inc ecx pushm ecx call gmalloc popm edi mov edx,edi rep movsb mov esi,edx jmp emitAddr emitInt: pushm ecx call atoi jmp emitCons emitHex: pushm ecx call htoi jmp emitCons emitFloat: pushm ecx call atof popm esi jmp emitAddr emitChar: xor eax,eax mov al,[ecx] jmp emitCons1 emitCons: popm eax mov [LAST_CONSTANT],eax ;save for optimization emitCons1: mov ecx,offset CODE_CONST mov [ecx+5],eax mov esi,offset CODE_CONST mov ecx,9 emitCpy: mov edi,[CP_PTR] rep movsb mov [CP_PTR],edi jmp compGo3 ;---------------------------------------------------------------------------- emitCheckLocal: ;remember offset, where to fill in sub esi, byte 4 ;the addresses of local cmp esi,[DICT_LAST_SAVE] ;after code is allocated in memory jle NEAR emitNoLocal ;and the addreses of locals are cmp esi,[DICT_LAST] ;known from [LOCAL_PTR] jg NEAR emitNoLocal add esi, byte 4 mov eax,[CP_PTR] ; cmp word ptr[GET_FLAG],1 jne emitCL1 add eax, byte 1 ;offset into CODE_ADDR_FETCH jmp emitCL3 emitCL1: cmp word ptr[PUT_FLAG],1 jne emitCL2 add eax, byte 3 ;offset into CODE_ADDR_STORE jmp emitCL3 emitCL2: add eax, byte 5 ;offset into CODE_ADDR ; emitCL3: sub eax,[CP_START] ;eax = offset into code for local addr mov ecx,[esi] ;ecx = number of local 0 ... n-1 shl ecx,2 ;ecx offset into locals in compiled code mov esi,[LOCAL_PTR] mov [esi],ax mov [esi+2],cx add dword ptr [LOCAL_PTR],4 ;check LOCAL_TABLE full sub esi,[LOCAL_TABLE] cmp esi,[LOCAL_SIZE] jl emitCLend sub ebx, byte 8 mov eax,[PRE_SRC_PTR] mov [ebx+4],eax mov dword ptr[ebx],offset E_LOCALOVR jmp errorProc emitCLend: mov esi,ecx ret emitNoLocal: add esi, byte 4 ret emitLocals: cmp dword ptr [LOCAL_COUNT],0 je emitNoLocal mov edi,[ebx+4] ;address of code add edi,edx ;edi = start of locals mov esi,[LOCAL_TABLE] cmp esi,[LOCAL_PTR] je emitLocalsEnd emitLocAddr: xor eax,eax xor edx,edx mov ax,[esi] ;offset in code add eax,[ebx+4] ;address of code mov ecx,edi mov dx,word ptr[esi+2];offset in locals add ecx,edx mov [eax],ecx add esi,4 cmp esi,[LOCAL_PTR] jne emitLocAddr emitLocalsEnd: xor eax,eax mov edi,[DICT_LAST_SAVE] mov [DICT_LAST],edi mov al,[edi+2] add edi,byte 8 add edi,eax mov dword ptr[edi],00000FFFFh ret ;---------------------- errors and fin -------------------------------------- compSyntax: sub ebx, byte 8 mov eax,dword ptr[PRE_SRC_PTR] mov [ebx+4],eax ;push new source ptr mov dword ptr[ebx],offset E_UNKNOWN jmp errorProc compNoMatch: pushm ecx pushe E_NOWORD jmp errorProc compileEnd: call checkFlowStacks mov ecx,[CP_PTR] mov al,byte ptr [CODE_EXIT] mov [ecx],al mov esi,[CP_START] sub ecx,esi add ecx, byte 2 ;add for CODE_EXIT and align and ecx,0FFFFFFFEh ;align length even mov edx,ecx ;save code length mov eax,[LOCAL_COUNT] shl eax, byte 2 ;calc space for locals add ecx,eax pushm ecx call gmalloc mov edi,[ebx] ;code addr mov ecx,edx ;recover code length rep movsb ;copy code sub ebx, byte 4 ;code addr is already on stack mov [ebx],ebp ;new source ptr call emitLocals pop ebp pop edi pop esi pop edx pop ecx ret align 2 compileFin: ;---------------------------------------------------------------------------- dd gstrcatFin-gstrcat gstrcat: push dword ptr[ebx] ;source push dword ptr[ebx+4];destination add ebx, byte 4 call strcat add esp, byte 8 mov [ebx],eax ret align 2 gstrcatFin: ;---------------------------------------------------------------------------- dd gstrcpyFin-gstrcpy gstrcpy: push dword ptr [ebx] ;get source push dword ptr [ebx+4] ;get destination add ebx, byte 4 call strcpy add esp, byte 8 mov [ebx],eax ret align 2 gstrcpyFin: ;---------------------------------------------------------------------------- dd createFin-create create: push ecx push edx push esi push edi mov edx,[ebx] ;type mov esi,[ebx+4] ;address mov edi,esi mov eax,0 mov ecx,-1 repne scasb ;find length not ecx add ebx, byte 8 ;pop args ; mov edi,[DICT_LAST] mov al,[edi+2] add edi,eax ;length last name add edi,20 ;2 hdrs + 0FFFF0000h add edi,ecx ;length of new name cmp edi,[DICT_END] jle createGo ; pushe E_NULL pushe E_DICFULL jmp errorProc createGo: mov edi,[DICT_LAST] add edi,8 add edi,eax mov [DICT_LAST],edi mov [edi],dx ;write type add cl,1 ;align length and ecx,0FFFFFFFEh mov [edi+2],cl ;write length mov [edi+3],al ;write length of prev name add edi,4 pushm edi ;addr of content dword mov dword ptr[edi],0 ;init content to zero add edi,4 ;name area createCpy: rep movsb ;copy name mov byte ptr[edi-1],0 ;secure second trailing 0 mov dword ptr[edi],0000FFFFh createEnd: pop edi pop esi pop edx pop ecx ret align 2 createFin: ;---------------------------------------------------------------------------- dd decrementFin-decrement decrement: mov eax,[ebx] add ebx, byte 4 dec dword ptr[eax] align 2 ret nop decrementFin: ;---------------------------------------------------------------------------- dd depthFin-depth depth: mov eax,[DATA_STK] sub eax,ebx shr eax,2 sub ebx, byte 4 mov [ebx],eax ret align 2 depthFin: ;---------------------------------------------------------------------------- dd dispFin-disp disp: push ebp push ecx mov ebp,esp mov ecx,esp sub ecx,16 ;scratch space for itoa conversion mov esp,ecx pushm ecx ;address on top of extisting integer call itoa add ebx, byte 4 ;pop address ; push ebp ;Win32 does not preserve ebp push ecx call printf add esp, byte 4 pop ebp ; mov esp,ebp pop ecx pop ebp ret align 2 dispFin: ;---------------------------------------------------------------------------- dd dropFin-drop drop: add ebx, byte 4 align 2 ret nop dropFin: ;---------------------------------------------------------------------------- dd dupsFin-dups dups: mov eax,[ebx] sub ebx, byte 4 mov [ebx],eax align 2 ret nop dupsFin: ;---------------------------------------------------------------------------- dd emitFin-emit emit: push esi push ebp mov ebp,esp sub esp, byte 4 mov esi,esp popm eax and eax,0000FFFFh mov [esi],eax ; push esi call printf add esp, byte 4 ; mov esp,ebp pop ebp pop esi ret align 2 emitFin: ;---------------------------------------------------------------------------- dd evalFin-eval eval: push ecx push edx push esi push edi push ebp mov ebp,esp ;save stack pointer mov dword ptr [DEBUG_LINE],0 evalGo: mov eax,[ebx] mov dword ptr[OLD_SRC_PTR],eax call token mov eax,[ebx] ;token type mov esi,[ebx+4] ;token address mov ecx,[ebx+8] ;new src pointer add ebx, byte 12 ;pop all args cmp al,TKN_NULL ;check for end of source je NEAR evalEnd cmp al,TKN_IDENT je lexLookup mov dword ptr[GETPUT_FLAGS],0 cmp al,TKN_STRING je NEAR pushString cmp al,TKN_INT ;breaks near je NEAR pushInt cmp al,TKN_HEX je NEAR pushHex cmp al,TKN_FLOAT je NEAR pushFloat cmp al,TKN_CHAR je NEAR pushChar jmp evalCont lexLookup: sub ebx, byte 4 mov [ebx],esi ;address of token call lookup cmp dword ptr[ebx],0 ;check orb address for not found jne execOrb mov [ebx],esi pushe E_NOWORD ;push error 'word not found' jmp errorProc execOrb: popm esi ;pop orb address mov al,[esi] add esi, byte 4 cmp al,TYP_CODE je NEAR execCode cmp al,TYP_INLINE je NEAR execCode cmp al,TYP_MEM je NEAR pushAddr cmp al,TYP_MEMIND je NEAR pushAddrInd cmp al,TYP_COMPILE je execCompile cmp al,TYP_DICTIONARY jne NEAR pushAddr ;allow user orb types 5..14 changeActDict: mov esi,[esi] ;change active dictionary mov [ACTIVE_DICT],esi mov eax,[esi] mov [DICT_LAST],eax mov eax,[esi+4] mov [DICT_END],eax jmp evalCont execCompile: mov esi,[esi] cmp esi,FLOW_GET je execOrbGet cmp esi,FLOW_PUT je execOrbPut cmp esi,FLOW_SEMICOLON ;ignore in eval mode jne execOrbErr jmp evalCont execOrbGet: mov word ptr[GET_FLAG],1 jmp evalCont execOrbPut: mov word ptr[PUT_FLAG],1 jmp evalCont execOrbErr: mov eax,dword ptr[OLD_SRC_PTR] mov [ebx],eax pushe E_COMPILE ;use IF/THEN/ELSE/WHILE/DO etc only in conpile jmp errorProc execCode: cmp word ptr[GET_FLAG],1 je pushAddrInd cmp word ptr[PUT_FLAG],1 je popAddrPut mov eax,ecx call pushsStack ;save source pointer mov eax,[esi] push ebp call eax ;call subroutine pop ebp call popsStack mov ecx,eax jmp evalCont pushAddrInd: mov dword ptr[GETPUT_FLAGS],0 mov esi,[esi] pushAddr: cmp word ptr[GET_FLAG],1 je pushAddrInd cmp word ptr[PUT_FLAG],1 je popAddrPut pushm esi jmp evalCont popAddrPut: mov dword ptr[GETPUT_FLAGS],0 mov eax,[ebx] add ebx, byte 4 mov [esi],eax jmp evalCont ; copy string to local stack space area (for reentrance of 'eval') ; this assumes all segments are equal! (flat model) pushString: mov edx,ecx ;save new src ptr xor ecx,ecx mov cx,[esi-2] ;get string length mov edi,esp ;stack pointer to copy destination sub edi,ecx ;length of string sub edi, byte 4 ;trailing 0 + headroom and edi,0FFFFFFFCh ;align stack ptr mov esp,edi ;allocate space on stack mov [edi],cx ;put length in front add edi, byte 2 pushm edi ;push address of string on data stack cmp cx,0 je copyStringEnd rep movsb ;copy string onto local stack space copyStringEnd: mov byte ptr[edi],0 mov ecx,edx ;recover new src ptr jmp evalCont pushInt: pushm esi call atoi jmp evalCont pushHex: pushm esi call htoi jmp evalCont pushFloat: pushm esi call atof jmp evalCont pushChar: xor eax,eax lodsb ;get first char in token pushm eax evalCont: call stackCheck pushm ecx jmp evalGo ;------------------------- source pointer stack ----------------------------- pushsStack: push ecx ;save reg mov ecx,dword ptr[SSTK_PTR] sub ecx, byte 4 mov [ecx],eax mov dword ptr[SSTK_PTR],ecx cmp ecx,offset SSTK_BTTM jg pushsEnd sstackError: sub ebx, byte 8 mov dword ptr[ebx+4],offset E_NULL mov dword ptr[ebx],offset E_EVALOVR jmp errorProc pushsEnd: pop ecx ret popsStack: push ecx mov ecx,dword ptr[SSTK_PTR] cmp ecx,offset SSTK_STK je sstackError mov eax,[ecx] add ecx, byte 4 mov dword ptr[SSTK_PTR],ecx pop ecx ret ;---------------------------------------------------------------------------- evalEnd: mov esp,ebp pop ebp pop edi pop esi pop edx pop ecx ret align 2 evalFin: ;---------------------------------------------------------------------------- dd exitEvalFin-exitEval exitEval: jmp exitProc align 2 exitEvalFin: ;---------------------------------------------------------------------------- dd gmemsetFin-gmemset gmemset: push edi mov edi,[ebx+8] mov eax,[ebx+4] mov ecx,[ebx] add ebx, byte 8 mov [ebx],edi rep stosb pop edi ret align 2 gmemsetFin: ;---------------------------------------------------------------------------- dd gstrstrFin-gstrstr gstrstr: push dword ptr [ebx] ;key push dword ptr [ebx+4] ;string add ebx, byte 4 call strstr add esp, byte 8 mov [ebx],eax ret align 2 gstrstrFin: ;---------------------------------------------------------------------------- dd gfreeFin-gfree gfree: mov eax,[ebx] add ebx, byte 4 ;pop ptr push eax ;push ptr mov eax,[eax-4] ;get size add [MEM_FREED],eax call free add esp, byte 4 ret align 2 gfreeFin: ;---------------------------------------------------------------------------- dd getbFin-getb getb: mov eax,[ebx] mov al,[eax] cbw cwde mov [ebx],eax align 2 ret nop getbFin: ;---------------------------------------------------------------------------- dd getcFin-getc getc: mov eax,[ebx] mov al,[eax] and eax,000000ffh mov [ebx],eax align 2 ret nop getcFin: ;---------------------------------------------------------------------------- dd getEnvFin-getEnv getEnv: push dword ptr [ebx] call getenv add esp, byte 4 mov [ebx], eax ret align 2 getEnvFin: ;---------------------------------------------------------------------------- dd getwFin-getw getw: mov eax,[ebx] mov ax,[eax] cwde mov [ebx],eax align 2 ret nop getwFin: ;---------------------------------------------------------------------------- dd getuFin-getu getu: mov eax,[ebx] mov eax,[eax] and eax,0000ffffh mov [ebx],eax align 2 ret nop getuFin: ;---------------------------------------------------------------------------- dd getlFin-getl getl: mov eax,[ebx] mov eax,[eax] mov [ebx],eax align 2 ret nop getlFin: ;---------------------------------------------------------------------------- dd htoiFin-htoi htoi: push ecx push esi xor eax,eax xor ecx,ecx mov esi,[ebx] ;string address htoiGo: lodsb cmp al,0 je htoiEnd cmp al,'a' jl isHexGo1 cmp al,'f' jg htoiEnd sub al,'a' add al,10 jmp isHexEnd isHexGo1: cmp al,'A' jl isHexGo2 cmp al,'F' jg htoiEnd sub al,'A' add al,10 jmp isHexEnd isHexGo2: cmp al,'0' jl htoiEnd cmp al,'9' jg htoiEnd sub al,48 isHexEnd: shl ecx,4 add ecx,eax jmp htoiGo htoiEnd: mov [ebx],ecx pop esi pop ecx ret align 2 htoiFin: ;---------------------------------------------------------------------------- dd incrementFin-increment increment: mov eax,[ebx] add ebx, byte 4 inc dword ptr[eax] align 2 ret nop incrementFin: ;---------------------------------------------------------------------------- dd initFin-init init: call GokuInit call clear ret align 2 initFin: ;---------------------------------------------------------------------------- dd itoaFin-itoa itoa: push ecx push edx mov eax,[ebx+4] ;interg to divide xor edx,edx ;set zero xor edi,edi mov byte ptr[ACHAR],0 mov ecx,10 ;divisor cmp eax,0 jge itoaGo mov byte ptr[ACHAR],1 ;remember if number is negative neg eax itoaGo: cmp eax,10 jge itoaDiv add al,'0' push ax inc edi ;count characters jmp itoaEnd itoaDiv: idiv ecx add dl,'0' push dx xor edx,edx inc edi jmp itoaGo itoaEnd: cmp byte ptr[ACHAR],1 ;was number negative ? jne itoaEndGo mov ax,'-' push ax inc edi itoaEndGo: mov ecx,edi ;get length mov edi,[ebx] ;get address for ascii number itoaReverse: pop ax stosb loop itoaReverse mov al,0 stosb mov ecx,[ebx] ;get original address add ebx,4 ;pop one arg mov [ebx],ecx ;return org address pop edx pop ecx ret align 2 itoaFin: ;---------------------------------------------------------------------------- dd gstrlenFin-gstrlen gstrlen: push dword ptr [ebx] ;string call strlen add esp, byte 4 mov [ebx],eax ret align 2 gstrlenFin: ;---------------------------------------------------------------------------- dd lookupFin-lookup lookup: push ecx push edx push esi push edi push ebp mov edi,[ebx] ;name address mov ecx,-1 mov al,0 repne scasb not ecx mov edx,ecx ;length including trailing zero mov esi,offset lastCoreEntry ;search core dict first compareInit: mov ebp,esi ;save address add esi, byte 8 ;skip header and ptr mov edi,[ebx] ;name address mov ecx,edx ;length compareLex: repz cmpsb jne nextWord jmp lexMatch nextWord: mov esi,ebp nextWordGo: xor ecx,ecx mov cl,[esi+3] ;read length of prev name sub esi,ecx ;goto start of previous name sub esi, byte 8 ;goto start of header nextCheck: cmp byte ptr[esi],0 jge compareInit cmp byte ptr[esi],TYP_CORE_START ;start of core jne noLexMatch ;it is end of user dictionary mov esi,[DICT_LAST] ;last entry of user dictionary jmp nextCheck noLexMatch: mov ebp,0 lexMatch: mov [ebx],ebp ;matching orb at start of hdr mov eax,[CURRNT_DICT] cmp eax,[ACTIVE_DICT] je lookupEnd mov [ACTIVE_DICT],eax ;restore current dictionary mov ecx,[eax] mov [DICT_LAST],ecx mov ecx,[eax+4] mov [DICT_END],ecx lookupEnd: pop ebp pop edi pop esi pop edx pop ecx ret align 2 lookupFin: ;---------------------------------------------------------------------------- dd gmallocFin-gmalloc gmalloc: push ecx push edx push esi push edi push dword ptr 1 push dword ptr [ebx] ;num bytes call calloc add esp, byte 8 cmp eax,0 jne gmallocEnd pushe E_NULL pushe E_NOMEMORY jmp errorProc gmallocEnd: mov ecx, [ebx] ;num bytes add [MEM_ALLOCED],ecx ;mem statistics mov [ebx],eax ;get mem ptr pop edi pop esi pop edx pop ecx ret align 2 gmallocFin: ;---------------------------------------------------------------------------- dd maxFin-max max: mov eax,[ebx] add ebx, byte 4 cmp eax,[ebx] jl maxEnd mov [ebx],eax maxEnd: ret align 2 maxFin: ;---------------------------------------------------------------------------- dd gmemcpyFin-gmemcpy gmemcpy: push ecx push esi push edi mov esi,[ebx+8] mov edi,[ebx+4] mov ecx,[ebx] add ebx, byte 8 mov [ebx],edi rep movsb pop edi pop esi pop ecx ret align 2 gmemcpyFin: ;---------------------------------------------------------------------------- dd minFin-min min: mov eax,[ebx] add ebx, byte 4 cmp eax,[ebx] jg minEnd mov [ebx],eax minEnd: ret align 2 minFin: ;---------------------------------------------------------------------------- dd notLogFin-notLog notLog: cmp dword ptr[ebx],0 je notTrue mov dword ptr[ebx],0 ret notTrue: mov dword ptr[ebx],1 ret align 2 notLogFin: ;---------------------------------------------------------------------------- dd orLogFin-orLog orLog: cmp dword ptr[ebx],0 jne orLogTrue cmp dword ptr[ebx+4],0 jne orLogTrue add ebx, byte 4 mov dword ptr[ebx],0 ret orLogTrue: add ebx, byte 4 mov dword ptr[ebx],1 ret align 2 orLogFin: ;---------------------------------------------------------------------------- dd putbFin-putb putb: mov eax,[ebx] mov dl,byte ptr[ebx+4] mov [eax],dl add ebx, byte 8 align 2 ret nop putbFin: ;---------------------------------------------------------------------------- dd putwFin-putw putw: mov eax,[ebx] mov dx,word ptr[ebx+4] mov [eax],dx add ebx, byte 8 align 2 ret nop putwFin: ;---------------------------------------------------------------------------- dd putlFin-putl putl: mov eax,[ebx] mov edx,[ebx+4] mov [eax],edx add ebx, byte 8 align 2 ret nop putlFin: ;---------------------------------------------------------------------------- dd quitFin-quit quit: xor eax,eax push eax call exit ret align 2 quitFin: ;---------------------------------------------------------------------------- dd sourcePtrFin-sourcePtr sourcePtr: push ecx mov ecx,dword ptr[SSTK_PTR] sub ebx, byte 4 mov eax,[ecx] mov [ebx],eax pop ecx ret align 2 sourcePtrFin: ;---------------------------------------------------------------------------- dd stackFin-stack stack: mov eax,[ebx] shl eax,2 add eax,ebx mov eax,[eax] mov [ebx],eax ret align 2 stackFin: ;---------------------------------------------------------------------------- dd sysvarFin-sysvar sysvar: sub ebx,4 mov dword ptr[ebx],offset SYSTEM_RECORD ret align 2 sysvarFin: ;---------------------------------------------------------------------------- dd swapFin-swap swap: mov eax,[ebx] mov edx,[ebx+4] mov [ebx],edx mov [ebx+4],eax align 2 ret nop swapFin: ;---------------------------------------------------------------------------- dd tokenFin-token token: push ecx push edx push esi push edi push ebp popm esi ;pop source address cmp esi, byte 0 je NEAR endSource xor edx,edx ;length of token xor eax,eax strip: lodsb cmp al, byte 0 je NEAR endSource cmp al,LF jne stripCont add dword ptr [DEBUG_LINE],1 stripCont: cmp al,' ' ;strip all space and less jle strip mov ebp,esi ;save token address dec ebp cmp al,'#' ;check for comment jne tokenGo commentCheck: lodsb cmp al,0 je NEAR endSource cmp al,LF jne commentCheck add dword ptr [DEBUG_LINE],1 jmp strip tokenGo: cmp al,'-' jne tokenGo1 mov al,[esi] call checkNumAL je negNumTkn mov al,'-' tokenGo1: call checkAlphaAL je nameTkn call checkNumAL je numberTkn cmp al,QUOTATION je NEAR quoted cmp al,SQUOTE je NEAR squoted jmp specialNameTkn nameTkn: inc edx ;increment length of token lodsb ;get next char call checkAlphaAL je nameTkn call checkNumAL je nameTkn cmp al,UNDERSCORE je nameTkn cmp al,PERIOD je nameTkn mov dword ptr[TOKEN_TYPE],TKN_IDENT jmp tokenEnd negNumTkn: inc esi inc edx jmp numberGo numberTkn: cmp al,'0' jne numberGo cmp byte ptr[esi],'x' jne numberGo inc esi ;source address mov dword ptr[TOKEN_TYPE],TKN_HEX numHexGo: lodsb ;get next char call isHexDigitAL jne numHexEnd inc edx jmp numHexGo numHexEnd: add ebp, byte 2 ;skip the '0x' for token address jmp tokenEnd numberGo: inc edx ;token length lodsb ;get next char call checkNumAL je numberGo mov dword ptr[TOKEN_TYPE],TKN_INT jmp tokenEnd specialNameTkn: inc edx call checkSeparatorAL jne specialCont mov dword ptr[TOKEN_TYPE],TKN_IDENT jmp tokenEnd2 specialCont: lodsb cmp al,' ' jle specialEnd call checkSpecialAL je specialNameTkn specialEnd: mov dword ptr[TOKEN_TYPE],TKN_IDENT tokenEnd: dec esi tokenEnd2: sub ebx, byte 12 mov eax,[TOKEN_TYPE] mov [ebx+8],esi ;push new source ptr mov [ebx],eax ;token type ; check if space for token mov edi,edx add edi, byte 3 cmp edi,[TOKEN_SIZE] jle tokenCopy pushe ebp pushe E_LONGSTR jmp errorProc ; tokenCopy: mov edi,[TOKEN_BUFFER] mov ecx,edx ;length mov esi,ebp ;token addr mov [edi],cx add edi, byte 2 mov [ebx+4],edi ;save token address rep movsb ;copy string mov byte ptr[edi],0 ;trailing 0 pop ebp pop edi pop esi pop edx pop ecx ret endSource: mov dword ptr[TOKEN_TYPE],TKN_NULL jmp tokenEnd ;--------------------------------- quoted string ---------------------------- quoted: mov edi,[STR_CLEAN] quotedGo1: lodsb cmp al,0 je quotedErr cmp al,QUOTATION je quotedEnd cmp al,LF jne quotedGo2 add dword ptr [DEBUG_LINE],1 quotedGo2: cmp al,BACKSLASH jne quotedGo9 ; process special chars preceded by '\' lodsb ;char after backslash cmp al,0 je quotedErr call isHexDigitAL je quotedHex quotedGo4: cmp al,'n' ;check hex line feed jne quotedGo5 mov al,LF quotedGo5: cmp al,'r' ;check for hex return jne quotedGo6 mov al,CR quotedGo6: cmp al,'t' ;check for hex tab jne quotedGo7 mov al,TAB quotedGo7: cmp al,'\' jne quotedGo8 mov al,BACKSLASH quotedGo8: cmp al,'"' jne quotedGo9 mov al,QUOTATION quotedGo9: stosb inc edx cmp edx,[STR_CLEAN_SIZE] jl quotedGo1 sub ebx, byte 8 mov [ebx+4],ebp mov dword ptr[ebx],offset E_LONGSTR jmp errorProc quotedErr: sub ebx, byte 8 mov [ebx+4],ebp mov dword ptr[ebx],offset E_MISSQU jmp errorProc quotedEnd: mov dword ptr[TOKEN_TYPE],TKN_STRING ;push type mov ebp,[STR_CLEAN] ;token address jmp tokenEnd2 quotedHex: mov ch,cl ;save converted hexdigit mov al,[esi] call isHexDigitAL jne quotHexEnd shl ch,4 add ch,cl inc esi quotHexEnd: mov al,ch jmp quotedGo9 ;------------------------- single quoted character -------------------------- squoted: lodsb cmp al,0 je squotedErr squoteGo: lodsb cmp al,0 je squotedErr cmp al,SQUOTE je squoteEnd jmp squoteGo squoteEnd: mov dword ptr[TOKEN_TYPE],TKN_CHAR inc ebp inc edx jmp tokenEnd2 squotedErr: sub ebx, byte 8 mov [ebx+4],ebp mov dword ptr[ebx],offset E_MISSQU jmp errorProc ;----------------- check characters ----------------------------------------- checkAlphaAL: cmp ax,'A' jl NEAR isNot cmp ax,'z' jle alphaCont cmp ax,192 ;check for non english alpha chars jge isAlpha jmp isNot alphaCont: cmp ax,'Z' jle isAlpha cmp ax,'a' jl NEAR isNot isAlpha: xor ah,ah ;set zero flag ret checkNumAL: cmp ax,'0' jl isNot cmp ax,'9' jg isNot isNum: xor ah,ah ;set zero flag ret checkSpecialAL: call checkAlphaAL je isNot call checkNumAL je isNot isSpecial: xor ah,ah ret checkSeparatorAL: cmp al,LEFT_PAR je isSeparator cmp al,RIGHT_PAR je isSeparator cmp al,LEFT_BRACKET je isSeparator cmp al,RIGHT_BRACKET je isSeparator cmp al,COLON je isSeparator cmp al,SEMICOLON jne isNot isSeparator: xor ah,ah ret isHexDigitAL: xor cl,cl call checkNumAL je isHex0 cmp al,'A' jl isNot cmp al,'f' jg isNot cmp al,'F' jle isHex0 cmp al,'a' jge isHex0 jmp isNot isHex0: cmp al,'a' jle isHex1 mov cl,al sub cl,'a' add cl,10 jmp isHexTrue isHex1: cmp al,'A' jl isHex2 mov cl,al sub cl,'A' add cl,10 jmp isHexTrue isHex2: mov cl,al sub cl,48 isHexTrue: xor ah,ah ret isNot: cmp ah,1 ;clear zero flag ret align 2 tokenFin: ;---------------------------------------------------------------------------- dd throwFin-throw throw: push ecx mov ecx,[ebx] add ebx, byte 4 mov eax,[ecx+4] ;get esp mov esp,eax mov eax,[ecx] push eax ;push return address fom call to catch ret align 2 throwFin: ;---------------------------------------------------------------------------- dd ptypeFin-ptype ptype: popm eax push eax call printf add esp,4 ret align 2 ptypeFin: ;---------------------------------------------------------------------------- dd updatePtrFin-updatePtr updatePtr: push ecx mov ecx,[SSTK_PTR] mov eax,[ebx] add ebx, byte 4 mov [ecx],eax pop ecx ret align 2 updatePtrFin: ;---------------------------------------------------------------------------- dd callLibFin-callLib callLib: push ecx push edx push esi push edi push ebp mov ebp,[ebx] ;address mov ecx,[ebx+4] ;count mov [ARG_COUNT],ecx add ebx, byte 8 cmp ecx,0 je callCsub ; pushParams: push dword ptr[ebx] ;push arg on CPU stack add ebx, byte 4 ;pop arg from Goku data stack loop pushParams callCsub: call ebp ; mov ecx,[ARG_COUNT] shl ecx,2 add esp,ecx ;not required on Win32 DLLs ; sub ebx, byte 4 mov [ebx],eax ;push return arg cld pop ebp pop edi pop esi pop edx pop ecx ret align 2 callLibFin: ;---------------------------------------------------------------------------- dd gcloseFin-gclose gclose: push dword ptr[ebx] ;handle call close add esp, byte 4 mov [ebx],eax ret align 2 gcloseFin: ;---------------------------------------------------------------------------- dd gsystemFin-gsystem gsystem: push dword ptr[ebx] call system add esp, byte 4 mov [ebx],eax ret align 2 gsystemFin: ;---------------------------------------------------------------------------- dd loadLibFin-loadLib loadLib: push dword ptr[ebx] ;ptr to libPathFile call loadLibrary add esp, byte 4 mov [ebx],eax ;library handle ret align 2 loadLibFin: ;---------------------------------------------------------------------------- dd loadFuncFin-loadFunc loadFunc: push dword ptr[ebx] ;ptr to function name push dword ptr[ebx+4] ;library handle call loadFunction add esp, 8 add ebx, 4 mov [ebx],eax ;ptr to C function ret align 2 loadFuncFin: ;---------------------------------------------------------------------------- dd gopenFin-gopen gopen: push ebp push dword ptr[ebx] ;mode push dword ptr[ebx+4] ;filePathName call open add esp, byte 8 add ebx, byte 4 mov [ebx],eax pop ebp ret align 2 gopenFin: ;---------------------------------------------------------------------------- dd greadFin-gread gread: push dword ptr[ebx] ;size push dword ptr[ebx+4] ;ptr push dword ptr[ebx+8] ;handle call read add esp, byte 12 add ebx, byte 8 mov [ebx],eax ret align 2 greadFin: ;---------------------------------------------------------------------------- dd gwriteFin-gwrite gwrite: push dword ptr[ebx] ;size push dword ptr[ebx+4] ;ptr push dword ptr[ebx+8] ;handle call write add esp, byte 12 add ebx, byte 8 mov [ebx],eax ret align 2 gwriteFin: ;---------------------------------------------------------------------------- dd gseekFin-gseek gseek: push dword ptr[ebx] ;method push dword ptr[ebx+4] ;amount push dword ptr[ebx+8] ;handle call lseek add esp, byte 12 add ebx, byte 8 mov [ebx],eax ret align 2 gseekFin: ;---------------------------------------------------------------------------- dd gsleepFin-gsleep gsleep: push dword ptr[ebx] ;seconds call sleep add esp, byte 4 sub ebx, byte 4 ret align 2 gsleepFin: ;--------------------------------------------------------------------------- dd gtimeFin-gtime gtime: push dword 0 call time add esp, byte 4 sub ebx, byte 4 mov [ebx],eax ret align 2 gtimeFin: ;---------------------------------------------------------------------------- dd gdateFin-gdate gdate: push dword ptr [ebx] ; time in seconds call date add esp, byte 4 mov dword ptr [ebx], eax ret align 2 gdateFin: ;---------------------------------------------------------------------------- ;ends ;---------------------------------------------------------------------------- ;end ;----------------------------- E O F ----------------------------------------