News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

The Ultimate Message Loop

Started by Zen, May 21, 2014, 05:12:26 AM

Previous topic - Next topic

Zen

You guys are geniuses,...:dazzled:
What is the most reliable assembly language version of the standard windows application Message Loop ???
(I've been reading alot of source code lately from old examples, and, I've noticed an IMMENSE amount of variability.)
Zen

dedndave

in my "WinMain" routine, EDI is zero throughout much of the code

EDI = 0

;------------------------------

;message loop

        mov     esi,offset msg                          ;ESI = msg structure address
        jmp short mLoop1

mLoop0: INVOKE  TranslateMessage,esi
        INVOKE  DispatchMessage,esi

mLoop1: INVOKE  GetMessage,esi,edi,edi,edi
        inc     eax                                     ;exit only
        shr     eax,1                                   ;if 0 or -1
        jnz     mLoop0                                  ;otherwise, we loop

;------------------------------

;exit program

        INVOKE  ExitProcess,[esi].MSG.wParam

Will

Quote from: Zen on May 21, 2014, 05:12:26 AM
You guys are geniuses,...:dazzled:

The problem with people who consider themselves geniuses is that some of them have too big an ego sometimes. Take hutch for example. He thinks he is so smart that anything ever written in DOS isn't worth even looking at. He thinks that anything written in DOS should be trash canned. He hasn't looked at ADAM and thinks it should be trash canned because it was written back in the early 1980s when DOS and the 8088 processor were state of the art.  he moved my project of converting ADAM to MASM32 to the DOS section of this forum so few of you will look at it. I guess, because DOS programs aren't worth upgrading. I'm attaching Pro Football Prophet in the version that will run on Window 7. I have a better version but, rather than fix bugs that were in earlier versions of DOS emulation, Microsoft did away with "Full Screen Mode" so that version won't run on Windows 7.  I defy hutch to write a system that will do as much as Pro Football Prophet will do. It's attached here. (It still has problems running on laptops but I intend to fix those before this NFL football season starts.)

hutch--

Will, this is your first and last warning, try and start an argument in here and you will be given the opportunity to explore Win32 assembler programming in another venue.

jj2007

Quote from: Will on May 21, 2014, 10:13:11 AMThe problem with people who consider themselves geniuses is that some of them have too big an ego sometimes.

Yes, we have all seen the bloated ego over the last weeks. Another problem is that people who consider themselves geniuses are sometimes real idiots.

On topic:

  .While 1
       invoke GetMessage, ADDR msg, NULL, 0, 0
       .Break .if !eax
       invoke TranslateMessage, ADDR msg
       invoke DispatchMessage, ADDR msg
  .Endw


This works - I've never seen it fail. However, occasionally you see

.Break .if sdword ptr eax<=0

instead, claiming that eax will be negative in case of an error. The official MSDN version is this:

    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    {
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    // Return the exit code to the system.

    return msg.wParam;


If you want to be on the safe side, check for zero and -1:

  .While 1
      lea edi, msg      ; -6 bytes
      xor eax, eax      ; -1 - tribute to Dave ;-)
      invoke GetMessage, edi, eax, eax, eax
      inc eax
      .Break .if Zero?      ; an error
      dec eax
      .Break .if Zero?      ; normal exit
      invoke TranslateMessage, edi
      invoke DispatchMessage, edi
  .Endw


P.S.: Dave's shr eax, 1 thing is actually one byte shorter :(

dedndave


sinsi

When will GetMessage return -1?

Quote from: Raymond Chen
But don't worry, the standard message pump is safe. If your parameters are exactly
•a valid pointer to a valid MSG structure,
•a null window handle,
•no starting message range filter,
•no ending message range filter,

then Get­Message will not fail with -1.

MichaelW

According to my PSDK:
Quote
If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer.
Well Microsoft, here's another nice mess you've gotten us into.

hutch--

This is why I have never taken any notice of the potential -1 return value, if your code is correct, it never happens. If your code is not correct, fix it.

farrier

Well, if we're going for "Ultimate":

.while TRUE
invoke GetMessage, msg, NULL, 0, 0
.if eax, e, 0
jmp @f
.endif
invoke TranslateAccelerator, [gWnd], [hAccel], msg
.if eax, e, 0
invoke IsDialogMessage, [gWnd], msg
.if eax, e, 0
invoke TranslateMessage, msg
invoke DispatchMessage, msg
.endif
.endif
.endw
@@:
mov     eax, [msg.wParam]


TranslateAccelerator handles keyboard shortcuts, I almost always use them!

IsDialogMessage allows special handling of keystrokes--Enter, Tab, ...--in Dialogs, and special handling of keystrokes for buttons, lists, etc which are part of "Regular" windows.

The code is fasm syntax!  That's why things look a little different.  My only assembler.

hth,

farrier

For the code is dark, and full of errors!
It's a good day to code!
Don't Bogart that code, my friend!

dedndave

well - he wanted "ultimate standard"   :lol:

so, i didn't put the accelerator stuff in there
but, here's the one i use for MDI windows with accelerators

;EBX = hwndFrame
;ESI = hwndClient
;EDI = 0

;----------------------------------------

;message loop

        mov     ebp,offset msg                              ;EBP = address of MSG structure
        jmp short mLoop1

mLoop0: INVOKE  TranslateMDISysAccel,esi,ebp
        or      eax,eax
        jnz     mLoop1

        INVOKE  TranslateAccelerator,ebx,haccelMain,ebp
        or      eax,eax
        jnz     mLoop1
   
        INVOKE  TranslateMessage,ebp
        INVOKE  DispatchMessage,ebp

mLoop1: INVOKE  GetMessage,ebp,edi,edi,edi
        inc     eax                                         ;exit only
        shr     eax,1                                       ;if 0 or -1
        jnz     mLoop0

;----------------------------------------

;terminate

        INVOKE  ExitProcess,[ebp].MSG.wParam


the message loop is not a great place for .if or .while
it's one of the places i still prefer the old label method

Gunther

Dave,

Quote from: dedndave on May 22, 2014, 02:18:32 AM
the message loop is not a great place for .if or .while
it's one of the places i still prefer the old label method

good solution.  :t

Gunther
You have to know the facts before you can distort them.

dedndave

some guys (Hutch is one of them) like to place the MSG structure on the WinMain stack frame
that doesn't make any sense, to me - lol

the stack frame is a great place for data that is both temporary and private
WinMain is not what i consider temporary
it has the same longevity as the instance of the process

i.e., you may as well put the MSG structure in the .DATA? section
it doesn't use or save any memory over the stack frame method
it doesn't make the EXE any larger (slightly smaller, perhaps - no stack frame code)
memory consumption is memory consumption, whether it's on the stack or in the uninitialized data section

that having been said, by not using a stack frame in WinMain, you can use EBP as a preserved general register   :t

Zen

...Definitely geniuses,...Thanks alot to everyone :biggrin:
This is the Message Loop that I use in every assembly program,...it's the super-deluxe version (that I undoubtedly highjacked from an Australian assembly geek),...the best feature is that it IS IMPERVIOUS TO SYSTEM ERRORS,...

.WHILE TRUE
invoke GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
        .ENDW
mov     eax, msg.wParam
RET


...The only thing that really mystified me was the possible return of -1 from GetMessage, which was explained in Raymond Chen's blog post (thanks, SINSI),...I probably shouldn't have titled the original post "ultimate message loop",...what I was REALLY looking for was a message loop that is both mindlessly simple and completely foolproof,...(to, say,..."zen-optimization"),... :icon_cool:
Zen

jj2007

Quote from: dedndave on May 22, 2014, 03:28:04 AMby not using a stack frame in WinMain, you can use EBP as a preserved general register   :t

What exactly is the problem?

WinMain proc
LOCAL msg:MSG
..
  lea edi, msg   ; -6 bytes
  .While 1
          xor ebp, ebp   ; another tribute to Dave ;-)
          xor eax, eax
          invoke GetMessage, edi, eax, eax, eax
          inc eax
          shr     eax,1   ; DednDave, -1
          .Break .if Zero?   ; an error
          invoke TranslateMessage, edi
          invoke DispatchMessage, edi
  .Endw