SAS/C Compiler Reference¶
SAS/C (Version 6.58) is the C compiler used to build all the NDK example code. This article documents its key features, extensions, and the knowledge needed to compile AmigaOS programs with it. Source: SAS/C User's Guide Volumes 1+2 (SAS Institute, 1993).
Version history¶
SAS Institute shipped the following public releases of the SAS/C Development System for AmigaDOS:
| Version | Date | Notes |
|---|---|---|
| 6.50 | 1993 | Initial release. Two volumes of the printed User's Guide + System Library Reference. |
| 6.55 | 1995 | First patch release. Added asm flag, several bug fixes. |
| 6.56 / 6.57 | mid–late 1990s | Interim patches (predominantly internal; not widely redistributed). |
| 6.58 | 2005 | Final public release. ~47 bug fixes plus two new builtins (__builtin_rol, __builtin_ror) and an extended SYMLOAD HUNKINFO directive. Development was officially terminated in 1995, but the 6.58 patch backports accumulated fixes from the in-house tree. |
After 6.58, no further public patches were issued. The compiler remains the official 68k development toolchain shipped with the NDK 3.x; for new development, see The VBCC Compiler, which is open source and actively maintained.
Key changes introduced by the patches (6.50 → 6.58)¶
The cumulative effect of the 6.55, 6.56, 6.57, and 6.58 patch chain on day-to-day Amiga development falls into four areas:
Debugger (CPR / CPRX) stability — One of the more visible improvements for working developers is the cross-debugger (CPRX, the remote/cross-Amiga debugger session between two machines). The 6.58 release substantially reduced crashes and system lockups during debug sessions on complex setups or networked cross-debug links. The earlier 6.50 release had frequent Enforcer hits in line-mode CPR (e.g., the SHOW command trigger fixed in 6.58 item #8) and crashes when exiting CPR after debugging a Workbench-launched program with -s (fixed in 6.58 item #27).
Bitfield compatibility — Earlier versions (6.0 and the first 6.50) had bitfield layout that drifted from the long-standing SAS/C 5.x conventions, breaking code that relied on the historical bit ordering and packing. The patch chain progressively restored retro-compatibility, so the bitfield layout in 6.58 matches the 5.x reference once again. This matters for code that pokes at hardware registers or uses bitfields to define on-disk structures.
Optimizer (sc) correctness — The aggressive optimizer combination OPT + OPTGO + OPTPEEP could in rare cases mis-schedule 68k register usage, producing correct-looking but broken code. The patch series corrected the register-tracking issues and related cases (e.g., the NEG <ea> memory-modification fix in 6.58 item #9, the memcpy alignment fix in 6.58 item #47). Most users will only notice the optimizer in the form of "weird crashes" that vanished with 6.58.
NDK alignment and static link libraries — sc.lib and amiga.lib were updated to interface cleanly with the NDK shipped alongside AmigaOS 3.1 and later. In particular the C runtime started honouring 16-bit-abs relocations correctly (broken in 6.57, fixed in 6.58 item #6: move foo.w,a0 once again assembles to the intended movw form). At the same time the linker (slink) gained the warning for constructor/destructor priority overflow (6.58 item #17) and the proper handling of the LIBFD startup option (startup=devinit / startup=devinitr, 6.58 item #24).
The compilation chain¶
source.c → sc (compiler) → object.o → slink (linker) → executable
source.c → sc link (one-step compile+link) → executable
| Tool | Purpose |
|---|---|
sc |
C compiler (also does assembly via .s input) |
slink |
Linker |
smake |
Make utility (reads smakefile) |
cdbg |
Source-level debugger (CodeProbe) |
bum |
Library maintenance |
oml |
Object module librarian |
Key sc compiler options¶
| Option | Effect |
|---|---|
link |
Compile + link in one step |
optimize=N |
Optimization level 0–4 (0=none, 4=max) |
define=SYM |
Define preprocessor symbol |
ignore=NN |
Suppress warning number NN |
nostackcheck |
Disable stack overflow checking |
structureequivalence |
Allow struct assignment by structure type |
verbose |
Verbose compilation output |
includedir=dir |
Additional include path |
code=small |
Small code model |
data=far |
Far data model |
math=standard |
Standard math library |
smakefile patterns¶
An smakefile (SAS/C makefile) uses tab-indented rules like standard make:
CFLAGS = optimize=2 structureequivalence
all: myapp helper
myapp: myapp.c
sc link $(CFLAGS) $*
helper: helper.c
sc $(CFLAGS) $*.c
slink lib:c.o helper.o myapp.o lib:sc.lib lib:amiga.lib to myapp
$* = target name without extension. $< = first dependency. $@ = full target name.
All NDK smakefiles follow the pattern: sc link structureequivalence $*.
SAS/C-specific keywords¶
These are critical for correct AmigaOS code:
__saveds — load data segment¶
void __saveds my_callback(void)
{
/* Data segment (A4) is loaded — safe to access globals */
}
Mandatory for: interrupt handlers, hook callbacks, timer callbacks, any function called from a different task context or supervisor mode. Without __saveds, the function may access the wrong data segment, causing silent corruption or crashes.
The NDK examples consistently use __saveds on:
- Hook entry functions
- Interrupt handlers (AddIntServer callbacks)
- Timer callbacks
- BOOPSI dispatcher functions
__interrupt — interrupt handler¶
Marks a function as an interrupt handler (no stack switch, must preserve all registers). Combined with __saveds.
__regargs / __stdargs¶
__regargs— pass all arguments in CPU registers (D0–D2, A0–A1) instead of on the stack. Faster but non-standard ABI.__stdargs— standard C calling convention (stack-based). Default.
Amiga library functions use the register-based ABI via the library's jump table and #pragma libcall.
Startup modules¶
SAS/C provides startup code that runs before main():
- OS calls the program entry point with:
A6=ExecBaseA0= BCPL return vectorA2= argument BSTR- Startup module (e.g.,
c.o) opensDOSBase, parses arguments intoargc/argv - Calls
main(argc, argv) - After
main()returns, startup closesDOSBaseand exits
Without a startup module (for libraries, device drivers):
void __saveds __startup entry(void)
{
/* A6 = ExecBase guaranteed */
/* Must manually open DOSBase if needed */
}
#pragma statements¶
Seven pragmas control library calls and diagnostics:
| Pragma | Purpose |
|---|---|
#pragma libcall |
Call library function via register ABI |
#pragma flibcall |
Library call with floating-point registers |
#pragma amicall |
Aztec C-compatible library call |
#pragma regcall |
Register-based call (Aztec compat) |
#pragma syscall |
System call |
#pragma tagcall |
Tag-based (TagItem) call |
#pragma msg |
Control diagnostic message severity |
#pragma msg — diagnostic control¶
#pragma msg 123 warn /* make message 123 a warning */
#pragma msg 123 ignore /* suppress message 123 */
#pragma msg 123 error /* make message 123 an error */
#pragma msg 123 warn push /* save current state, then change */
#pragma msg 123 pop /* restore previous state */
Only works on messages numbered 1–299 (C compiler messages, not C++ translator).
Stack management¶
Default stack: 4000 bytes (stkneed = 400). This is often enough but can overflow with deep recursion or large local arrays.
| Solution | How | When |
|---|---|---|
stackext keyword |
Per-function stack extension | Deep recursion in one function |
stackext option |
Entire program | Many functions need more stack |
Increase stkneed |
extern long stkneed = 8192; |
All functions need more |
nostackcheck |
Disable checking | Release builds (minor speed gain) |
Never set stkneed below 400. The stackext keyword adds overhead (extra register + entry code), so use selectively.
CodeProbe debugger (cdbg)¶
Source-level debugger with:
cdbg program # load program
| Command | Action |
|---|---|
break function |
Breakpoint at function |
break file.c:42 |
Breakpoint at source line |
watch variable |
Break when variable changes |
step / next |
Single step (into/over) |
continue |
Resume execution |
print expr |
Evaluate expression |
backtrace |
Call stack |
list |
Show source around PC |
CodeProbe supports debugging shared libraries (Chapter 5) and multitasking programs (Chapter 6) — both essential for AmigaOS where most programs spawn multiple tasks.
Optimization levels¶
| Level | Effect | Recommended use |
|---|---|---|
| 0 | No optimization | Debugging |
| 1 | Basic peephole | Quick dev builds |
| 2 | Standard | Development builds |
| 3 | Aggressive (inlining, loop opts) | Release candidates |
| 4 | Maximum (may alter FP precision) | Release builds |
Trade-off: higher optimization = slower compilation, harder to debug.
See Also¶
Sub-articles¶
This article is the entry point for the SAS/C 6.58 documentation set on the wiki. Each sub-article covers a specific aspect of the SAS/C Development System; navigate to the one you need.
Editor, source workflow¶
- The SAS/C Editor (se) — full-screen editor
se, multiple windows, marked blocks, configuration viaS:se.config, AREXX interface to the editor (ADDRESS SE). - SAS/C Compilation and Linking —
scoptions in depth,slinklinker and library order, Workbench startup (ToolTypes, ArgArrayInit), project structure. - SAS/C Startup Modules and Auto-Initialization — what
c.odoes, library auto-open, custom entry points,__autoinit/__autoexit, argument parsing.
Language extensions¶
- SAS/C Extensions to C and C++ —
__saveds,__interrupt,__regargs/__stdargs,__aligned,#pragma libcall,#pragma msg, GCC-style__attribute__subset, C++ support notes. - SAS/C Assembly Language —
scas assembler, inline__asm/#asm/asm(), register mapping, calling conventions, hardware access patterns, cache pitfalls. - SAS/C Portable C — three-layer portability model (standard C / SAS extensions / AmigaOS), wrapping patterns, porting to/from GCC.
Debugging¶
- The CodeProbe Debugger (cdbg) — compiling for debug (
debug=line,debug=local), windowing UI, basic commands, breakpoints, watchpoints, C++ debugging. - The SAS/C Debugger — Advanced — shared libraries (
OpenLibraryattach), multitasking (task switching, signals), AREXX automation, cross-debugging over serial. - The SAS/C Debugger — Command Reference — full command list, AREXX built-ins (
BREAK,CONTINUE,EVALUATE,WAITFORSTOP, ...), configuration files.
Toolchain¶
- SAS/C Utilities —
smake,slink,oml,bum,blazemgr,fpsp,resdent,Commodore,tr. - SAS/C Optimization — levels 0–4, peephole, CSE, inlining, FP precision, profiling and measuring, debug interaction.
Library reference overview¶
- SAS/C System Library Reference — Commodore libraries (exec, dos, intuition, graphics, layers, utility, ...), SAS/C libraries (
sc.lib,amiga.lib,debug.lib), NDK header layout, predefined data, library-open patterns.
Sources: SAS Institute Inc., "SAS/C Development System User's Guide" Volumes 1+2, Version 6.50 (1993).
Raw: raw/sasc/sasc-reference-extract.md; raw/sasc/sasc-syslib-ref.md
Updated: 2026-10-02