News:

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

GoAsm 0.56.03a macro/define parameter bugs

Started by eilenbeb, March 26, 2007, 12:16:07 AM

Previous topic - Next topic

eilenbeb

if a macro is passed a parameter including an underscore or an OR then the macro will fail in some cases.

Following is a 'macro' used to call DirectX interfaces: (I am typing this so ignore typos)
(also i am omitting the line-continuation character \ and repetitive #if-#endif)

invd3(%o,%p,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l) =
    #if ARGCOUNT == 14
    push %l
    #endif
    #if ARGCOUNT >= 13
    push %k
    #endif
        |
        |
    #if ARGCOUNT >= 3
    push %a
    #endif
    mov eax,[%o]
    push eax
    mov eax,[eax]
    call [eax+%p]

the first bug i found occurred when i did this:
inv3d (pD3DD,IDirect3DDevice9_Clear,0,0,D3DCLEAR_TARGET OR D3DCLEAR_ZBUFFER,BakColor,1.0,0)
DirectX simply crashed.  Wasn't pushing the right values.

to fix it, i did this:
CLEARCODE   EQU D3DCLEAR_TARGET OR D3DCLEAR_ZBUFFER
inv3d (pD3DD,IDirect3DDevice9_Clear,0,0,CLEARCODE,BakColor,1.0,0)

The next bug ocurred when i tried this:
inv3d (pD3DD,IDirect3DDevice9_SetTextureStageState,0,D3DTSS_COLOROP,D3DTOP_MODULATE)
inv3d (pD3DD,IDirect3DDevice9_SetTextureStageState,0,D3DTSS_COLORARG1,D3DTA_TEXTURE)
inv3d (pD3DD,IDirect3DDevice9_SetTextureStageState,0,D3DTSS_,COLORARG1,D3DTA_DIFFUSE)
inv3d (pD3DD,IDirect3DDevice9_SetTextureStageState,0,D3DTSS_ALPHAOP,D3DTOP_DISABLE)
No matter which order I placed these four lines in, GoAsm would stop --ON THE THIRD LINE-- with the error
    "Too many arguments when using structure or union"

D3DTSS_COLOROP and th others are defined simply as hex values.  No nesting or ORing.

The only solution i have found for this problem was to replace the defines with actual numbers like this:
inv3d (pD3DD,IDirect3DDevice9_SetTextureStageState,0,1,4)

i have also defined the inv3d macro using MACRO-ENDM.  Bugs remained.
The only thing I can think of is that the macros are too close together and GoAsm isn't clearing its macro argcount after each instance.  But then i look at my paint proc and I have 5 inv3d's back to back with no problems.
However, none of those 5 calls have any underscores in the parameter list.
Other 3d calls in my code use defined parameters with underscores (like D3DFMT_A8R8G8B8) with no problems.

Any thoughts on this?

jorgon

eilenbeb

Thanks for the bug reports.
I'll look into these and come back to you.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

jorgon

eilenbeb

I have tried to replicate both of your bugs without success.

This is an unusual situation, because normally I would be able to use the source posted by a user and the bug also happens to me.

Since neither bug happened to me, I suspect that there could well be something earlier in your source which has thrown out GoAsm.  The most likely thing in the light of the errors you reported would be that GoAsm has entered a nest of definitions or structures earlier in your source and thinks it is still in the nest when the source code which you have posted was assembled.

To analyse this I shall therefore need to look at more of your source so that I can replicate the bug myself and work from there.  Sorry to have to ask you therefore, either to pair down your source whilst maintaining the bug, or alternatively send me all of your source so that I can have a look at it, including all include files so that it can be assembled discretely my end.  I appreciate that you may be reluctant to do the latter if you are making a commercial program, but you can send it to me privately at the email address which appears on the command line when you run GoAsm, on a confidential basis of course.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

eilenbeb

Thanks for the reply.
I'll fine-tooth all the files and try some more experiments, see what i can find.  I'll post back tonight or in the morning.
laters,
b

eilenbeb

Ok here it is:  a single-file assembly that demonstrates the first bug.
The second bug is probably very much related, so let's just deal with this one for now.

I have taken a defined parameter, D3DFORMAT_X8R8G8B8, and defined two others,
D3DFORMAT_X8R8 and D3DFORMAT_B8G8, that when OR'd together are equivalent to the first.

Then i make two identical macro-calls, one using the first equate and the second using the OR.
I have included in my source the debugger listing for each call, and the bug becomes obvious.

Here's the file:
; -------------------------------------------------------------------------

inv3d(%o,%p,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k,%l) MACRO
            #if ARGCOUNT == 14
            PUSH %l
            #endif
            #if ARGCOUNT >= 13
            PUSH %k
            #endif
            #if ARGCOUNT >= 12
            PUSH %j
            #endif
            #if ARGCOUNT >= 11
            PUSH %i
            #endif
            #if ARGCOUNT >= 10
            PUSH %h
            #endif
            #if ARGCOUNT >= 9
            PUSH %g
            #endif
            #if ARGCOUNT >= 8
            PUSH %f
            #endif
            #if ARGCOUNT >= 7
            PUSH %e
            #endif
            #if ARGCOUNT >= 6
            PUSH %d
            #endif
            #if ARGCOUNT >= 5
            PUSH %c
            #endif
            #if ARGCOUNT >= 4
            PUSH %b
            #endif
            #if ARGCOUNT >= 3
            PUSH %a
            #endif
            mov eax,[%o]
            push eax
            mov eax,[eax]
            call [eax+%p]
ENDM

Direct3DCreate9                 EQU d3d9:Direct3DCreate9
IDirect3D9_Release              EQU 8
IDirect3D9_GetAdapterModeCount  EQU 24
; #########################################################################

D3DFMT_X8R8G8B8 EQU 16h     ;       TAKE NOTE OF THESE!  I HAVE SPLIT THE FORMAT
D3DFMT_X8R8     EQU 10h     ;       INTO SEPARATE VALUES TO BE COMBINED USING
D3DFMT_G8B8     EQU 06h     ;       THE -OR- OPERATOR AS A MACRO PARAMETER!

; #########################################################################
.data
    pD3D    dd 0

; -------------------------------------------------------------------------
.code

start:

    invoke Direct3DCreate9,31
    mov [pD3D],eax

    inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8 OR D3DFMT_G8B8)
        ;
        ;   WHAT SHOWS UP IN THE DEBUGGER
        ;
        ;       PUSH    0
        ;       MOV     EAX, DWORD PTR [00402000]    ([pD3D])
        ;       PUSH    EAX
        ;       MOV     EAX, DWORD PTR [EAX]
        ;       CALL    [EAX+18]
        ;

    inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
        ;
        ;   WHAT SHOWS UP IN THE DEBUGGER
        ;
        ;       PUSH    16
        ;       PUSH    0
        ;       MOV     EAX, DWORD PTR [00402000]    ([pD3D])
        ;       PUSH    EAX
        ;       MOV     EAX, DWORD PTR [EAX]
        ;       CALL    [EAX+18]
        ;

    inv3d (pD3D,IDirect3D9_Release)

    invoke kernel32:ExitProcess,0

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

eilenbeb

Updates:

Underscores are irrelevant.  Sorry for not investigating further before my postings.
by replacing ---PUSH %k--- with ---PUSH (%k)--- in my inv3 macro, the above problem went away.  Proper values being pushed.

Now the second bug I mentioned in my original post, it's still there. 
I have modded the macro to echo the method name and ARGCOUNT at every push.
Every inv3d in my code is now pushing the correct parameters, and ARGCOUNT is correct.

As a precaution, I also removed all nested defines in my source and headers. Everything is now defined as a numeric value.
(All headers, not just D3D)
I also un-nested all structures.
This didn't help, but we know it's not a double-nesting problem.

After a day of experimenting, I have some new info on the error.
---It is directly related to passing defined values to macros.

---It only appears when my source is long enough (enough macro calls).
   My source is now exactly long enough to generate the error on the 2nd to last compiled macro call.

---I can move the error up through my source by replacing numbers in my macro-calls with defined values.
   I can move the error down through my source by replacing defined values with numbers or variables.

---I can eliminate the error by commenting-out any 1-3 macro-calls (moving the error past the end of them all).
   If I add another macro-call, it will have the error.
   The number of macro-calls commented is directly related to how many defined params in they use.

---The error is occurring before any echoing from the failed macro-call.

I also compiled using GoAsm 0.55.02 and got the same results.
I hope this helps.  Let me know if you need my source or any other info.
laters,
b


eilenbeb

Ok, I feel like I'm over-posting on this but I decided to post a file that demonstrates the problem.
GoAsm stops on the last GetAdapterModeCount with the error:
  Too many arguments when using structure or union
Hope this helps.

; -------------------------------------------------------------------------
inv3d(%o,%p,%a,%b) MACRO
            #if ARGCOUNT >= 4
            PUSH (%b)
            #endif
            #if ARGCOUNT >= 3
            PUSH (%a)
            #endif
            mov eax,[%o]
            push eax
            mov eax,[eax]
            call [eax+%p]
ENDM
; -------------------------------------------------------------------------
#define Direct3DCreate9                           d3d9:Direct3DCreate9
#define IDirect3D9_Release                       8
#define IDirect3D9_GetAdapterModeCount  24
#define D3DFMT_X8R8G8B8                      16h
; -------------------------------------------------------------------------
.data
    pD3D    dd 0
; -------------------------------------------------------------------------
.code
start:
    invoke Direct3DCreate9,31
    mov [pD3D],eax

inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)
inv3d (pD3D,IDirect3D9_GetAdapterModeCount,0,D3DFMT_X8R8G8B8)

    inv3d (pD3D,IDirect3D9_Release)

    invoke kernel32:ExitProcess,0
; -------------------------------------------------------------------------

jorgon

eilenbeb

Brilliant - you're a hero.

I've now got bug 2 on the run, and high hopes for bug 1.

Be back shortly.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

jorgon

eilenbeb

Thanks very much for all your hard work in isolating these bugs.  This certainly justifies a full report back to you.

Bug No. 1 (non-recognition of the first parameter if a parameter contained OR in main source script when using ARGCOUNT in the CoInvoke macro) was because in the particular circumstances ARGCOUNT was one short, so the first parameter was not being assembled.  ARGCOUNT was one short because when the arguments were being used, one of the commas separating the parameters was being written over.  One of the commas separating the parameters was being written over because when GoAsm found "OR" in the argument, it thought that brackets were needed to maintain the correct arithmetic priority and it was overwriting the comma with an opening bracket.  This would have been the correct action in the case of a straightforward arithmetical macro but it is not the correct action when the macro argument held parameters.  Stopping this happening corrected the error.  The reason why it didn't happen when you used your own brackets in the macro is that if there are already brackets in the macro GoAsm does not bother to add any more to maintain the correct arithmetic priority.  And the reason why I was unable to replicate this error was that I just tried a straightforward macro, not one using ARGCOUNT.

Bug No. 2 (consecutive macros with arguments overloading the argument buffer).  GoAsm copies arguments to a "safe place" (the argument buffer) so that they can be manipulated a little, prior to use.  Arguments applied to structures (overriding initialisations) are also put in there.  Bearing in mind that structures and also macros can be nested, GoAsm needs to know when the nest is finished (return to the text starting point) and at that point reset everything including resetting the start of the argument buffer.  GoAsm was doing this properly for structures but not for macros of the CoInvoke type.  Hence if there were a number of such macros in sequence with no intervening structures, the argument buffer would overload.  The error message was also a bit wrong since it referred only to structures and unions.  The reason why I was unable to replicate this error was that I worked only with your original source code, it needed more earlier macro calls for the overload to happen.

Whilst fixing these bugs I came across another one.  This was happening if a parameter given to a macro like the CoInvoke macro itself has brackets
eg. inv3d (pD3D,ID,0,10h+(D3DFMT_X8R8 OR D3DFMT_G8B8),0)
Here GoAsm was not counting or using the parameters properly, being put off by the extra brackets.

All these bugs are now fixed in this version of GoAsm (Version 56.03b).
Thanks again for pointing out these bugs and for your work on this.


[attachment deleted by admin]
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

eilenbeb

jorgon,

Very cool.  Thanks for the fix and the feedback, and I'm happy to have helped.
I got a certain measure of satisfaction seeing how accurate my assumptions were, so the full report was much appreciated.
GoAsm seems to be getting pretty solid, first rate job all around.

laters,
b