News:

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

Runtime conditionals

Started by donkey, March 24, 2009, 11:15:42 AM

Previous topic - Next topic

jorgon

No it doesn't.

Please give me a full window procedure example for me to look at.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

mitchi

Why are you always coming back to the Windows procedure? That's something you have to write once in your app.
IF/ELSE are used everywhere.

jorgon

Ok well that's my first bullet point.

1. Is it true that switches might be useful everywhere?

2. If you give the answer "yes" please prove this by giving an example of a CMP JMP switch, compared with a high level switch so I can see whether it looks any better.

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

donkey

Here's an example of a couple of things from TBPaint. It is a block of nested IF/ENDIF comparisons involving EAX whose value is changing within the block making it impractical for SWITCH CASE, it contains just simple comparisons however there are many routines that contain multiple comparisons per IF operator however due to time constraints I did not translate them to GoAsm...

cmp D[SkipQuery],0
jne >>.ELSE
cmp eax,[imageX]
je >>.ELSE
invoke MsgBox,[hDlg],OFFSET szDiffSize,NULL,MB_OKCANCEL,IDI_WARNING
cmp eax,IDOK
jne >
invoke ResetSize,[bmp.bmHeight],[bmp.bmHeight]
jmp >>.ENDBLOCK
:
invoke DeleteObject, [hBmp]
mov eax,-1
ret
.ELSE
invoke ResetSize, [bmp.bmHeight], [bmp.bmHeight]
.ENDBLOCK

mov eax,bmp.bmHeight
.IF SkipQuery == FALSE
.IF eax != imageX
invoke MsgBox,hDlg,OFFSET szDiffSize,NULL,MB_OKCANCEL,IDI_WARNING
.IF eax == IDOK
invoke ResetSize,bmp.bmHeight,bmp.bmHeight
.ELSE
invoke DeleteObject,hBmp
mov eax,-1
ret
.ENDIF
.ENDIF
.ELSE
invoke ResetSize,bmp.bmHeight,bmp.bmHeight
.ENDIF


The MASM code with the IF/ENDIF blocks is much easier to read and the purpose and destinations of the jumps are more evident. This is not in a window procedure, it is part of a large procedure that contains many such switches some much more complex than this one.

Note that this translation was done on the fly and isn't tested so I'm not sure its accurate.
"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

mitchi

Quote from: jorgon on May 18, 2009, 04:13:52 PM
Ok well that's my first bullet point.

1. Is it true that switches might be useful everywhere?

2. If you give the answer "yes" please prove this by giving an example of a CMP JMP switch, compared with a high level switch so I can see whether it looks any better.



1. Well yes they are used everywhere. Whenever you need  IF/ELSEIF/ELSE/ LOGIC in your code you can use them. It's common programming logic and these blocks add more readability. Even if you don't believe this, you'll just have to trust me on that :D

2. I'll just use Donkey's answer  :green

By the way, in the way that GoAsm was programmed, is adding IF/ELSEIF/ELSE/  a difficult task?

BlackVortex

Yeah, if/elseif is very useful and simplifies coding, improves readability  without taking away any of asm's power and flexibility.  Sometimes I've looked at masm's results in a disassembler and the produced assembly looks fine.

Also, some of us are here because ml64 sucks bad (no invoke,no if/elseif anymore !) and we need a good winAPI-oriented assembler for the 64bit future, like goasm.

I've checked all(?) other 64bit capable assemblers and I didn't like their syntax or they are too OS-abstract.

Ramon Sala

What about this?

MyWndProc FRAME hWnd, uMsg, wParam, lParam
   IF uMsg == WM_CREATE
      ;Write code here

   ELSEIF uMsg == WM_COMMAND
      ;Write code here

   ELSEIF uMsg == WM_DESTROY
      ;Write code here

   ENDIF
   INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
   RET
ENDF


All messages might have a RET sentence for no further processing. If not, the 'DeWindowProc' function would be called instead.

Greetings from Catalonia

Mark Jones

Jeremy, first let me say that I love GoASM. It is powerful and concise. However, while the "raw-ness" of coding conditional jumps by hand sometimes provides additional flexibility or capability, I find modifying large conditional blocks to be very unweildy. Take something like this for instance:

Tab1Proc FRAME hWin,uMsg,wParam,lParam
mov eax,d[uMsg]
cmp eax,WM_INITDIALOG
jne >>.WM_CREATE
; Put code in here....................
jmp >>.EXIT

.WM_CREATE
cmp eax,WM_CREATE
jne >>.WM_COMMAND
;
jmp >>.EXIT

.WM_COMMAND
cmp eax,WM_COMMAND
jne >>.WM_DESTROY
;
jmp >>.EXIT

.WM_DESTROY
cmp eax,WM_DESTROY
jne >>.DEFAULT
;

.DEFAULT
mov eax,FALSE
ret
.EXIT
mov eax,TRUE
ret
ENDF


Now say one wanted to add another "switch" to this, in the middle somewhere, for say WM_PAINT. The current process requires defining a new local jump ".LABEL", renaming the previous jump destination to this new label, creating the new conditon test code, and creating the code to jump to the next label. Move this block out-of-order or make a mistake in any jump targets and presto: a hard-to-spot bug. Often, if the order has to be completely changed, it is simpler and faster just to code a new WndProc rather than try to fixup all the jumps.

I can't speak for anyone else, but when I'm juggling a hundred other things in my head during program creation, it sure would be simpler and shorter to type something like this:

Tab1Proc FRAME hWin,uMsg,wParam,lParam
switch d[uMsg]
case WM_INITDIALOG
; Put code in here....................
case WM_CREATE
;
; whoa, we need to process paint messages now! new condition here:
case WM_PAINT
;
case WM_COMMAND
;
case WM_DESTROY
;
default
mov eax,FALSE
ret
endsw
mov eax,TRUE
ret
ENDF


Although, I do agree that conditionals have a limited application---mostly in window procedures, but they also could be very handy in code such as this for rapid development. A ton of conditionals are used in that code and it really helps to speed up development. After the code is working, then care can be taken to optimize specific jumps, if necessary. I would wager that the vast majority of us know not to use HLL-conditionals in a speed-critical algorithm.

Alas, on the other hand, I agree that GoASM should not be turned into Turbo-Basic-On-Crack. :P However again, as long as any conditional syntax remained completely optional and transparent, then the die-hard tape-punchers out there should remain happily indifferent, or at least not moan very much. :bg
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

jorgon

Ok I do see that GoAsm would be improved by the addition of both IF/ELSE/ENDIF and SWITCH/CASE.
My concern about IF/ELSE/ENDIF being confused with #IF/#ELSE/#ENDIF has been dispelled by this debate.  I was also hoping that one syntax form might replace both IF/ELSE/ENDIF and SWITCH/CASE, or that we might find a better syntax but despite your efforts this didn't happen.
Having switched my view, I'm on the case, but give me a while and in the end it will be done (sorry, puns intended).
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

ecube

This is good, While my preprocessor seems to work well and gives the flexibility of changing the syntax when you like, the extra temp files generated is kind of annoying, and it'll be nice to have this support built right in.

jj2007

Quote from: jorgon on May 24, 2009, 07:12:42 AM
Having switched my view, I'm on the case, but give me a while and in the end it will be done (sorry, puns intended).


Ambitious program! On [condition] Gosub proc1, proc2... ok, that one I understood. But what is done? ExitProcess?

:wink

BlackVortex

* BlackVortex dances around

:boohoo:                     :cheekygreen:

Mark Jones

Quote from: jorgon on May 24, 2009, 07:12:42 AM
My concern about IF/ELSE/ENDIF being confused with #IF/#ELSE/#ENDIF has been dispelled by this debate.  I was also hoping that one syntax form might replace both IF/ELSE/ENDIF and SWITCH/CASE, or that we might find a better syntax but despite your efforts this didn't happen.

Perhaps like (I believe Donkey) had said earlier, the simpler syntax is always easier to understand. I commend you on trying to find one unifying solution however. Since the header syntax is close to C's, it seems logical that the assemble-time variants would be prefixed by #'s i.e. #IF/#ELSE/#ENDIF/#SWITCH/#CASE etc. As for the run-time conditional syntax, that is still open to interpretation. The base functionality is the same regardless of what the instructions are called (IF==SWITCH, ELSEIF==CASE, ENDIF==ENDSW, etc.) :bg

"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

wjr

With IF confusion dispelled, between the two I would lean towards IF/ELSEIF/ELSE/ENDIF which has a slightly lower level feel to it (unsigned comparisons as the default... IFS/ELSEIFS/ELSE/ENDIF for signed?). With higher level language CASE variations and without the more advanced compiler-like output (giving functionality similar to IF) I would say that CASE does not fit in as well.

The repetition in Ramon Sala's IF/ELSE/ENDIF WndProc example a bit earlier stood out... in another unifying attempt, instead of the longer ELSEIF expecting a full expression, how about also having a shorter ELIF with just a VALUE, compared as in the initial IF (or possible previous longer ELSEIF):


MyWndProc FRAME hWnd, uMsg, wParam, lParam
    mov eax,[uMsg]
    IF eax == WM_CREATE
        ;Write code here

    ELIF WM_COMMAND
        ;Write code here

    ELIF WM_DESTROY
        ;Write code here

    ENDIF
    INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
    RET
ENDF


dedndave

the operators can be chosen for signed/unsigned
the if...endif can remain uniform