The MASM Forum

General => The Laboratory => Topic started by: hutch-- on March 11, 2016, 12:30:54 AM

Title: Using a structure in FASTCALL
Post by: hutch-- on March 11, 2016, 12:30:54 AM
I have been a bit distracted over the last couple of weeks with another task but this is the technique I had in mind for a roll your own FASTCALL where you have more arguments than the 3 registers that can be used.

In simple terms, a procedure with less than 4 arguments can use EAX ECX & EDX.
With a technique posted below in an earlier post you can simulate locals with .DATA? section variables.
The technique below uses a structure for procedures that require more than 3 arguments.

The gains are a stack free procedure that does not need  the complex stack offset changes common in no-stack frame procs, the extra register EBP is easily available if needed, the equivalent of LOCALS work fine and with the use of a structure, the argument count limit does not matter.


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

    fcargs STRUCT
      arg1 dd ?
      arg2 dd ?
      arg3 dd ?
      arg4 dd ?
      arg5 dd ?
      arg6 dd ?
      arg7 dd ?
      arg8 dd ?
    fcargs ENDS

    .data?
      pMessageBox dd ?
      pLib dd ?

    .data
      tMsg db "This is a message box",0
      pMsg dd tMsg
      tTtl db "MessageBox",0
      pTtl dd tTtl

    .code

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

    call main
    exit

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

main proc

    LOCAL astruct    :fcargs

    mov pLib, rv(LoadLibrary,"user32.dll")
    mov pMessageBox, rv(GetProcAddress,pLib,"MessageBoxA")

    m2m astruct.arg1, pMessageBox    ; function address
    mov astruct.arg2, 0              ; handle
    m2m astruct.arg3, pMsg           ; text message
    m2m astruct.arg4, pTtl           ; dialog title
    mov astruct.arg5, MB_OK          ; style

    lea eax, astruct.arg1
    call mbox

    fn FreeLibrary,pLib

    ret

main endp

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

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

mbox PROC

    push DWORD PTR [eax+16]
    push DWORD PTR [eax+12]
    push DWORD PTR [eax+8]
    push DWORD PTR [eax+4]

    call DWORD PTR [eax]

    ret

mbox ENDP

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

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

end start
Title: Re: Using a structure in FASTCALL
Post by: dedndave on March 14, 2016, 04:22:40 AM
you could pass the address of the structure
then, load EBP with that address  :P
Title: Re: Using a structure in FASTCALL
Post by: npnw on March 23, 2016, 03:48:40 AM
x86 calling conventions
https://en.wikipedia.org/wiki/X86_calling_conventions (https://en.wikipedia.org/wiki/X86_calling_conventions)
Title: Re: Using a structure in FASTCALL
Post by: K_F on March 23, 2016, 06:49:23 PM
Quote from: dedndave on March 14, 2016, 04:22:40 AM
you could pass the address of the structure
then, load EBP with that address  :P
That what I thought... there's a lot of extra memory movement with that mbox code  ;)

Quotehttps://en.wikipedia.org/wiki/X86_calling_conventions
??
:biggrin:
Title: Re: Using a structure in FASTCALL
Post by: jj2007 on March 23, 2016, 08:08:54 PM
Quote from: dedndave on March 14, 2016, 04:22:40 AM
you could pass the address of the structure
then, load EBP with that address  :P

include \masm32\include\masm32rt.inc

MBOX STRUCT
mRet dd ?
mArg dd ?
mText dd ?
mTitle dd ?
MBOX ENDS

.data?
mbox MBOX <>

.code
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
MyBox proc
LOCAL mTitle, mText, mArg, mRet
push ebp
lea ebp, [eax+MBOX]
invoke MessageBox, 0, mText, mTitle, mArg
mov mRet, eax
pop ebp
ret
MyBox endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

start:
  mov eax, offset mbox
  mov mbox.mTitle, chr$("Title")
  mov mbox.mText, chr$("Text")
  mov mbox.mArg, MB_YESNOCANCEL
  call MyBox
  inkey str$(mbox.mRet), " returned"
  exit

end start
Title: Re: Using a structure in FASTCALL
Post by: hutch-- on March 25, 2016, 03:59:51 AM
Here is the difference. The point of the FASTCALL demo was to eliminate the stack overhead as well as having the extra register.


-------
JJ MBOX
-------
00401000                    fn_00401000:                ; Xref 0040103C
00401000 55                     push    ebp
00401001 8D6810                 lea     ebp,[eax+10h]
00401004 FF75F4                 push    dword ptr [ebp-0Ch]
00401007 FF75FC                 push    dword ptr [ebp-4]
0040100A FF75F8                 push    dword ptr [ebp-8]
0040100D 6A00                   push    0
0040100F E8AE010000             call    jmp_MessageBoxA
00401014 8945F0                 mov     [ebp-10h],eax
00401017 5D                     pop     ebp
00401018 C3                     ret

-------------
FASTCALL MBOX
-------------
00401074                    fn_00401074:                ; Xref 00401062
00401074 FF7010                 push    dword ptr [eax+10h]
00401077 FF700C                 push    dword ptr [eax+0Ch]
0040107A FF7008                 push    dword ptr [eax+8]
0040107D FF7004                 push    dword ptr [eax+4]
00401080 FF10                   call    dword ptr [eax]
00401082 C3                     ret