CALL (External WinAPI)

Syntax

Syntax: CALL FunctionName(args)
Source: pb_cg_emit_call (pb_codegen.c:4719)

Description

Invokes an external function declared with DECLARE, such as a Windows API or DLL export. The compiler follows the Windows x64 calling convention: the first four integer/pointer arguments go in RCX, RDX, R8, R9; remaining arguments are pushed to the stack. Float arguments go to XMM0-XMM3. BYREF arguments pass a pointer to the variable. String arguments are converted to null-terminated ASCIIZ pointers before the call.

Parameters

ParameterDescription
FunctionNameThe name of the external function as declared with DECLARE.
argsComma-separated list of arguments. Each argument is evaluated and passed according to the Win64 ABI. Use BYVAL or BYREF as specified in the declaration.

Example

DECLARE FUNCTION MessageBoxA LIB "user32.dll" _
    ALIAS "MessageBoxA" ( _
    BYVAL hWnd AS QUAD, _
    BYVAL lpText AS ASCIIZ PTR, _
    BYVAL lpCaption AS ASCIIZ PTR, _
    BYVAL uType AS LONG _
) AS LONG

FUNCTION PBMAIN() AS LONG
    LOCAL result AS LONG
    
    ' Call Windows API MessageBox
    CALL MessageBoxA(0, "Hello from PowerBASIC!", _
                     "PB x64", 0)
    
    FUNCTION = 0
END FUNCTION

Generated Assembly

Integer/Pointer Arguments

; Evaluate each argument -> temp slot
mov    [rbp - arg_offset_0], rax       ; arg 1 value
mov    [rbp - arg_offset_1], rax       ; arg 2 value
; ... etc for each arg

; Stage first 4 to registers (Win64 ABI):
mov    rcx, [rbp - arg_offset_0]       ; arg 1 -> RCX
mov    rdx, [rbp - arg_offset_1]       ; arg 2 -> RDX
mov    r8,  [rbp - arg_offset_2]       ; arg 3 -> R8
mov    r9,  [rbp - arg_offset_3]       ; arg 4 -> R9

; Stage args 5+ to stack (above shadow space):
mov    rax, [rbp - arg_offset_4]
mov    [rsp + 32], rax                 ; arg 5 -> [rsp+32]
mov    rax, [rbp - arg_offset_5]
mov    [rsp + 40], rax                 ; arg 6 -> [rsp+40]
; ... offset = 32 + (i-4)*8 ...

call   [__imp_<FunctionName>]

Float Arguments

movsd  xmm0, [rbp - arg_offset_0]      ; FP arg 1 -> XMM0
movsd  xmm1, [rbp - arg_offset_1]      ; FP arg 2 -> XMM1
movsd  xmm2, [rbp - arg_offset_2]      ; FP arg 3 -> XMM2
movsd  xmm3, [rbp - arg_offset_3]      ; FP arg 4 -> XMM3

BYREF Arguments

; Get address of variable (LEA for stack locals)
lea    rax, [rbp - var_offset]
mov    [rbp - arg_offset], rax          ; store address in arg temp
; Then staged normally: mov rcx, [rbp - arg_offset]

STRING Arguments (to ASCIIZ PTR)

; pb_cg_emit_asciiz_pointer -> RAX = null-terminated string pointer
mov    [rbp - arg_offset], rax

Win64 Argument Layout

ArgInteger/PtrFloatStack (if >4)
1RCXXMM0-
2RDXXMM1-
3R8XMM2-
4R9XMM3-
5[rsp+32][rsp+32]Stack slot 0
6[rsp+40][rsp+40]Stack slot 1
N[rsp+32+(N-5)*8]-Stack slot N-5