This document explains how each major AmigaOS compiler generates library calls and what the resulting machine code looks like — essential for recognising compiler signatures during reverse engineering.
---
## The AmigaOS Calling Convention
All library calls use the same register-based convention:
- **A6** = library base pointer
- Arguments in **A0–A3**, **D0–D7** as specified by the `.fd` file
- Return value in **D0** (or D0+D1 for 64-bit returns)
- **Callee** preserves: D2–D7, A2–A6
- **Caller** may destroy: D0, D1, A0, A1
The code generated by all compilers follows this — the difference is how they **set up A6** before the `JSR`.
---
## SAS/C 6.x
SAS/C uses **global library base variables** (`_DOSBase`, `_SysBase`, etc.) and generates direct `JSR LVO(A6)` calls. The standard pattern:
```asm
; Calling Write(file, buffer, length):
; D1=file, D2=buffer, D3=length, A6=_DOSBase
MOVE.L _DOSBase, A6 ; load library base from global
MOVE.L file, D1 ; arg 1
MOVE.L buffer, D2 ; arg 2
MOVE.L length, D3 ; arg 3
JSR -48(A6) ; Write LVO = -48
```
### SAS/C Inline Pragmas
SAS/C uses `#pragma libcall` to define inline stubs:
MOVEA.L (A0), A6 ; dereference to get SysBase value
JSR -$228(A6) ; OpenLibrary LVO = -552
```
This reduces relocation entries and is the default for GCC on AmigaOS.
---
## VBCC (vbcc m68k-amigaos)
VBCC uses `inline.h` style stubs similar to GCC. The calling pattern is identical at the assembly level:
```asm
; VBCC compiled library call — indistinguishable from GCC at asm level
MOVEA.L (_SysBase), A6
MOVE.L D2, -(SP) ; VBCC may push/pop D2 as scratch
MOVE.L arg, D0
JSR -$C6(A6)
MOVE.L (SP)+, D2
```
VBCC is slightly more aggressive about not clobbering D2-D7, matching the calling convention exactly.
---
## Recognising Compiler Signatures During RE
### SAS/C Signature
```asm
; Entry prologue:
LINK A5, #-N ; frame setup (A5 = frame pointer)
MOVEM.L D2-D7/A2-A4, -(SP) ; save callee-saved regs
; ...
MOVEM.L (SP)+, D2-D7/A2-A4 ; restore
UNLK A5 ; teardown
RTS
```
SAS/C uses `A5` as frame pointer and `LINK/UNLK` for stack frames.
### GCC Signature
```asm
; Entry prologue (GCC without frame pointer):
MOVEM.L D2/A2, -(SP) ; only saves what it uses
; ...
MOVEM.L (SP)+, D2/A2
RTS
```
GCC typically does **not** use LINK/UNLK unless required. It uses `A5` as an additional scratch register and often generates `JSR` through `A0` for indirect calls.
### VBCC Signature
VBCC generates very clean, minimal code — similar to GCC but with more consistent callee-save patterns and no GCC-specific idioms (e.g., no `__builtin_` calls).