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

BlackVortex

How is the progress with this feature ?   :bg

Mark Jones

I was just wondering the same thing. :U
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

jorgon

I've put this on hold for the following reasons:-

1. Users seem to be developing a preprocessor to do this work so that they can use the syntax that they themselves prefer see http://www.masm32.com/board/index.php?topic=11180.0.
2. In my message of http://www.masm32.com/board/index.php?topic=11097.msg82753#msg82753 I identified a weakness in the proposed GoAsm syntax when it was put to practical use.  This has not been answered.  And I must say that looking at the code there, my personal view is that it merely confuses the switching further.
3. Only a limited number of people expressed a view about the preferred GoAsm syntax.
4. No clear consensus as to the GoAsm syntax has emerged in this debate.

We all have our personal preferences, and I give mine below (table window procedure).  It can be adapted easily into a dialog procedure, and also for people who like to use FRAME...ENDF.

If anyone can come up with a working, practical syntax clearer than this which gets general support, then of course I would be willing to consider adding it to GoAsm.

The Tabular Window Procedure
;******************** Window message table 
;          (in a real program this would deal with many more messages)
DATA
MESSAGES DD (ENDOF_MESSAGES-$-4)/8      ;=number to be done
         DD  1h,CREATE,2h,DESTROY,0Fh,PAINT
ENDOF_MESSAGES:         ;label used to work out how many messages
;******************************************
CODE
;
;********** this is a general window procedure which in an ordinary
;********** program deals with all messages sent to the window
GENERAL_WNDPROC:        ;eax can be used to convey information to the call
PUSH EBP                ;use ebp to avoid using eax which may hold information
MOV EBP,[ESP+10h]       ;uMsg
MOV ECX,[EDX]           ;get number of messages to do
ADD EDX,4               ;jump over size dword
L2:
DEC ECX
JS >L3
CMP [EDX+ECX*8],EBP     ;see if its the correct message
JNZ L2                  ;no
MOV EBP,ESP
PUSH ESP,EBX,EDI,ESI    ;save registers as required by Windows
ADD EBP,4               ;allow for the extra call to here
;now [EBP+8]=hwnd, [EBP+0Ch]=uMsg, [EBP+10h]=wParam, [EBP+14h]=lParam,
CALL [EDX+ECX*8+4]      ;call the correct procedure for the message
POP ESI,EDI,EBX,ESP
JNC >L4                 ;nc=return value in eax - don't call DefWindowProc
L3:
PUSH [ESP+18h],[ESP+18h],[ESP+18h],[ESP+18h]     ;allowing for change of ESP
CALL DefWindowProcW
L4:
POP EBP
RET
;
;*******************
CREATE:                 ;one of the few messages dealt with by this example
XOR EAX,EAX             ;return zero to make window
RET
;
DESTROY:                ;one of the few messages dealt with by this example
PUSH 0
CALL PostQuitMessage    ;exit via the message loop
STC                     ;go to DefWindowProc too
RET
;
;******************* This is the actual window procedure
MyWndProc:
MOV EDX,ADDR MESSAGES   ;give edx the list of messages to deal with
CALL GENERAL_WNDPROC    ;call the generic message handler
RET 10h                 ;restore the stack as required by caller
;
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

BlackVortex

@ Jeremy
You must have an integrated de-obfuscator chip in your brain   :green2  When I look at your code sample I get lost in the "asm woods".

If it had some sort of if/elseif or switch/case to get rid of the labels and nice indentation, also in Radasm with syntax colour highliting, it would be the way I like to program, hehe !

jorgon

#79
QuoteYou must have an integrated de-obfuscator chip in your brain     When I look at your code sample I get lost in the "asm woods".

You don't need to understad how GENERAL_WNDPROC works.  That is the same in every program.  A bit like a macro.  You don't change it (unless you want to use the dialog procedure version).  You just call it and it's there.  If you concentrate on the table of messages, the window procedure, and the calls that are made to suit each message (these are the bits which you would change) you can see that the coding is very simple.

I know you still want the switches. Please give an example of the syntax and we can see if it really is better than the above.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

wjr

If using 'familiar' syntax, perhaps best not to stray too far from that usage, as well as functioning. Some re-evaluating... C does not have ENDSWITCH, default: in C uses a colon, C#/J# require the break statement after case code, and with C/C++  the break statement is optional - when not used, after doing matching case code, execution falls through to test the remaining cases which, in our case, can cause a problem if a register is used for switch and then modified within the matched case code (with further register care required when nesting).

Continuing along the lines of  'familiar' yet similar syntax, SELECT...CASE from Visual Basic would seem more flexible with the added benefit of comparison operators (=, <>, <, <=, >, or >=) for near enough IF-like support (elseif equivalent requiring nested SELECT...CASE, register care still required when nesting):


SELECT eax
CASE 0
;
CASE 1 TO 4
;
CASE 5, 7, 9 TO 15, <100
;
CASE >=[MemCmp]
;
CASE ELSE
;
ENDSELECT


The above seems reasonable with some possible minor variations:
- I have omitted the Is keyword before comparison operators
- additional short form ENDSC, so as not to conflict with ENDS for ENDSTRUCT
- how about no EXIT SELECT, possibly due to .EXIT MASM directive, and really, if you can't jmp to a label, you shouldn't be using assembly language!
- the comparison operators bring in a bit of an unsigned (MASM default) vs. signed (HLL) conflict. Tempting to go the HLL route with this HLL syntax, otherwise we start to stray with something like
SELECT SIGNED eax or SCASE.

My personal preference would generally not involve the use of this higher level syntax. I do not find it better, especially in the case of a window procedure. Also, in contrast with HLL compilers which can attempt to optimise (ex. switch using tables), the code generated here will be 'basic' since the assembler programmer expects and retains control over register usage.

donkey

I believe that the standard IF/ELSEIF/ELSE/ENDIF blocks are the most intuitive to implement and they would get my vote. As for the syntax ambiguity, GoAsm uses a # (pound) prefix for any compile time conditionals and no prefix for runtime, that should stay the same. The rules governing valid comparisons should be the same as for the CMP instruction, this would eliminate the need for register appropriation. Multiple comparisons in a single line should be separated by boolean operators, for example

IF eax = 0 AND ecx < edx

ELSEIF [MemCmp] > edi OR [MemCmp] < 200

ELSE

ENDIF


This is not ambiguous, is english readable and most if not all GoAsm programmers are already familiar with the syntax.
"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

Ramon Sala

I also vote for IF/ELSEIF/ELSE/ENDIF.

Ramon
Greetings from Catalonia

mitchi

Agreed. Let's get these PRONTO  :bg

BlackVortex

select/case and if/elseif look good to me   :thumbu

donkey

Quote from: BlackVortex on May 17, 2009, 09:17:59 PM
select/case and if/elseif look good to me   :thumbu

Hi Black Vortex,

Lets just agree on IF/ENDIF, SELECT CASE and later be done with macros or preprocessors or maybe even added at a later time. For now though we need a consensus...
"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

GregL

Quote from: donkeyI believe that the standard IF/ELSEIF/ELSE/ENDIF blocks are the most intuitive to implement and they would get my vote.

The IF/ELSEIF/ELSE/ENDIF blocks would get my vote too.


PauloH

Quote from: donkey on May 17, 2009, 09:20:56 PM
Lets just agree on IF/ENDIF, SELECT CASE and later be done with macros or preprocessors or maybe even added at a later time. For now though we need a consensus...

I agree with this block and this is my vote too.

Kind regards,
PauloH

jorgon

This is all very well but no one has dealt with these issues:-


  • The main areas of assembler code which may be regarded as requiring simplification is the callback procedure (window, dialog, enum, DLL entry etc.).
  • The flow of execution in my practical example of this using switches in this message is not easy to follow at all.

Again, it is not clear to me (yet) that adding these switches makes anything simpler and clearer (this is why GoAsm exists).
Maybe someone can produce a new syntax to handle these callbacks which is simpler and clearer than CMP and JMP or other methods such as the tabular window procedure I referred to earlier.  If so, then I am happy to consider adding it to GoAsm, but without that it is pointless to do so and contrary to the principles behind GoAsm.



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

mitchi

Well to you it may not seem necessary because you're used to code without them. But for someone like me with a C background, It's more natural to use this structure when I code and when I think of my code.
I think it's also very readable and you don't have to type a label that is used once.
Did that convince you?  :green