News:

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

Experimental macro.

Started by hutch--, October 17, 2009, 01:03:21 PM

Previous topic - Next topic

hutch--

I thought someone may like this one. I am trying to simplify a template for a dialog code design as it makes the code generator easier to write when you don't have to make multiple entries for the same value. The example is for setting a global scope handle to the return value of an API call but the general idea for global handles looks like it will be useful for writing simpler cleaner code.


  ;; -------------------------------------------------------
  ;; Use this macro as follows.
  ;; UniqueHandle = SetGlobalHandle(ParentHandle,Control_ID)
  ;; EXAMPLE : hButton1 = SetGlobalHandle(hWin,250)
  ;;
  ;; NOTE that the unique handle is created in the .DATA? section
  ;; by the MACRO, do NOT create a LOCAL or GLOBAL value for
  ;; this handle or you will get s "symbol redefinition" error.
  ;; -------------------------------------------------------

    SetGlobalHandle MACRO hParent, ctlID
      LOCAL hndl
      .data?
        hndl dd ?
      .code
        invoke GetDlgItem,hParent,ctlID
        mov hndl, eax
      EXITM < hndl>
    ENDM

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


This one looks even more useful.


    gh MACRO args:VARARG
      LOCAL hndl
      .data?
        hndl dd ?
      .code
        invoke args
        mov hndl, eax
      EXITM < hndl>
    ENDM


It makes general purpose global handles available to any API/function that returns a value that you want in the .DATA? section.


    hInstance = gh(GetModuleHandle, NULL)
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Hutch,
Interesting stuff. I am still trying to figure out what exactly it does: in the disassembly below, the middle assignment does not appear, i.e. the hInstance = 12345678 gets treated like any other assembly time constant definition. But the other two do assign runtime values... ::)

include \masm32\include\masm32rt.inc

    gh MACRO args:VARARG
      LOCAL hndl
      .data?
        hndl dd ?
      .code
        invoke args
        mov hndl, eax
      EXITM < hndl>
    ENDM

.code
AppName db "Masm32:", 0

start:
; int 3
hInstance = gh(GetModuleHandle, NULL)
nop
hInstance = 12345678
nop
hInstance = gh(GetTickCount)

MsgBox 0, str$(hInstance), str$(rv(GetTickCount)), MB_OK
exit

end start


CPU Disasm
Address    Hex dump          Command                               Comments
00401009   ³. 6A 00          push 0                                ; ÚModuleName = NULL
0040100B   ³. E8 BC000000    call <jmp.&kernel32.GetModuleHandleA> ; ÀKERNEL32.GetModuleHandleA
00401010   ³. A3 F0204000    mov dword ptr [NewWin32.4020F0], eax
00401015   ³. 90             nop                                   ; ÚType => MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
00401016   ³? 90             nop                                   ; ³
00401017   ³. E8 B6000000    call <jmp.&kernel32.GetTickCount>     ; ³Caption = ""FF,"%",88," @"
0040101C   ³. A3 F4204000    mov dword ptr [NewWin32.4020F4], eax  ; ³Text => ""

qWord

At compiletime 'hndl' gets replaced by something like ??0012 - this is then assigned to the  assembly constant: hInstance=??0012
FPU in a trice: SmplMath
It's that simple!

hutch--

Having played with this idea for a while I have reverted back to the form that uses the MASM "EQU" notation because it provides an error message when a duplicate ID is use. You can redefine a value set with the " = " notation where an "EQU" cannot. This is the macro form that I will propbably use.


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

    IFNDEF cgv
      cgv MACRO args:VARARG       ;; create GLOBAL value
        LOCAL hndl
        .data?
          hndl dd ?
        .code
          invoke args
          mov hndl, eax
        EXITM < equ <hndl>>
      ENDM
    ENDIF

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



The IFNDEF is purely so I can add the macro to macros.asm later without duplicates.

In terms of usage the difference is very slight, you use no " = " in this form.


    hInstance cgv(GetModuleHandle, NULL)


The way it works is reasonably simple, The .DATA? section items are known at assembly time and effectively what the macro is doing is runnig the function/API/procedure call in the normal manner, writing the return value to the .DATA? section entry then setting an equate for the .DATA? section entry to a name.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php