Skip to content

docs: add stdcall.md page #989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 42 additions & 24 deletions docs/fastcall.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
# FASTCALL

Fastcall is used to indicate that an assembly function should be jumped into with registers already set.
`FastCall` is used to indicate that a [`SUB`](sub.md) or [`FUNCTION`](function.md) will follow the _FastCall_ Calling
Convention. In this convention, the 1<sup>st</sup> parameter of the function will come in the registers as follows:

* If the function takes a Byte (or uByte) parameter, then the A register will be set with this parameter.
* If it takes an Integer (or uInteger) parameter, then the HL register will be set with the value of that parameter on entry to the function.
* If it takes a Long (or uLong), or fixed parameter, then the DE and HL registers will hold the 32 bit value of the parameter.
* If it takes a float type parameter, then the registers C, DE and HL will hold the five bytes for that value.
* If the function takes a `Byte` (or `UByte`) parameter, then the `A` register will be set with this parameter.
* If it takes an `Integer` (or `UInteger`) parameter, then the `HL` register will be set with the value of that parameter
on entry to the function.
* If it takes a `Long` (or `ULong`), or fixed parameter, then the `DE` and `HL` registers will
hold the 32bit value of the parameter, where `HL` holds the lower 16 bits and `DE` the higher one.
* If it takes a `Float` type parameter, then the registers C, DE and HL will hold the five bytes for that value.
Here, `C` is the exponent (excess 127), and `DEHL` the mantissa, being `DE` the highest 16 bits and `HL` the lower ones.

Return is automatic based on the function return type in the same way:
* 8 bit returns should be in the A register
* 16 bit returns should be in HL
* 32 bit returns should be in DEHL
* 40 bit FLOAT returns should be in CDEHL.
* 8bit returns should be in the A register
* 16bit returns should be in HL
* 32bit returns should be in DEHL
* 40bit FLOAT returns should be in CDEHL.

Fastcall should ONLY be used with functions that take a single parameter. If you use more than one parameter, you'll have to deal with the stack (SP register) and restore it to the previous it had before your function was called.
Strings are a 16bit `UInteger` pointer, hence the `HL` register will be used (both for parameters and return values)

**Example:**
`FastCall` should ONLY be used with functions that take a single parameter. If you use more than one parameter, the remaining
parameters will come in the stack. Upon return, you will have to deal with the stack (SP register) and restore it to the
state it had prior your function was called.

```
When entering the function, the stack will be as follows:

* [SP + 00]: Return address. Top of the stack (16 bits)
* [SP + 02]: 2<sup>nd</sup> parameter (if any)


## Example

```vbnet
FUNCTION FASTCALL whatLetter (A as uByte) as uByte
Asm
PROC
LOCAL DATA, START
JP START
DATA: DEFB "A Man, A Plan, A Canal, Panama"
START: LD HL,DATA
LD D,0
LD E,A
ADD HL,DE
LD A,(HL)
ENDP
End Asm
Asm
PROC
LOCAL DATA, START
JP START
DATA: DEFB "A Man, A Plan, A Canal, Panama"
START: LD HL,DATA
LD D,0
LD E,A
ADD HL,DE
LD A,(HL)
ENDP
End Asm
END FUNCTION
```

Expand All @@ -40,3 +54,7 @@ The above function, when called with `whatLetter(<value>)` will return the `<val
### Notes
* Note that the A register already contains `<value>` when the inline assembly is reached.
* Note that we do NOT need to put a ret opcode on the end of the assembly. The compiler will do that for us.

## See Also

* [STDCALL](stdcall.md)
37 changes: 37 additions & 0 deletions docs/stdcall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# STDCALL

`StdCall` is used to indicate that a `FUNCTION` or `SUB` will receive all its parameters in the stack, following the
_Standard Calling Convention_.

The standard calling convention pushes all the function's parameters into the stack in _reverse order_. For 8bit values,
since Z80 stack register SP register is word-aligned, the parameter is pushed as a 16 bit value, in the high 8 bits
(the Z80 ASM instruction `push af` pushes `A` register in the higher part, and `F` register -flags- in the lower).

Return value for functions is placed in registers, based on the function return type:
* 8 bit returns should be in the A register
* 16 bit returns should be in HL <br/>
Also for `String` values, the memory address of the string.
* 32 bit returns should be in DEHL
* 40 bit FLOAT returns should be in CDEHL.

`STDCALL` is used by default in any function if no calling convention is used.

The stack is automatically cleaned upon function termination.

## Example

```vbnet
REM These two declarations are equivalent

SUB STDCALL Hello
PRINT "HELLO WORLD!"
END SUB

SUB Hello
PRINT "HELLO WORLD!"
END SUB
```

## See Also

* [FASTCALL](fastcall.md)