Announcement

Collapse
No announcement yet.

Calling conventions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Calling conventions

    An issue that was raised recently in this forum was the "need" for an old
    Microsoft standard calling convention called FASTCALL. Here is the viable
    alternative that can be written directly in PowerBASIC when an external
    DLL is being called, for lack of another name, this is DIRTYCALL calling
    convention.

    It works by making a standard DLL function call to retrieve the address
    of a label in the DLL function, then it directly calls that address with
    a value in the EAX register which is used in the DLL internal function
    to perform a simple calculation.

    On a large DLL with many function, this would be done first so that you
    have the addresses in an array or a global variable and then call the
    internal function in the normal DLL function as the program requires.

    This method benchmarks on my PIII 600 at about 1100 milliseconds for
    100 million iterations of the direct call to the address in the DLL
    including the simple calculation in the DLL.

    Depending on how familiar you are with PowerBASIC's inline assembler, you
    can pass 6 DWORD size parameters in the available integer registers and 8
    floating point values in the FP registers. If you have the need to pass
    more parameters, you can pass the address of an array or structure in one
    integer register.

    FASTCALL, ho hum

    Regards,

    [email protected]

    Code:
      Test code in calling EXE file.
      
          TheAddress& = TestFunction
      
          tc& = GetTickCount()
      
          ! mov ecx, 100000000    ' 100 million
        tst:
          ! mov eax, ecx          ' pass directly in EAX
          ! call TheAddress&
          ! dec ecx
          ! jnz tst
      
          tc2& = GetTickCount() - tc&
      
          MessageBox hWin,ByCopy str$(tc2&),"Test", _
                     %MB_OK or %MB_ICONINFORMATION
      
      
      
      Test DLL code
      
      '##########################################################################
      
          #COMPILE DLL
      
      '##########################################################################
      
      FUNCTION TestFunction ALIAS "TestFunction" () EXPORT as LONG
      
          ! jmp past_It
      
        ' --------------------------
        ' The REAL function is here
        ' --------------------------
      
          LabelAddress:
      
          ! shl eax, 1
      
          ! ret
      
        ' --------------------------
      
          past_It:
      
          FUNCTION = CodePtr(LabelAddress)
      
      END FUNCTION
      
      '##########################################################################
    [This message has been edited by Steve Hutchesson (edited January 27, 2001).]
    hutch at movsd dot com
    The MASM Forum

    www.masm32.com

  • #2
    Steve,

    One word: brilliant!


    Peter.


    ------------------
    [email protected]
    [email protected]

    Comment


    • #3
      I haven't tried this yet. But it sounds great. Steve, you
      mentioned the benchmark for your direct call. But how did it
      compare with the speed of a conventional PB call? (I'm assuming
      that it was much faster, right?)

      My concern now would be whether the next version of the compiler
      would break my code if I decided to rely on something like
      this. I had once made an unconventional use of label addresses
      (after checking with tech support first). It worked smoothly
      with PB 5. But I had to undo it with PB 6.0.

      ------------------
      Daniel Corbier
      UCalc Fast Math Parser
      http://www.ucalc.com
      Daniel Corbier
      uCalc Fast Math Parser
      uCalc Language Builder
      sigpic

      Comment


      • #4
        Daniel,

        It should not be a problem because it uses a documented function
        to get the address and normal assembler instructions to do the
        direct call to that label. If you are interested in trying this
        technique, note that you cannot use LOCAL variable at all in
        area between the label and the RET instruction, what you can do
        is use GLOBAL variables in that area as PB is a 2 pass compiler
        which will handle them within the code without problems.

        You can pass data in EAX, ECX & EDX easily, you will need to
        be careful with EBX, ESI & EDI if you wish to use them for
        passing parameters but I think from memory that PB tidies this
        up for you. If you have problems there, just preserve EBX, ESI & EDI
        at the beginning of the proc that calls the code in the DLL and
        it should work OK.

        I don't think there are any limits on how you use the 8 floating
        point registers but you will have to work out how to get the data
        you want to pass into that format.

        Let us know how you go with the idea as I am sure many are interested
        in the type of code you are writing.

        Regards,

        [email protected]

        ------------------
        hutch at movsd dot com
        The MASM Forum

        www.masm32.com

        Comment

        Working...
        X