flat assembler
Message board for the users of flat assembler.

Index > Windows > fastcall

Author
Thread Post new topic Reply to topic
b1528932



Joined: 21 May 2010
Posts: 287
b1528932 29 Mar 2011, 20:10
parameters are passed in rcx, rdx, r8 and r9. Rest goes on stack after 32byte shadow space. This i understand.
But why do i have to align stack to 16 bytes?

Is it ok to do and rsp, 0xFFFFFFFFFFFFFFF0 at the beggining of program?
Post 29 Mar 2011, 20:10
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4119
Location: vpcmpistri
bitRAKE 30 Mar 2011, 02:24
OS requires alignment and shadow space. If you can guarantee that state prior to API calls then you are in compliance. Leaf node that don't use the API can do whatever.
Post 30 Mar 2011, 02:24
View user's profile Send private message Visit poster's website Reply with quote
b1528932



Joined: 21 May 2010
Posts: 287
b1528932 30 Mar 2011, 06:01
Ok, so basically i have to do anything to make rsp aligned to 16 bytes before any api call?

I think its better to do so at the beginning, and then keep track of rsp so its always aligned.
Post 30 Mar 2011, 06:01
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4119
Location: vpcmpistri
bitRAKE 31 Mar 2011, 05:19
API will use the shadow space to store registers, so more that RSP aligned is needed! Look for my examples on this board - I have used some techniques you will like.

http://board.flatassembler.net/topic.php?t=10231
http://board.flatassembler.net/topic.php?p=94910#94910
http://board.flatassembler.net/topic.php?p=109871#109871

Good related discussion:
http://board.flatassembler.net/topic.php?t=11133

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 31 Mar 2011, 05:19
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 812
Location: Russian Federation, Sochi
ProMiNick 09 Nov 2020, 22:54
what do you think
Code:
macro detect@argsize arg {
    define type@param
    define definition@param arg
    match =float value,definition@param
    \{ define definition@param value
       define type@param float \}
    match =addr value,definition@param
    \{ define definition@param value
       define type@param addr \}
    match param,definition@param
    \{ local opcode,origin
       size@param = 0
       if param eqtype 0 | param eqtype 0f | type@param eq addr
        size@param = 8
       else if param eqtype byte 0 | param eqtype byte 0f
        match prefix value,definition@param
         \\{ if prefix eq qword
              size@param = 8
             else if prefix eq dword
              size@param = 4
             else if prefix eq word
              size@param = 2
             else if prefix eq byte
              size@param = 1
             end if \\}
       else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
        virtual
         origin = $
         inc param
         load opcode byte from origin
         if opcode = 67h | opcode = 41h
          load opcode byte from origin+1
         end if
         if opcode and 0F8h = 48h
          size@param = 8
         else if opcode = 66h
          size@param = 2
         else if opcode = 0FFh
          size@param = 4
         else
          size@param = 1
         end if
        end virtual
       end if \} }    
Code:
macro __mov reg,src,regd,regw,regb,regxmm {
        detect@argsize src
        match param,definition@param \{
                if type@param eq float
                        if ~ param eq regxmm
                                if size@param = 4
                                        if param eqtype byte 0 | param eqtype byte 0f
                                                mov eax,param
                                                movd regxmm,eax
                                        else
                                                movd regxmm,param
                                        end if
                                else
                                        if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
                                                mov rax,param
                                                movq regxmm,rax
                                        else
                                                movq regxmm,param
                                        end if
                                end if
                        end if
                        if vararg@fastcall & ~ param eq reg
                                movq reg,regxmm
                        end if
                else if type@param eq addr
                        if ~ param eq reg
                                lea reg,[param]
                        end if
                else if size@param = 8
                        if ~ param eq reg
                                mov reg,param
                        end if
                else if size@param = 4
                        if ~ param eq regd
                                mov regd,param
                        end if
                else if size@param = 2
                        if ~ param eq regw
                                mov regw,param
                        end if
                else if size@param = 1
                        if ~ param eq regb
                                mov regb,param
                        end if
                end if \} }    
Code:
macro __push arg {
        detect@argsize arg
        match param,definition@param \{
                if type@param eq addr
                        lea     rax,[param]
                        push    rax
                else if param eqtype [0] | param eqtype byte [0]
                        if size@param = 8
                                mov     rax,param
                                push    rax
                        else if size@param = 4
                                mov     eax,param
                                push    rax
                        else if size@param = 2
                                mov     ax,param
                                push    rax
                        else
                                mov     al,param
                                push    rax
                        end if
                else if size@param = 8
                        virtual
                                origin = $
                                mov     rax,param
                                load opcode byte from origin+1
                        end virtual
                        if opcode = 0B8h
                                mov     rax,param
                                push    rax
                        else
                                push    param
                        end if
                else if param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
                        movq    rax,param
                        push    rax
                else
                        mov     eax,param
                        push    rax
                end if \} }    
Code:
macro fastcall proc,torcx:rcx,tordx:rdx,tor8:r8,tor9:r9,[arg] {
 common local stackspace,argscount,counter
        counter = 4
        if ~arg eq
                if argscount and 1
                        sub     esp,8
                end if
 reverse
        counter = counter + 1
        __push arg
 common
        end if
        argscount = counter
        stackspace = ((argscount and 1) + argscount)*8
        if stackspace
                if defined current@frame
                        if current@frame<stackspace
                                current@frame = stackspace
                        end if
                else
                        if stackspace
                                sub rsp,4*8;stackspace
                        end if
                end if
        end if

        __mov r9,tor9,r9d,r9w,r9b,xmm3
        __mov r8,tor8,r8d,r8w,r8b,xmm2
        __mov rdx,tordx,edx,dx,dl,xmm1
        __mov rcx,torcx,ecx,cx,cl,xmm0

        call proc
        if stackspace & ~defined current@frame
                add rsp,stackspace
        end if }    


four macros instead of big one "macro fastcall proc,[arg]"
all rest from proc64.inc untouched.
Is this realization has advantages or weaknesses against official realization?
I guess in my realization I should remove
Code:
                if defined current@frame
                        if current@frame<stackspace
                                current@frame = stackspace
                        end if
                else    
Am I right?
I like pushes - modern CPU are pretty fast to choose coding style based on my own preferences.
And in that variant it is close to linuxfastcall but there are 6 regs not 4 like in windows, and that close to linux syscall64 too, there are too 6 regs.
Post 09 Nov 2020, 22:54
View user's profile Send private message Send e-mail 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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.