Menu

invoke (MS) fastcall

2012-02-09
2013-04-20
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-02-09
    code    segment para 'code'
        assume cs:code,ds:code
        org 100h
    start:  jmp around
    fast1   proc fastcall a1:word
        mov ax,a1
        ret
    fast1   endp
    around:
        invoke fast1, 1
        sub ax,1
        mov ah,4Ch
        int 21h
    code    ends
        end start
    

    DX is used as argument to fast1:

    JWasm v2.07pre, Nov  2 2011
    fast1.asm
    00000000            code    segment para 'code'
                        assume cs:code,ds:code
                        org 100h
    00000100  EB03          start:  jmp around
    00000102            fast1   proc fastcall a1:word
    00000102  8BC1              mov ax,cx
    00000104                ret
    00000104  C3            *   retn
    00000105            fast1   endp
    00000105            around: invoke fast1, 1
    00000105  BA0100        *    mov dx, 1
    00000108  E8F7FF        *    call fast1
    
     
  • japheth

    japheth - 2012-06-26

    There are 2 problems with support of MS 16-bit fastcalls:

    - the registers used to hold arguments in JWasm v2.06 were CX and DX. However, the correct registers are  AX, DX and BX.

    - Additional parameters are pushed from LEFT to RIGHT ( like the PASCAL calling convention )

     
  • Hjort Nidudsson

    Hjort Nidudsson - 2012-07-05

    The fastcall combined with invoke is also a powerful tool in assembly ;-)

    > Conventions entitled fastcall have not been standardized, and have been
    > implemented differently, depending on the compiler vendor.

    The standards in this case is C/C++, and in the case of MS stdcalls will be used?
    Watcom allows the user to specify his own calling convention, and uses
    EAX, EDX, EBX, ECX - ax, dx, bx, cx (-zf1).

    The assembler calling convention is register calls, usually using (E)AX, (E)DX and (E)CX.
    EBX is preserved in Win32, but BX used in 16-bit.

    fast4   proc _CType a1:size_t, a2:size_t, a3:size_t, a4:size_t
        mov ax?,a1
        mov dx?,a2
        mov bx?,a3
        mov cx?,a4
        ret
    fast4   endp
        invoke  fast4, 1, dx?, bx?, cx?
    

    MS: (-zf0) ECX and EDX - cx and dx

    00000000            fast4   proc fastcall a1:dword, a2:dword, a3:dword, a4:dword
    00000000  55            *   push ebp
    00000001  8BEC          *   mov ebp, esp
    00000003  8BC1              mov eax,ecx
    00000005  8BD2              mov edx,edx
    00000007  8B5D08            mov ebx,a3
    0000000A  8B4D0C            mov ecx,a4
    0000000D                ret
    0000000D  C9            *   leave
    0000000E  C20800        *   retn 8
    00000011            fast4   endp
    00000011                invoke  fast4, 1, edx, ebx, ecx
    00000011  51            *    push ecx
    00000012  53            *    push ebx
    00000013  8BD2          *    mov edx, edx
    00000015  B901000000        *    mov ecx, 1
    0000001A  E8E1FFFFFF        *    call fast4
    0000001F
    

    Watcom: (-zf1)

    00000000            fast4   proc fastcall a1:dword, a2:dword, a3:dword, a4:dword
    00000000  8BC0              mov eax,eax
    00000002  8BD2              mov edx,edx
    00000004  8BDB              mov ebx,ebx
    00000006  8BC9              mov ecx,ecx
    00000008                ret
    00000008  C3            *   retn
    00000009            fast4   endp
    00000009                invoke  fast4, 1, edx, ebx, ecx
    00000009  8BC9          *   mov ecx, ecx
    0000000B  8BDB          *   mov ebx, ebx
    0000000D  8BD2          *   mov edx, edx
    0000000F  B801000000        *   mov eax, 1
    00000014  E8E7FFFFFF        *    call fast4
    00000019
    

    It would be nice then if this..

    00000000            fast4   proc fastcall a1:word, a2:word, a3:word, a4:word
    00000000  8BC0              mov ax,ax
    00000002  8BD2              mov dx,dx
    00000004  8BDB              mov bx,bx
    00000006  8BC9              mov cx,cx
    00000008                ret
    00000008  C3            *   retn
    00000009            fast4   endp
    00000009                invoke  fast4, 1, dx, bx, cx
    00000009  8BC9          *   mov cx, cx
    0000000B  8BDB          *   mov bx, bx
    0000000D  8BD2          *   mov dx, dx
    0000000F  B80100        *   mov ax, 1
    00000012  E8EBFF        *    call fast4
    00000015
    

    ..could be reduced to this:

    00000000            fast4   proc fastcall a1:word, a2:word, a3:word, a4:word
    00000000                ret
    00000000  C3            *   retn
    00000001            fast4   endp
    00000001                invoke  fast4, 1, dx, bx, cx
    00000001  B80100        *   mov ax, 1
    00000004  E8EBFF        *    call fast4
    00000007
    
     
  • japheth

    japheth - 2012-07-05

    Yes, I agree the proposed optimization is useful. But it won't happen for v2.07, this version is due to be released soon.

     
  • japheth

    japheth - 2012-08-07

    in v2.08, support for MS fastcall has been improved. The proposed optimization has been implemented, and loading the arguments into the registers is now more fool-proved.

     

Log in to post a comment.