← Home · Exec Kernel
ExecBase — Full Structure Reference
Overview
ExecBase is the root structure of AmigaOS, located at absolute address $4. It is a struct Library extended with all exec kernel state: memory lists, task queues, interrupt vectors, library lists, and hardware abstraction fields. Every system call goes through ExecBase — it is the single point of truth for the entire running system.
Locating ExecBase
/* C — standard method */
struct ExecBase *SysBase = *((struct ExecBase **)4);
/* Or use the auto-open variable (SAS/C, GCC): */
extern struct ExecBase *SysBase; /* Linker resolves from startup code */
; Assembly — canonical method
MOVEA.L 4.W,A6 ; A6 = SysBase (short absolute addressing)
; All exec LVO calls use JSR offset(A6)
Why address $4? The 68000 stores the initial Program Counter at address $4 in the exception vector table. During cold boot, the CPU reads this address to find the ROM entry point. After boot, Exec overwrites it with a pointer to ExecBase. This is the one absolute address every Amiga program can rely on.
Structure Layout
graph TB
EB["ExecBase at $4"] --> LIB["Library Header<br/>(struct Library)<br/>Offsets 0–33"]
EB --> SOFT["Software Config<br/>SoftVer, ColdCapture,<br/>WarmCapture, SysStkUpper"]
EB --> TASK["Task Scheduling<br/>TaskReady, TaskWait,<br/>ThisTask, IDNestCnt,<br/>TDNestCnt, Quantum"]
EB --> MEM["Memory Management<br/>MemList, MaxLocMem,<br/>MaxExtMem"]
EB --> LISTS["System Lists<br/>LibList, DeviceList,<br/>ResourceList, PortList,<br/>IntrList"]
EB --> HW["Hardware Detection<br/>AttnFlags, ChipRevBits0,<br/>PowerSupplyFrequency,<br/>VBlankFrequency"]
style EB fill:#e8f4fd,stroke:#2196f3,color:#333
style TASK fill:#e8f5e9,stroke:#4caf50,color:#333
style HW fill:#fff3e0,stroke:#ff9800,color:#333
Key Field Groups
Every library starts with this — ExecBase is exec.library's own base:
struct Library LibNode; /* ln_Name = "exec.library" */
/* lib_Version = 40 (OS 3.1), 45 (OS 3.2), 47 (OS 3.2.2) */
/* lib_OpenCnt = open count */
Boot and Configuration
| Offset |
Field |
Type |
Description |
$22 |
SoftVer |
UWORD |
Kickstart software revision |
$24 |
LowMemChkSum |
WORD |
Checksum of vectors $0–$200 |
$26 |
ChkBase |
ULONG |
ExecBase self-checksum |
$2A |
ColdCapture |
APTR |
Cold reboot intercept vector |
$2E |
CoolCapture |
APTR |
Warm reboot intercept vector (after Diag) |
$32 |
WarmCapture |
APTR |
Keyboard reset intercept vector |
$36 |
SysStkUpper |
APTR |
Top of supervisor stack |
$3A |
SysStkLower |
APTR |
Bottom of supervisor stack |
$3E |
MaxLocMem |
ULONG |
Top of Chip RAM (e.g., $200000 for 2 MB) |
$42 |
DebugEntry |
APTR |
Entry point for ROM debugger (Wack) |
$46 |
DebugData |
APTR |
Data area for ROM debugger |
$4A |
AlertData |
APTR |
Last Alert data |
$4E |
MaxExtMem |
APTR |
Top of Extended RAM (or NULL) |
Task Scheduling
| Offset |
Field |
Type |
Description |
$126 |
IDNestCnt |
BYTE |
Interrupt disable nesting (−1 = enabled) |
$127 |
TDNestCnt |
BYTE |
Task disable nesting (−1 = enabled) |
$128 |
ThisTask |
APTR |
Pointer to currently running Task |
$12C |
Quantum |
UWORD |
Time slice for equal-priority round-robin |
$12E |
Elapsed |
UWORD |
Ticks elapsed in current quantum |
$130 |
SysFlags |
UWORD |
Internal scheduler flags |
$132 |
TaskReady |
List |
Tasks ready to run (sorted by priority) |
$146 |
TaskWait |
List |
Tasks blocked on Wait() |
Memory
| Offset |
Field |
Type |
Description |
$15A |
MemList |
List |
All memory regions (MemHeader chain) |
System Lists
| Offset |
Field |
Type |
Description |
$17A |
LibList |
List |
Loaded libraries (NT_LIBRARY) |
$18E |
DeviceList |
List |
Loaded devices (NT_DEVICE) |
$1A2 |
IntrList |
List |
Interrupt server lists |
$1B6 |
ResourceList |
List |
System resources |
$1CA |
PortList |
List |
Public message ports |
$1DE |
SemaphoreList |
List |
Public semaphores |
Hardware Detection
| Offset |
Field |
Type |
Description |
$128 |
AttnFlags |
UWORD |
CPU and FPU capability flags |
$212 |
VBlankFrequency |
UBYTE |
VBL rate: 50 (PAL) or 60 (NTSC) |
$213 |
PowerSupplyFrequency |
UBYTE |
Mains: 50 or 60 Hz |
$21E |
ChipRevBits0 |
UBYTE |
Chip revision detection |
AttnFlags — CPU Detection
| Bit |
Constant |
Meaning |
| 0 |
AFF_68010 |
68010 or better detected |
| 1 |
AFF_68020 |
68020 or better |
| 2 |
AFF_68030 |
68030 or better |
| 3 |
AFF_68040 |
68040 or better |
| 4 |
AFF_68881 |
68881 FPU detected |
| 5 |
AFF_68882 |
68882 FPU detected |
| 6 |
AFF_FPU40 |
68040 internal FPU |
| 7 |
AFF_68060 |
68060 detected (OS 3.1+) |
| 10 |
AFF_PRIVATE |
Exec private — do not use |
Usage
/* Check for 68020+ */
if (SysBase->AttnFlags & AFF_68020)
{
/* Can use CACHE instructions, 32-bit multiply, etc. */
}
/* Check for FPU */
if (SysBase->AttnFlags & (AFF_68881 | AFF_68882 | AFF_FPU40))
{
/* Floating-point hardware available */
}
Detecting Chipset Revision
/* via graphics.library */
struct GfxBase *gfx = (struct GfxBase *)OpenLibrary("graphics.library", 36);
if (gfx)
{
if (gfx->ChipRevBits0 & GFXB_AA_ALICE) /* AGA Alice */
if (gfx->ChipRevBits0 & GFXB_AA_LISA) /* AGA Lisa */
if (gfx->ChipRevBits0 & GFXB_HR_AGNUS) /* ECS Agnus */
if (gfx->ChipRevBits0 & GFXB_HR_DENISE) /* ECS Denise */
}
Enumerating System Lists
Walking the Library List
Forbid();
struct Node *node;
for (node = SysBase->LibList.lh_Head;
node->ln_Succ != NULL;
node = node->ln_Succ)
{
struct Library *lib = (struct Library *)node;
Printf(" %s V%ld.%ld (open: %ld)\n",
lib->lib_Node.ln_Name,
lib->lib_Version,
lib->lib_Revision,
lib->lib_OpenCnt);
}
Permit();
Walking the Task Lists
Forbid();
/* Currently running */
Printf("Running: %s\n", SysBase->ThisTask->tc_Node.ln_Name);
/* Ready to run */
for (node = SysBase->TaskReady.lh_Head;
node->ln_Succ; node = node->ln_Succ)
{
Printf(" Ready: %s (pri %ld)\n",
node->ln_Name, node->ln_Pri);
}
/* Waiting */
for (node = SysBase->TaskWait.lh_Head;
node->ln_Succ; node = node->ln_Succ)
{
Printf(" Wait: %s (pri %ld)\n",
node->ln_Name, node->ln_Pri);
}
Permit();
ExecBase Safety Rules
| Rule |
Reason |
| Never write to ExecBase fields |
Corrupts kernel state for all tasks |
Use Forbid() when walking lists |
Lists change as libraries open/close, tasks start/stop |
| Don't cache pointers from lists |
Nodes may be removed between accesses |
| Always use LVO functions |
Direct field manipulation bypasses safety checks |
Verify SysBase after warm reboot |
ColdCapture/CoolCapture may have altered it |
ExecBase in IDA Pro / Ghidra
After loading Kickstart ROM:
- Create a segment at
$000000–$000400 (exception vectors)
- Mark
$4 as a pointer — follow it to the ExecBase in ROM
- Apply
struct ExecBase type from NDK39 headers
- IDA:
File → Parse C header with exec/execbase.h
- Ghidra: Import C headers via Data Type Manager
- All
N(A6) offsets in exec code auto-annotate as field names
- Label the system lists —
LibList, DeviceList, PortList are entry points for understanding boot order
References
- NDK39:
exec/execbase.h — authoritative field definitions
- ADCD 2.1: exec.library autodoc
- See also: Library System — how libraries relate to ExecBase
- See also: Multitasking — TaskReady/TaskWait and scheduler internals
- See also: Kickstart Boot Diagnostics — ColdStart ExecBase allocation, chip RAM sizing
- Amiga ROM Kernel Reference Manual: Exec — ExecBase chapter