News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Simple expressions

Started by donkey, January 26, 2012, 04:19:24 PM

Previous topic - Next topic

donkey

I needed a very simple expression evaluator for a project I've attached it here in case anyone else can use one. It is extremely simple and not meant to do anything too complex, there is no operator precedence, its strictly a left to right evaluator. If you want to enforce precedence use (). This pretty much meets my needs so I'm not likely to expand on it or fix any parts of it, if you need something more you're free to modify all you need and post your results here.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave


donkey

I like writing my own when I need one but I'll take a look at qWord's and see if I can't find a place to use it.

A quick look and its way too much for my use, polluted with macros (I really dislike macros) and not easily incorporated into any of my code base. Have to trace through the endless macros and see if there's any ideas I can steal.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

it seems to me that this may be a good place for a recursive routine   :P

donkey

Quote from: dedndave on January 26, 2012, 05:41:37 PM
it seems to me that this may be a good place for a recursive routine   :P

Hi Dave,

Can't write one without recursion, at least I don't know of any way to handle parenthesis without a recursive routine. For qWord's stuff, I haven't had a chance to trace through it yet but it looks really good. I may add the ability to include full boolean mnemonics like OR and AND etc... since in my project it has to handle symbols anyway. Floating point is interesting but it won't be added for my current project though it is possible to add it later I guess.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

qWord

hi donkey,
there is no need to trace through my macros, because they don't do the same  as your code does: the macros create FPU-code at assembly time thus there is no runtime parsing of expressions.
f.e. fSlv y = x^2 produces:
fld x
fmul st,st
fstp y


FPU in a trice: SmplMath
It's that simple!

donkey

Hi qWord,

Ah, I see. I wouldn't have had time to look at it til the weekend anyway but since it doesn't do runtime parsing it is of little use to my current project which is an ASSERT macro for my debug tools. The example above doesn't have the symbol evaluation section in it but that is done, allowing the user to insert a data symbol from their program into the expression. For example this is already perfectly valid:

"25+[hInstance]+B[MyVariable]"

adds 25 to the value of hInstance and then adds the low order byte of MyVariable to the result. My hope is to allow statements like these:

ASSERT("[MyVariable]=1234")
ASSERT("W[MyVariable]+4=1234")
ASSERT("[MyVariable]=1+[hInstance]")

Where if TRUE it would allow the program to continue, if FALSE would throw an exception to the handler. A very complex but extremely useful debugging tool I would think. For this reason it can be simple parser that doesn't have to be overly feature rich, just basic math and the inclusion of symbols and registers. Haven't worked out how to get all the header symbols without writing a complete symbol table generator yet but that is something I can leave out if it becomes too cumbersome.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

are you writing a debugger, Edgar ?
or - just making a set of personal tools ?

donkey

Quote from: dedndave on January 27, 2012, 03:08:20 AM
are you writing a debugger, Edgar ?
or - just making a set of personal tools ?

Well, the debuging tools for RadAsm have most of my personal tools in them, there are only a few that are inherently unstable and too dangerous to allow neophites to play with so they're not included. The ASSERT function will be included once I can get the CONTEXT structure reliably. I may have to fault the program and use a debug handler to get it as I seem to have problems with the data when I create a thread to suspend the main thread then call GetThreadContext. It always comes out empty...

GetTheContext FRAME
LOCAL hProcess:D
LOCAL hPseudoThread:D
LOCAL hThread:D

pushad
invoke GetCurrentThread
mov [hPseudoThread],eax
invoke GetCurrentProcess
mov [hProcess],eax
invoke DuplicateHandle,[hProcess],[hPseudoThread],[hProcess],offset hThread,NULL,NULL,DUPLICATE_SAME_ACCESS
popad
invoke CreateThread,NULL,NULL,offset GetContextThread,[hThread],NULL,NULL
ret
endf

GetContextThread FRAME lpParameter
LOCAL hThread:D

mov eax,[lpParameter]
mov [hThread],eax

mov D[ctxt.ContextFlags],CONTEXT_ALL

// Get the thread context then exit
invoke SuspendThread,[hThread]
invoke GetThreadContext,[hThread],offset ctxt
invoke ResumeThread,[hThread]

invoke ExitThread,NULL
RET
ENDF


Not sure why, missing something obvious I suppose. Everything returns no error but the context structure (ctxt) is not filled.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Inserting a breakpoint (int 3) gets me reliable data, it looks like I'll have to use that method...

invoke AddVectoredExceptionHandler,1,offset ExcptHandler
push eax
int 3
pop eax
invoke RemoveVectoredExceptionHandler,eax

ExcptHandler FRAME pExcptPointers
uses ebx,edi,esi

mov edi,[pExcptPointers]
mov esi,[edi+EXCEPTION_POINTERS.ContextRecord] // Pointer to context structure
mov edi,[edi+EXCEPTION_POINTERS.ExceptionRecord] // Pointer to exception record

xor ebx,ebx
mov ebx,[edi+EXCEPTION_RECORD.ExceptionCode]
mov eax,[edi+EXCEPTION_RECORD.ExceptionAddress]

// Check for breakpoint
.EXCEPTION_BREAKPOINT
cmp ebx,EXCEPTION_BREAKPOINT
jne >>.UNHANDLED
// Jump past the INT3
inc D[esi+CONTEXT.Eip]
// Copy the context structure
mov edi,offset ctxt
mov ecx,SIZEOF CONTEXT
rep movsb
// Continue normal execution
mov eax,EXCEPTION_CONTINUE_EXECUTION
ret

.UNHANDLED
// Pass other exceptions to the next handler
mov eax,EXCEPTION_CONTINUE_SEARCH
ret
endf
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Well I decided it was easier and faster just to save the registers to an array before the call and restore them afterwards since I am only allowing the data registers to be used anyway. I have currently got it working to allow the following assert statements (still uses invoke, the final version will not):

Note that this isn't all the possible combinations, that would take a few pages but it gives you an idea:

invoke Assert,"[hInstance]" ; returns TRUE if non-zero
invoke Assert,"eax=15" ; returns TRUE if equal
invoke Assert,"eax!=15+4*(8+3)" ; returns TRUE if not equal
invoke Assert,"ebx+15<D[hInstance]-4" ; returns TRUE if less

At any rate I just have to clean up the code then convert it to something my debug library can use. Should end up being a great tool.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Here's the assert version for now, still have to stress test it and reduce the code size, at nearly 1700 lines its has quite a few candidates for reduction. However, it appears to work OK and once the project is complete and a 64 bit version is done I will be adding an ASSERT macro to my debug tools for RadAsm (x32 only for MASM, x32 and x64 for GoAsm). The functions require a debug build (after all this is a debug tool) in order to extract the symbol information, for GoAsm it requires a DBG file, for MASM a PDB file (this version is not compatible with MASM, the final LIB will be). ASSERT will have a separate library and header since it is so large I don't want to add it to the main tools, preferring to allow the user to select it if they want.

For what its worth, here's the ASSERT test program:

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

I have built the Assert32 library, compatible with MASM and GoAsm and uploaded it to the RadAsm forum

http://www.masm32.com/board/index.php?topic=16317.msg153886#msg153886

There were a few bugs in the debug library as well as in the debug32.a file for GoAsm and MASM so they are fixed and included in the upload.

No 64 bit version yet.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable