amiga-bootcamp/05_reversing/static/compilers/dice_c.md

135 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[← Home](../../../README.md) · [Reverse Engineering](../../README.md) · [Static Analysis](../README.md) · [Compilers](README.md)
# DICE C — Reverse Engineering Field Manual
## Overview
**DICE C** (by Matt Dillon, 19921995) was a fast, lean C compiler for AmigaOS known for its incredible compilation speed — often 1050× faster than SAS/C. It was the compiler of choice for rapid development cycles and produced tight, no-frills code. Its key RE characteristics: **no frame pointer** (like GCC/VBCC), **PC-relative string addressing** (like GCC), and **minimal register saves** (per-function, like VBCC). DICE C binaries look most similar to VBCC output but with some distinctive patterns.
Key constraints:
- **No frame pointer** — DICE C omits the frame pointer by default. Functions use SP-relative addressing.
- **PC-relative strings** — Like GCC and VBCC, DICE uses `LEA string(PC), A0`.
- **Extremely fast compilation** — DICE's speed came from a simpler optimizer; the binary output is clean but not as aggressively optimized as SAS/C -O2 or GCC -O2.
- **Custom startup** — `_mainCRTStartup` (not `_start`) is the typical entry point name.
- **Hunk names**: `CODE`, `DATA`, `BSS` (Amiga standard)
```asm
; DICE C function — no frame pointer, PC-relative, per-function save:
_func:
MOVEM.L D2-D4/A2-A3, -(SP) ; save only what's used
; ... function body, SP-relative access ...
MOVEM.L (SP)+, D2-D4/A2-A3
RTS
```
---
## Binary Identification
| Criterion | DICE C | SAS/C | GCC | VBCC |
|---|---|---|---|---|
| **Frame pointer** | None | A5 always | A6 or none | None |
| **String addressing** | PC-relative | Absolute + reloc | PC-relative | PC-relative |
| **Register save** | Per-function | Fixed 9 regs | Per-function | Per-function |
| **Startup entry** | `_mainCRTStartup` | `_start` | `_start` | `_start` |
| **Hunk names** | `CODE`, `DATA`, `BSS` | `CODE`, `DATA`, `BSS` | `.text`, `.data`, `.bss` | `CODE`, `DATA`, `BSS` |
| **Optimizer** | Moderate | Aggressive | Aggressive | Aggressive (peephole) |
| **Compile speed** | Very fast | Moderate | Slow | Fast |
### Key Distinguishing Patterns
1. **`_mainCRTStartup` entry point** — unique to DICE C. No other Amiga compiler uses this name for the startup entry.
2. **`ADDQ.L #4, SP` argument cleanup** — DICE C often uses `ADDQ` to pop arguments after function calls, where SAS/C would use `LEA`.
3. **Conservative optimization** — DICE C may not perform CSE or loop-invariant code motion as aggressively as SAS/C or GCC.
---
## Library Call Patterns
```asm
; DICE C library call:
MOVEA.L (_SysBase).L, A6
JSR -$C6(A6) ; AllocMem
; DICE C may not cache A6 — reloads from global for each call block
```
DICE C is notable for using **`MOVEA.L (_LibBase).L, A6`** (absolute long with relocation) rather than `MOVEA.L _LibBase, A6` (absolute with reloc). The `().L` suffix is a DICE C assembler convention that appears in the disassembly.
---
## Historical Context
**Matt Dillon** (later known for DragonFly BSD, the HAMMER filesystem, and the D compiler) wrote DICE C as a side project while developing Amiga software. Its claim to fame was compiling the entire DICE C compiler itself in **under 10 seconds** on a stock Amiga 3000 — a feat SAS/C needed minutes for.
DICE C was particularly popular in the Amiga demoscene and shareware community, where fast edit-compile-test cycles mattered more than squeezing every last cycle out of the generated code. It also shipped with a suite of development tools including a linker, librarian, and debugger.
DICE C's development effectively ended when Matt Dillon moved to FreeBSD development in the mid-1990s. The final version was released as freeware.
Software known or likely to use DICE C:
- **DICE C itself** (self-hosting — compiled with DICE C)
- Various Amiga shareware utilities (19921995 era)
- Some demoscene tools and intros
- Early Amiga networking utilities
---
## Same C Function — DICE C Output
```asm
; CountWords() — DICE C:
; (No frame pointer, PC-relative strings, per-function save)
_CountWords:
MOVEM.L D2-D3, -(SP) ; save D2-D3 only
MOVEQ #0, D2 ; D2 = count
MOVEQ #0, D3 ; D3 = in_word
MOVEA.L $0C(SP), A0 ; A0 = str (SP+12, after saved regs + ret addr)
BRA.S .loop_test
.loop_body:
MOVEQ #' ', D0
CMP.B (A0), D0
BEQ.S .not_word
MOVEQ #'\t', D0
CMP.B (A0), D0
BEQ.S .not_word
MOVEQ #'\n', D0
CMP.B (A0), D0
BEQ.S .not_word
TST.B D3
BNE.S .next_char
ADDQ.L #1, D2
MOVEQ #1, D3
BRA.S .next_char
.not_word:
MOVEQ #0, D3
.next_char:
ADDQ.L #1, A0
.loop_test:
TST.B (A0)
BNE.S .loop_body
MOVE.L D2, D0
MOVEM.L (SP)+, D2-D3
RTS
```
**DICE C observations**: For this simple function, DICE C's output is nearly identical to GCC and VBCC. The distinction emerges in:
- **Startup code naming** (`_mainCRTStartup` vs `_start`)
- **Argument cleanup patterns** (`ADDQ.L #4, SP` after calls)
- **Less aggressive CSE** in more complex functions
---
## References
- [compiler_fingerprints.md](../../compiler_fingerprints.md) — Quick identification
- DICE C distribution (Aminet: `dev/c/dice`)
- Matt Dillon's DICE C documentation (archive.org)
- See also: [sasc.md](sasc.md), [gcc.md](gcc.md), [vbcc.md](vbcc.md) — compare with other compilers