Author Topic: Pseudo FASTCALL for 32 bit MASM.  (Read 123 times)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 7531
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Pseudo FASTCALL for 32 bit MASM.
« on: August 12, 2020, 11:03:09 AM »
Seems to work OK.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    fcall MACRO procedure,arg1,arg2,arg3,arg4,arg5
    push ebx
      IFNB <arg5>
        .err
        %echo 4 argument limit exceeded
      ENDIF
      IFNB <arg1>
        mov eax, arg1
      ENDIF
      IFNB <arg2>
        mov ebx, arg2
      ENDIF
      IFNB <arg3>
        mov ecx, arg3
      ENDIF
      IFNB <arg4>
        mov edx, arg4
      ENDIF
      call procedure
    pop ebx
    ENDM

    .data
      tmsg db "Text Message",0
      pmsg dd tmsg
      tttl db "Title",0
      pttl dd tttl

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main

    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    fcall mbox,0,pmsg,pttl,MB_OK

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

mbox proc

    invoke MessageBox,eax,ebx,ecx,edx

    ret

mbox endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

comment *

00401010                    start:
00401010 E807000000             call    fn_0040101C
00401015 6A00                   push    0
00401017 E8EAFFFFFF             call    jmp_ExitProcess

0040101C                    fn_0040101C:                ; Xref 00401010
0040101C 53                     push    ebx
0040101D B800000000             mov     eax,0
00401022 8B1D0D304000           mov     ebx,[off_0040300D]
00401028 8B0D17304000           mov     ecx,[off_00403017]
0040102E BA00000000             mov     edx,0
00401033 E802000000             call    fn_0040103A
00401038 5B                     pop     ebx
00401039 C3                     ret

0040103A                    fn_0040103A:                ; Xref 00401033
0040103A 52                     push    edx
0040103B 51                     push    ecx
0040103C 53                     push    ebx
0040103D 50                     push    eax
0040103E E8BDFFFFFF             call    jmp_MessageBoxA
00401043 C3                     ret

*
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

jj2007

  • Member
  • *****
  • Posts: 10539
  • Assembler is fun ;-)
    • MasmBasic
Re: Pseudo FASTCALL for 32 bit MASM.
« Reply #1 on: August 12, 2020, 12:24:54 PM »
Works fine, but I would suggest to save ebx only when needed:

Code: [Select]
    fcall MACRO procedure,arg1,arg2,arg3,arg4,arg5
      IFNB <arg5>
        .err
        %echo 4 argument limit exceeded
      ENDIF
      IFNB <arg1>
        mov eax, arg1
      ENDIF
      IFNB <arg2>
        push ebx
        mov ebx, arg2
      ENDIF
      IFNB <arg3>
        mov ecx, arg3
      ENDIF
      IFNB <arg4>
        mov edx, arg4
      ENDIF
      call procedure
      IFNB <arg2>
  pop ebx
      endif
    ENDM

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 7531
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Pseudo FASTCALL for 32 bit MASM.
« Reply #2 on: August 12, 2020, 12:51:59 PM »
I have a better version that does not use ebx.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    fastcall32 MACRO procedure:REQ,arg1,arg2,arg3,arg4,arg5,arg6, \
                                   arg7,arg8,arg9,arg10,arg11,arg12, \
                                   arg13,arg14,arg15,arg16,arg17,arg18
   ;; -----------------------
   ;; stack arguments 4 to 18
   ;; -----------------------
      IFNB <arg18>
        push reparg(arg18)
      ENDIF
      IFNB <arg17>
        push reparg(arg17)
      ENDIF
      IFNB <arg16>
        push reparg(arg16)
      ENDIF
      IFNB <arg15>
        push reparg(arg15)
      ENDIF
      IFNB <arg14>
        push reparg(arg14)
      ENDIF
      IFNB <arg13>
        push reparg(arg13)
      ENDIF
      IFNB <arg12>
        push reparg(arg12)
      ENDIF
      IFNB <arg11>
        push reparg(arg11)
      ENDIF
      IFNB <arg10>
        push reparg(arg10)
      ENDIF
      IFNB <arg9>
        push reparg(arg9)
      ENDIF
      IFNB <arg8>
        push reparg(arg8)
      ENDIF
      IFNB <arg7>
        push reparg(arg7)
      ENDIF
      IFNB <arg6>
        push reparg(arg6)
      ENDIF
      IFNB <arg5>
        push reparg(arg5)
      ENDIF
      IFNB <arg4>
        push reparg(arg4)
      ENDIF
   ;; -------------------------
   ;; register arguments 1 to 3
   ;; -------------------------
      IFNB <arg3>
        mov edx, reparg(arg3)
      ENDIF
      IFNB <arg2>
        mov ecx, reparg(arg2)
      ENDIF
      IFNB <arg1>
        mov eax, reparg(arg1)
      ENDIF
      call procedure
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main

    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    fastcall32 mbox,0,"Text Message","Title",MB_OK

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

mbox proc styl:DWORD

    invoke MessageBox,eax,ecx,edx,styl

    ret

mbox endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

This is the disassembly of the above, reasonably efficient for a stackframe procedure.

0040101C                    fn_0040101C:                ; Xref 00401010
0040101C 6A00                   push    0
0040101E BA00304000             mov     edx,offset off_00403000   ; 'Title',000h
00401023 B906304000             mov     ecx,offset off_00403006   ; 'Text Message',000h
00401028 B800000000             mov     eax,0
0040102D E801000000             call    fn_00401033
00401032 C3                     ret

00401033                    fn_00401033:                ; Xref 0040102D
00401033 55                     push    ebp
00401034 8BEC                   mov     ebp,esp
00401036 FF7508                 push    dword ptr [ebp+8]
00401039 52                     push    edx
0040103A 51                     push    ecx
0040103B 50                     push    eax
0040103C E8BFFFFFFF             call    jmp_MessageBoxA
00401041 C9                     leave
00401042 C20400                 ret     4
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 7531
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Pseudo FASTCALL for 32 bit MASM.
« Reply #3 on: August 13, 2020, 12:01:13 PM »
Here is a variation that emulates shadow space if a nested set of calls is required. It starts to get up to the overhead of a normal STDCALL so there is little advantage in doing so but for low argument counts while calling a leaf procedure, its a more efficient calling technique.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    fastcall32 mbox,0,"Text Message","Title",MB_OK

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

mbox proc styl:DWORD

    LOCAL hMbox :DWORD
    LOCAL pMsg  :DWORD
    LOCAL pTtl  :DWORD

    mov hMbox, eax
    mov pMsg, ecx
    mov pTtl, edx

    push styl
    push pTtl
    push pMsg
    push hMbox
    call MessageBox

    ret

mbox endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy: