Period: 1992-1993 (Age 16)
Role: Sole Developer & "Founder"
Project Type: First Commercial Software Product
My first commercial software product, built when I was 16 years old. Micro-Ed performed statistical regression analysis ("value-added" analysis) for UK secondary schools, helping them measure student progress beyond raw exam scores - analyzing the correlation between GCSE and A-Level results. I developed it with my father, who was a deputy headteacher at a secondary school in Bedfordshire. Together we marketed and sold it to schools across Bedfordshire.
This was real business-to-business software sales as a teenager - cold calls to headteachers, product demos, installation, training, and support. The software reached Version 2.00 Revision A1 and was released to schools in Bedfordshire, Hertfordshire, and Buckinghamshire between June and November 1993.
What made this work wasn't just the code - it was understanding the market. My dad knew the pain points: schools were being judged on raw GCSE results, but that didn't account for where students started. A school taking in struggling students and getting them to pass was doing better work than a selective school getting straight A's from kids who were already high achievers.
We identified the need, built the solution, and sold it school-by-school. Real sales, real invoices, real support calls. This was my introduction to the fact that building software is only half the battle - you have to sell it, support it, and make it actually useful to people who aren't programmers.
The application was written in Borland C++ Version 3.1 (not Turbo C), compiled for MS-DOS using the large memory model with 80286 instruction set output. Performance-critical sections were optimized using inline assembly directives (#pragma inline), and the entire system relied heavily on direct BIOS/DOS interrupt calls rather than standard library functions.
Key technical achievements:
-
Direct BIOS/DOS interrupts: Extensive use of
geninterrupt()and inlineintinstructions (INT 10h for video, INT 21h for DOS services, INT 67h for EMS, INT 24h for critical errors) -
Inline assembly optimization: Critical sections marked with
#pragma inlinefor performance-critical loops and low-level operations -
Register-level programming: Direct manipulation of CPU registers (
_AH,_AL,_BX,_DX, etc.) for BIOS/DOS calls -
Segment/offset addressing: Working with far pointers (
MK_FP()) and the segmented memory model -
Direct video memory manipulation: Custom text-mode UI rendering via direct VGA/CGA memory writes at segment 0xB800/0xB000
-
Large memory model: Enabled handling of 350+ student records in far heap memory
-
8087 FPU detection: Runtime detection and utilization of the math coprocessor (8087/80287/80387) for floating-point regression calculations
-
Statistical algorithms: Linear regression, correlation coefficients, variance calculations, least-squares fitting
-
Memory-optimized data structures: Student records designed for efficient memory usage under DOS constraints
-
EMS/XMS support: Expanded Memory Specification support for larger datasets, with custom 64KB sub-allocation using first-fit algorithm
The codebase demonstrates several sophisticated 16-bit DOS programming patterns:
-
Far/huge pointers: Managing data structures across segment boundaries with
hugepointer arithmetic for student record arrays -
Large memory model: All code and data pointers are far pointers, enabling datasets larger than 64KB
-
Direct hardware I/O: Port-level keyboard and display control using
outp()andinp() -
Custom interrupt handlers: Replaced INT 24h (critical error handler) and INT 1Ch (timer tick) with custom handlers
-
PCX image decoding: Custom 256-color PCX decoder with RLE decompression (
PCXVIEW.C,DrawPCX()) -
VGA palette programming: Direct manipulation of VGA DAC registers (ports 0x03C4, 0x03C5) for color palette setup
-
Borland Graphics Interface (BGI): Used for scatter plot graphs with mouse support
-
Custom binary file formats: Proprietary
.DSand.Sysfile formats with XOR encryption for passwords and school names -
Password protection: Custom authentication with obfuscated developer backdoor password
-
Critical error handling: Replaced DOS critical error handler to gracefully handle floppy disk errors and removable media
-
Context-sensitive help system: Complete inline help with multiple contexts stored in binary
.HLPfile
Mid-1990s, targeting schools with aging hardware - many still running 8086/286 machines with 640KB of RAM:
-
Small executable size: Critical when distributing on 1.44MB floppy disks
-
Fast performance: Statistical calculations on hundreds of student records needed optimization via inline assembly
-
Low system requirements: Had to run on the oldest hardware schools had (required only MS-DOS 3.3+)
-
Developer productivity: C for structure and maintainability, inline assembly and BIOS calls for performance
-
No runtime dependencies: Self-contained executable, no DLLs or external libraries beyond BGI drivers
-
Direct hardware control: Inline assembly allowed precise control over CPU registers for BIOS interrupt calls
The software performed multiple linear regression analysis to calculate "value-added" scores:
-
Input data: Student prior attainment (GCSE scores converted to numerical points, top 8 best grades)
-
Output data: Student A-Level results (numerical points: A=10, B=8, C=6, D=4, E=2)
-
Analysis: Expected vs. actual performance, controlling for prior achievement using banded baselines
-
GCSE Ability Bands: 34-39, 40-45, 46-50, 51-56 points (maximum theoretical score: 8 × 7 = 56)
-
Correlation analysis: Calculated mean A-Level points for each GCSE score, with scatter measures
-
Regression line: Least-squares linear regression with gradient calculation:
gradient = Σ((x-x̄)(y-ȳ)) / Σ((x-x̄)²) -
Predictions: Generated expected A-Level scores based on historical correlation data from all loaded years
-
Reporting: Student performance reports showing predicted vs. actual scores, under-achievers flagged with asterisks
-
Grade distributions: Analysis of A-C grades, 5+ A-G percentages, and A-Level grade distributions
All the correlation analysis, least-squares fitting, variance calculations, and statistical significance testing implemented in the STAT.C module (2,230 lines), with the 8087 FPU doing the heavy floating-point lifting when available.
The software used a sophisticated three-tier memory allocation strategy:
- Far heap: Primary storage for student record array (350 max records × ~50 bytes each) using
farcalloc() - EMS memory: Screen buffer save/restore (
ScrPush()/ScrPop()) and text display buffering for scrollable lists - Stack: Increased to 12KB via
extern unsigned _stklen = 1024 * 12to avoid overflow on deep function call chains
EMS detection checked for "EMMXXXX0" driver signature and allocated all available pages (minimum 4 × 16KB pages required), with custom first-fit sub-allocator supporting up to 200 concurrent allocations within the 64KB page frame.
- Language: Borland C++ 3.1 with inline assembly (
#pragma inline) - Compiler: Borland C++ 3.1 (16-bit DOS)
- Memory Model: Large (far code and far data pointers)
- Code Generation: 80286 instruction set, floating-point emulation
- Optimization: Optimized for smallest code size
- Assembler: Inline assembly via Borland C++ compiler directives
- Math: 8087/80287/80387 FPU detection and utilization when present
- Platform: MS-DOS 3.3+, IBM PC/XT/AT compatibles (8086/286/386)
- Memory: Real mode, segmented addressing, far/huge pointers, EMS (LIM EMS 4.0) support
- Graphics: Direct VGA/CGA video memory manipulation (segment 0xB800/0xB000), BGI (Borland Graphics Interface)
- Storage: Floppy disk distribution, custom binary file formats with XOR encryption
- UI: Custom text-mode interface with box-drawing characters (CP437)
- File I/O: Direct DOS file handles via
open(),read(),write(),close() - Interrupts: INT 10h (video), INT 21h (DOS), INT 67h (EMS), INT 24h (critical errors), INT 2Fh (Windows detection)
The software consisted of 12 primary modules totaling over 8,500 lines of code:
MICRO-ED.C(858 lines) - Main program, initialization, startup splash screenSTAT.C(2,230 lines) - Statistical analysis engine, regression calculations, all reporting functionsHS_IO.C(873 lines) - Low-level screen I/O, keyboard, mouse, printer, scrollable text buffersEMS.C(245 lines) - Expanded Memory Specification interface with sub-allocatorLLSTUFF.C(215 lines) - Low-level DOS interface, interrupt handlers, critical error handlingBOXES.C(532 lines) - UI components, dialog boxes, PCX decoder, status barMENUS.C- Drop-down menu system with keyboard and mouse supportEDIT.C- Full-screen student data entry and editingIMPORT.C- SIMS broadsheet data importDATAEX.C- Data file loading, saving, and managementHELP.C- Context-sensitive help systemFILEOUT.C/PRINTOUT.C- Report output redirection to file/printer
Plus installation program (INSTALL.C), developer password/debugging module (DEVPASS.C), and more.
The version history embedded in the source code documents 20+ pre-release versions from 0.00 to 0.20:
- v0.00-0.02 (1992): Basic menu system and data extraction
- v0.03 (early 1993): First working version with Conway charts
- v0.04-0.09: Added graphing, passwords, encryption, teacher performance, subject analysis
- v0.10: EMS support added, switched to compact memory model
- v0.11-0.15: Major features added - sorting, editing, SIMS import, scroll bars
- v0.16: Re-compiled under Borland C++ Version 3.1 (upgrade from earlier version)
- v0.17-0.19: Critical error handler, help system, ability profiles
- v0.20: Bug fixes, preparing for beta release
- v1.00 Rev A (June 5, 1993): Beta release to TVEI Group 5 Consortium
- v1.00 Rev B-v1.01 Rev A5: Refinements, PCX splash screen, mouse support, anti-debug tricks
- v2.00 Rev A1 (Sept-Nov 1993): Full retail release to Bedfordshire, Hertfordshire, and Buckinghamshire schools
First sale: Sandy Upper School, November 8, 1993.
- Systems programming: Real mode memory management, segment:offset addressing, far/huge pointers, EMS memory management
- Low-level optimization: Inline assembly for performance-critical code paths, direct BIOS/DOS interrupt calls
- Hardware interfacing: Direct video memory writes, port I/O (
outp()/inp()), VGA palette programming - Mathematical implementation: Statistical regression algorithms from first principles, floating-point calculations
- Data structure design: Memory-efficient layouts for DOS constraints, custom binary file formats
- Interrupt programming: Custom INT 24h critical error handler, INT 1Ch timer handler replacement
- Graphics programming: PCX image decoding with RLE decompression, BGI scatter plots, mouse support
- Full-stack development: From hardware to UI, every layer hand-coded - no frameworks
- Software architecture: Well-organized modular design with 12+ separate compilation units
- Market identification: Recognized a real need in the education sector before value-added analysis became standard
- Product development: Built something that solved actual problems for real customers
- B2B sales: Sold to institutions (schools), not consumers - navigated procurement processes
- Customer support: Handled training, technical support, and bug fixes post-sale
- Partnership: Worked effectively with my father who brought domain expertise and market access
- Professional software delivery: Version control, serial numbers, licensing, anti-piracy measures
- GitHub: github.com/7-of-9/MicroEd
This project taught me that programming is a tool for solving real problems and creating value. The assembly language work gave me a deep understanding of how computers actually work at the register and interrupt level - knowledge that still informs my architectural decisions today, even in high-level languages and cloud systems.
The business experience showed me that technical excellence without market fit is just a hobby. You have to understand the customer's problem, build something they'll actually pay for, support it properly, and iterate based on feedback.
Everything I've built since - from 3D game engines to blockchain systems - traces back to these lessons learned at 16: understand the hardware, understand the market, and ship something that works.