Guys,

This is a gas macro for calling functions without pushing all the PUSHes


.macro invoke func:req, args:vararg
    .irp arg, \args
        push \arg
    .endr
    call \func
.endm



But the problem is it can only push in the reverse order. I have explored all the gas assembler directives for something that can help reverse the arguments before pushing. Any ideas ?? I don't yet wanna explore M4 preprocessor option unless I'm sure that there is no way to accomplish this using gas macros.

Thank you
Posted on 2009-12-21 00:00:00 by uglyhunK
I'm not sure the macro engine is up to the task, we defeated a similar issue using MASM.

NASM IS NOT MATURE ENOUGH.

If it was, we'd all swing that way.
Posted on 2009-12-21 01:50:14 by Homer
uglyhunK,

GAS is not my area of expertise, so the following may be completely wrong:

Try to reverse arguments list yourself: .irp through it and collect them backward, i.e. something like this:

.irp arg, \args
    .ifdef reversed_args
        .equ reversed_args, \arg , \reversed_args
    .else
        .equ reversed_args, \arg
    .endif
.endr


reversed_args should be local to macro (or undefined beforehand).

This trick is depends on whether .equ evaluates symbols in expression being assigned to symbol.
Posted on 2009-12-21 03:58:50 by baldr
.equ will not take more than 2 arguments, so that will throw up an error. And moreover I would definitely not like to add overhead of additional instructions into the source just for this macro.  
Posted on 2009-12-21 04:27:59 by uglyhunK
uglyhunK,

I'd downloaded binutils and tried several approaches to the problem. This one appears to work:

.macro stdcall function:req,args:vararg
    argc=0
    .ifnb \args
        .irp arg,\args; argc=argc+1; .endr
        argrc=argc
        .rept argc
            argrc=argrc-1
            argc=0
            .irp arg,\args
                .if argrc==argc; push \arg; .endif
                argc=argc+1
            .endr
        .endr
    .endif
    call    \function
.endm


Awkward, I know.
Posted on 2009-12-21 06:31:48 by baldr
That cool badlr !! working perfectly  :).  Lemme c if there I can tweak it little more...



Posted on 2009-12-21 07:14:52 by uglyhunK
Here another solution with a little test code:


.intel_syntax noprefix

.altmacro       
.macro ccall func:req, arg1, args:vararg
        local argc
        argc = 0

        /* recursive reverse pusher */
        .macro pusher parg1, pargs:vararg
                .ifnb \parg1
                        pusher  \pargs
                        push    \parg1
                        argc = argc + 1
                .endif
        .endm

        pusher  \arg1 \args
        call    \func
        /* check if ther were arguments pushed */
        .if \argc
                add    esp, argc * 4
        .endif
.endm       

        ccall  myfunc eax, ebx, ecx, (offset fd), fd,

/* test variable in memory */
fd:    .long 0x1234

/* test function to call */       
myfunc:
        ret
Posted on 2010-04-17 11:14:27 by theorizer