May 15, 2024, 01:12:20 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


RPNToAsm

Started by WayneA, June 22, 2010, 01:38:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

WayneA

Dim a$[120000] As IString
If RPNToAsm("2 [ebp+8] *",a$) Then
Print a$
WaitCon
End
EndIf

Sub RPNToAsm(equation As String,asm As String),Int
Dim i,x=FieldCount(equation," ") As Int
Dim cmd="" As String
asm=""
For i=1 to x
cmd=NthField(equation," ",i)
If InStr("+-*/",cmd) And Len(cmd)=1 Then
asm+="\t\tpop dword eax\n\t\tpop dword ebx\n"
Select cmd
Case "+"
asm+="\t\tadd dword eax,ebx\n"
Case "-"
asm+="\t\tsub dword eax,ebx\n"
Case "*"
asm+="\t\timul dword eax,ebx\n"
Case "/"
asm+="\t\tcdq\n\t\tidiv dword ebx\n"
EndSelect
asm+="\t\tpush dword eax\n"
ElseIf Val(cmd)<>0 Or InStr(cmd,"0") Or InStr(cmd,"[ebp+") Then
If Left$(cmd,5)="[ebp+" And Right$(cmd,1)="]" Then
asm+="\t\tpush dword "+cmd+"\n"
Else
asm+="\t\tpush dword "+LTrim$(Str$(Val(cmd)))+"\n"
EndIf
EndIf
Next i
If Len(asm) Then
asm="Sub Math(...),Int\n\tDim ret As Int\n\t_asm\n"+asm+"\t\tpop dword eax\n\t\tmov dword [ebp-4],eax"+_
"\n\t_endasm\n\tReturn ret\nEndSub"
Return True
EndIf
Return False
EndSub

Sub NthField(source As String,delimiter As String,fieldnumber As Int),String
Dim delpos,nexpos,count As Int
count=1
delpos=0
nexpos=InStr(source,delimiter)
While nexpos
If count=fieldnumber Then
If count=1 Then delpos=1-Len(delimiter)
Return Mid$(source,delpos+Len(delimiter),nexpos-delpos-Len(delimiter))
Else
delpos=nexpos
nexpos=InStr(source,delimiter,delpos+1)
count++
End If
Wend
Return Mid$(source,delpos+Len(delimiter))
EndSub

Sub FieldCount(source As String,test As String),Int
Dim delpos,nexpos,count As Int
count=0
delpos=0
nexpos=InStr(source,test)
While nexpos
delpos=nexpos
nexpos=InStr(source,test,delpos+1)
count++
Wend
Return count+1
EndSub


This generates a sub with inline assembly that will return the integer result of an Reverse Polish Notation equation.

The pushing/popping is inefficient, so this isn't going to produce code that is in anyway superior to just do the math in ebasic. This was a "I'm bored" kinda project. I expected it to take much longer than it did. It took about 5 minutes to produce the first version, so I added the ability to reference variables on the stack ([ebp+8] ect) so you can have it generate useful functions, rather than just calculating the answer to a static problem.

Next is the infix->rpn converter. That'll probably take more than 5 minutes. ;)
99 little bugs in the code,
99 bugs in the code,
Fix one bug,
Compile again,
104 little bugs in the code...

All code I post is in the public domain.