Author Topic: Prototype bug and API implementation  (Read 1207 times)

nidud

  • Member
  • *****
  • Posts: 1999
    • https://github.com/nidud/asmc
Re: Prototype bug and API implementation
« Reply #15 on: May 26, 2020, 11:36:06 PM »
Yes, and in the link you see the actual function called by the Microsoft and PellesC are the Open Watcom version. However, these are also defined as C with no decoration so you cant use INVOKE directly on them either. Watcall is FASTCALL using EAX, ECX, EDX, and EBX so two QWORD fits in registers. The mangling appends an underscore at the end. A direct register call:

        mov eax,diff_eax
        mov edx,diff_edx
        mov ebx,60
        xor ecx,ecx
        _U8D()
        sub edi,1
        scputf(esi, edi, 0, 0, "%19I64d", edx::eax)

I tested WATCALL but that failed in Asmc. The command line switch -zf1 (and -zf0) didn't work and a few other things that needs fixing. Uasm and Jwasm works but you cant use WATCALL on individual functions as C/STDCALL. It's a good and flexible (and fast) calling convention.

; jwasm -zf1 test.asm

    .486
    .model flat, fastcall

alldiv proto :qword, :qword

    .code

main proc

  local a:qword
  local b:qword

    invoke alldiv, a, b
    ret

main endp

    end

public main_
extern alldiv_: near

main_   PROC NEAR
        push    ebp
        mov     ebp, esp
        sub     esp, 16
        mov     ebx, dword ptr [ebp-10H]
        mov     ecx, dword ptr [ebp-0CH]
        mov     eax, dword ptr [ebp-8H]
        mov     edx, dword ptr [ebp-4H]
        call    alldiv_
        mov     esp, ebp
        pop     ebp
        ret

Vortex

  • Member
  • *****
  • Posts: 2381
Re: Prototype bug and API implementation
« Reply #16 on: May 27, 2020, 12:00:26 AM »
Hi nidud,

Thanks for explaining Watcall, I didn't knew this calling convention.

Quote
Watcall is FASTCALL using EAX, ECX, EDX, and EBX

Regarding Watcall, the fifth and the further parameters are passed to the stack, is that correct? Another variant of my custom invoke macro could handle Watcall.

Edit :

Quote
Watcom compiler

The Watcom compiler doesn't conform to the register usage conventions in table 4. The
only scratch register is EAX. All other general purpose registers are callee-save, except for
EBX, ECX, EDX when used for parameter transfer, and ESI when used for return pointer. (In
16-bit mode, ES is also a scratch register). It is possible to specify any other register usage
by the use of pragmas in the Watcom compiler.

https://www.agner.org/optimize/calling_conventions.pdf

nidud

  • Member
  • *****
  • Posts: 1999
    • https://github.com/nidud/asmc
Re: Prototype bug and API implementation
« Reply #17 on: May 27, 2020, 12:55:54 AM »
I haven't  "released" any of these FASTCALL conventions in 32-bit as done in 64. There you can use SYSCALL individually in Windows which is a perfect match. You may then pass argument in 14 registers where RDI and RSI is the first two which will be preserved thru API calls. I'm doing some experiments on this with the GDI+ classes for functions with a lot of pointers and an arrays of coordinates passed in XMM registers.

In 32-bit JWasm lumps all of these together as FASTCALL so you may only use one type per module.

Vortex

  • Member
  • *****
  • Posts: 2381
Re: Prototype bug and API implementation
« Reply #18 on: May 27, 2020, 01:31:45 AM »
Hi nidud,

Quote
I haven't  "released" any of these FASTCALL conventions in 32-bit as done in 64.

Maybe I am missing something, Asmc supports the standard fastcall convention in 32-bit :

Code: [Select]
; Source code assembled with
; Asmc Macro Assembler Version 2.31.30

.386
.model flat,stdcall
option casemap:none

includelib "\asmc-master\lib\kernel32.lib"
includelib "\asmc-master\lib\msvcrt.lib"

ExitProcess PROTO :DWORD
printf PROTO C :DWORD,:VARARG

.data
string1     db '10 + 20 + 30 + 40 = %d',0

.code

fcallproc PROC FASTCALL a:DWORD,b:DWORD,c:DWORD,d:DWORD

    mov     eax,a
    add     eax,b
    add     eax,c
    add     eax,d
    ret

fcallproc ENDP

start:

    invoke  fcallproc,10,20,30,40
    invoke  printf,ADDR string1,eax
    invoke  ExitProcess,0
   
END start

Disassembling the object module :
Code: [Select]
_text   SEGMENT DWORD PUBLIC 'CODE'

@fcallproc@16 PROC NEAR
        push    ebp
        mov     ebp, esp
        mov     eax, ecx
        add     eax, edx
        add     eax, dword ptr [ebp+8H]
        add     eax, dword ptr [ebp+0CH]
        leave
        ret     8
@fcallproc@16 ENDP

_start  PROC NEAR
        push    40
        push    30
        mov     edx, 20
        mov     ecx, 10
        call    @fcallproc@16
        push    eax
        push    offset _string1
        call    _printf
        add     esp, 8
        push    0
        call    _ExitProcess@4
_start  ENDP

_text   ENDS

nidud

  • Member
  • *****
  • Posts: 1999
    • https://github.com/nidud/asmc
Re: Prototype bug and API implementation
« Reply #19 on: May 27, 2020, 03:02:28 AM »
Yes so whats is missing here is this:

wproc proto watcall :qword, :qword
fproc proto fastcall :qword, :qword
.code
start:
    invoke wproc, 1, 2
    invoke fproc, 1, 2

What I'm ment with "released" refer to 64-bit where you can mix FASCALL types in the same module:

a proto syscall :qword, :qword
b proto vectorcall :qword, :qword
c proto fastcall :qword, :qword

.code

foo proc fastcall x:qword
    a(x,2)
    b(x,2)
    c(x,2)
    ret
foo endp

bar proc syscall x:qword
    a(x,2)
    b(x,2)
    c(x,2)
    ret
bar endp

    end

public foo
public bar

extern c: near
extern b@@16: near
extern a: near


_text   SEGMENT PARA 'CODE'

foo     PROC
        mov     qword ptr [rsp+8H], rcx
        push    rbp
        mov     rbp, rsp
        sub     rsp, 96
        mov     esi, 2
        mov     rdi, qword ptr [rbp+10H]
        call    a
        mov     edx, 2
        mov     rcx, qword ptr [rbp+10H]
        call    b@@16
        mov     edx, 2
        mov     rcx, qword ptr [rbp+10H]
        call    c
        leave   
        ret
foo     ENDP

bar     PROC
        push    rbp
        mov     rbp, rsp
        sub     rsp, 96
        mov     esi, 2
        call    a
        mov     edx, 2
        mov     rcx, rdi
        call    b@@16
        mov     edx, 2
        mov     rcx, rdi
        call    c
        leave
        ret
bar     ENDP