News:

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

accessing elements of arrays

Started by bigrichlegend, July 11, 2007, 09:42:53 PM

Previous topic - Next topic

bigrichlegend

Can anyone help me in understanding how this code is able to access the correct elements of the arrays?

;;
;;   MAIN WINDOW MESSAGES
;;

          CONST
   ALIGN   4
   
MainMsg   DD   WM_COMMAND,\
      WM_WINDOWPOSCHANGED,\
      WM_PAINT,\
      WM_CREATE, WM_CLOSE, WM_DESTROY
MainM DD MainWM_COMMAND,\                                                   {THIS UP HERE}
       MainWM_WINDOWPOSCHANGED,\                   
       MainWM_PAINT,\                               
       MainWM_CREATE, MainWM_CLOSE, MainWM_DESTROY 
   

   CODE
   ALIGN   4
MainWND:
   FRAME   hWnd, uMsg, wParam, lParam
   USES   ebx,esi,edi

;IF message is not found
   mov   eax,[uMsg]
   mov   edi,ADDR MainMsg
   mov   ecx,SIZEOF(MainMsg)/4
   repne scasd
   je   >.Process

;THEN let DefWindowProc handle this message

.Default
   push   [lParam]            ;lParam   
   push   [wParam]            ;wParam   
   push   [uMsg]            ;Msg     
   push   [hWnd]            ;hWnd   
   call   [DefWindowProc]   ;User32   

   jmp   >.Return

;ELSE process this message possibly setting carry flag for default processing

   ALIGN   4
.Process
   call   D[edi+SIZEOF(MainMsg)-4] ;                       {HOW DOES THIS ACCESS}
   jc   <.Default
.Return
   ret
   ENDF

jorgon

Hi bigrichlegend, welcome to the forum!

Assuming the code you have posted actually does work, it looks as though prior to the repne scasd instruction the address of the MainMsg table is given to edi.  This table contains the message constants which must be somewhere else in the file or in an include file.  Repne scasd will return zero (zero flag set) if it found the correct message, not zero if it didn't.

If it found the correct message, the code jumps down to .Process where the call is made to the function to process the message (the function will be elsewhere in the code).
At the time of the call, edi holds the address in the MainMsg where the message was found by repne scasd, plus 4 bytes.  The extra 4 bytes is because the scasd instruction moves four bytes at a time even if it is about to return zero.  So the 4 bytes are removed in the call instruction using "-4".  And to get to the second table (holding the addresses of the functions) it's necessary to move edi over the first table.  This is done by adding the size of the first table using "+SIZEOF(MainMsg)". 

The second table holds the addresses of the functions to process the correct message in exactly the same sequence as the first table.

Personally I find it easier to make the tables if you have only one table (not split into two) as in the GoAsm HelloWorld examples.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

bigrichlegend

Thanks for the assist. It makes more sense now!. However, I was of the opinion that to access an element in an array one would use this approach

Element_Address = [Base_Address + index * Element_Size]
                         = [edi               + value returned by scasd - 4]

Base_Address would be [ADDR MainMsg] in edi.

wjr

That looks familiar :bg with a sensible description above :U... the label MainM is required for SIZEOF to do its thing (in this case with two tables) but is not used elsewhere in the code as may have been expected.

The opinion is still good and could be used if you set up your own loop to scan through the table(s) (as in the GoAsm HelloWorld examples). It just doesn't apply to the way repne scasd processes by advancing from the base address with increases (in this case) to edi, using ecx as a count rather than an index.