flat assembler
Message board for the users of flat assembler.

Index > Main > Call macro

Author
Thread Post new topic Reply to topic
redsock



Joined: 09 Oct 2009
Posts: 430
Location: Australia
redsock 15 Feb 2014, 07:05
I am trying to come up with a call macro, optionally enabled or disabled such that without it, normal calls work, and with it, the macro applies. This all works well and good, except I can't quite figure out the syntax required in order to achieve:

call qword [rdx]

If I use call qword, [rdx] then I can check inside the macro for argument order, etc.

Is there a way to do this such that both qword [rdx] ends up in the same argument to the macro? I have tried as many ways as I could come up with to no avail.

Cheers everyone!
Post 15 Feb 2014, 07:05
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20363
Location: In your JS exploiting you and your system
revolution 15 Feb 2014, 07:38
Show us what you tried. Because by default it will place such text into the first macro argument.
Post 15 Feb 2014, 07:38
View user's profile Send private message Visit poster's website Reply with quote
redsock



Joined: 09 Oct 2009
Posts: 430
Location: Australia
redsock 15 Feb 2014, 08:18
macro call target* {
push @f
jmp target
align 16
@@:
}

basically, one of Agner's theories that has proven to be absolutely correct (with my x86_64 goods), is that _ALL JUMP TARGETS_ should be aligned 16. Interestingly, when I created proper multibyte noop macros, he is absolutely correct. Without a functioning version of this macro, I am unable to align 16 the _return_ (and still have it conditionally compiled). In all of my testing thus far, including 16 byte aligned returns for function calls indeed causes dramatic speed improvements.

So, the above macro works a treat for simple calls like:

call some_function_i_declared

it is only with size preface that fasm complains and won't do the deed.

Hope this helps to clarify. In retrospect, I should have included example macro and fails thereof in my original post. Apologies for that.

Cheers
Post 15 Feb 2014, 08:18
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 15 Feb 2014, 12:12
redsock,

Were you literally invoking that macro with call qword, [rdx] (note the comma)? Because call qword [rdx] (without comma) works as expected.

You may try to add padding before and pass argument(s) to previous call verbatim (it may be macro too):
Code:
                                  macro call [args] {
                                  common
                                  local ..call, ..ret
                                          times 15 and (..call-..ret-$) nop
                                  ..call: call    args
                                  ..ret:
                                  }
                                          use64
00000000: 90 90 90 90 90 90 90 90         call    qword [rdx]
          90 90 90 90 90 90 FF 12 
00000010: 90 90 90 90 90 90 90 90         call    $
          90 90 90 E8 FB FF FF FF    
Post 15 Feb 2014, 12:12
View user's profile Send private message Reply with quote
redsock



Joined: 09 Oct 2009
Posts: 430
Location: Australia
redsock 15 Feb 2014, 20:20
HA! Wow, I must have been having a "special" day when I was fighting with this. You were absolutely correct in that my own example works as expected.

Here is what tripped me up when I was overcomplicating the solution:

Code:
        align_returns = 1

        macro call target* {
                display `target,10
if align_returns
                push    @f
                jmp     target
                align 16
                @@:
else
                call    target
end if
        }
    


In my feverish and frustrated state that day, I took the fasm error of "Extra characters on line" from the display as to mean it wasn't going to fly and then decided at some point I would just ask here... hahah, removing the display line does what I wanted it to in the first place.

Maybe a sign I should take a break or something, hahah.

Thank you very kindly in any case, sometimes can't see the forest for the trees! Smile

The rest of my simple test case is below. Is there a way to make display work in that way?

Code:
        format ELF64

        align_returns = 1

        macro call target* {
                display `target,10
if align_returns
                push    @f
                jmp     target
                align 16
                @@:
else
                call    target
end if
        }

section '.text' executable align 16

public func1
align 16
func1:
        int3
        nop
        ret

public _start
align 16
_start:
        call    func1
        mov     rdx, func1
        call    rdx
        push    func1
        mov     rdx, rsp
        call    qword [rdx]
        int3
        nop
    


Cheers and thanks again
Post 15 Feb 2014, 20:20
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
m3ntal 16 Feb 2014, 02:59
Just a note: Inside macros, @@: can have undesired effects:
Code:
macro a {
 @@:
 ; ...
}

@@:
a
jmp @b    
Solution: Replace @@: with "local x" then "x:".
Post 16 Feb 2014, 02:59
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 16 Feb 2014, 05:41
redsock wrote:
Is there a way to make display work in that way?
You must feed backtick symbol-wise, i.e. using irps s, target { display `s }.

----8<----
m3ntal wrote:
Solution: Replace @@: with "local x" then "x:".
Just a note: your solution can produce undesired effects:
Code:
macro a {
local x
x:
;...
}

test_a:
  .1:   a
        jmp     .1; Error: undefined symbol "x?0.1".    
Solution: prepend x with two dots (..x: won't change prefix for local labels).
Post 16 Feb 2014, 05:41
View user's profile Send private message Reply with quote
redsock



Joined: 09 Oct 2009
Posts: 430
Location: Australia
redsock 16 Feb 2014, 21:16
baldr wrote:
Code:
                                  macro call [args] {
                                  common
                                  local ..call, ..ret
                                          times 15 and (..call-..ret-$) nop
                                  ..call: call    args
                                  ..ret:
                                  }
    


This was an excellent suggestion, thx! When I cut-pasted your code in as a test, I got:

calltest.asm [25]:
call func1
calltest.asm [8] call [3]:
times 15 and (..call-..ret-$) nop
error: invalid use of symbol.

I did however modify my multibyte alignment macro to successfully do what you suggested (align the call/return itself).

I now have 3 variants, call_baldr_style, align_returns (which does the push and jmp instead of the real call), and the call itself...

This is the one I took from your suggestion:

Code:
macro call target* {
        local ..c, ..r, a
        virtual
                align 16
                a = $ - $$
        end virtual
        a = a - (..r - ..c)
        if a = 15
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0x66, 0xf, 0x1f, 0x44, 0x00, 0x00
        else if a = 14
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0xf, 0x1f, 0x44, 0x00, 0x00
        else if a = 13
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0xf, 0x1f, 0x40, 0x00
        else if a = 12
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0xf, 0x1f, 0x00
        else if a = 11
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0x66, 0x90
        else if a = 10
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
                db 0x90
        else if a = 9
                db 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
        else if a = 8
                db 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
        else if a = 7
                db 0xf, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
        else if a = 6
                db 0x66, 0xf, 0x1f, 0x44, 0x00, 0x00
        else if a = 5
                db 0xf, 0x1f, 0x44, 0x00, 0x00
        else if a = 4
                db 0xf, 0x1f, 0x40, 0x00
        else if a = 3
                db 0xf, 0x1f, 0x00
        else if a = 2
                db 0x66, 0x90
        else if a = 1
                db 0x90
        end if
..c:    call    target
..r:
}    


thanks again Smile
Post 16 Feb 2014, 21:16
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
m3ntal 17 Feb 2014, 05:45
baldr: Typo, forgot the dots.

To anyone who's writing a function, here's my function for reference.
Post 17 Feb 2014, 05:45
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.