Home
Protected mode
Protected-mode tutorial
This is an 858K text file PKZIPped to 207K. A must-read for those who
want to work with protected mode.
12 programs written in NASM.
Basic pmode, unreal mode, interrupts and exceptions, multitasking
with TSSes and without, Ring 0 versus Ring 3, etc. This was a by-product
of my attempt to write an operating system, so it's missing Local
Descriptor Tables (LDTs), Virtual 8086 mode, DPMI, etc.
- Works with these BIOS interrupts:
- INT 10h (VGA and VBE)
- INT 13h (disk)
- INT 16h (keyboard)
- other (nested) interrupts called from the interrupts listed above:
INT 15h, INT 2Ah
- Works with 16-bit BIOS code accessed by far CALL, e.g. PnP BIOS
- Unlike most other V86 mode monitors, this code does not use
TSS-based task-switching to switch between protected mode and
virtual 8086 mode
- V86 code can run at IOPL=0 or IOPL=3
- Kernel can report what I/O ports were used by V86 code
- Faulting I/O operations cause the appropriate port to be
enabled in the IOPB. The offending instruction is then re-tried.
- Includes code that is useful if screen becomes garbled
- Kernel text output can be sent to serial port
- set_text_mode() function sets text mode without using the
video BIOS
Operating systems
Most of the things on this page will eventually be moved into the OSD
project. If you don't find what you're looking for on this page,
try the OSD page.
New features in release 11 vs. Cosmos 10:
- New name: Borealis
- Code is now public-domain (no copyright)
- Changed global variable naming convention
- Identical names and prototypes for syscall dispatcher functions in
libc and syscall handlers in kernel. This allows some programs to be
built as stand-alone tasks or as kernel modules.
- kprintf(), panic(), printf(), and sprintf() now use GCC
__attribute__((format(printf, ...))) to validate args
- Fixed I/O permission bitmap base in TSS (was 103, now 104)
- Realtime clock code now works with BCD or binary modes, and
uses interrupt instead of polling to wait for end of update
- Interrupts:
- sleep_on() now uses assembly-language stack-swap code to
yield; instead of stupid fake timer interrupt
- Now enabling interrupts in the kernel during syscall processing
- Syscall interrupt changed from INT 30h to INT 20h, and IRQ
0-15 now mapped to INT 28h-37h for future APIC compatability
- Made code build easily with GCC under different host OSes
(DOS, Windows, Linux):
- Dummy __main() in libc for MinGW. (Got rid of dummy
_alloca() by compiling with -mno-stack-arg-probe)
- Switched to improved OSD linker script
- Makefiles rewritten for host OS portability
- NASM code converted to AS
- ELF, DJGPP COFF, and Win32 PE COFF loaders for executable files
(tasks) and relocatable files
(kernel modules)
- Got rid of:
- init_keyboard()
- sleep() syscall (use select() instead)
- Enabling CPU caches in CR0 register in kernel startup code
(big speedup! thanks Rob!)
- More validation of section addresses when loading user tasks
- Allocating kernel objects dynamically, from kernel heap
instead of fixed-size arrays:
- Virtual consoles (only 12 VCs can be displayed)
- Keyboard buffers
- Memory sections in task_t structure
- Converted to Multiboot:
- Getting conventional and extended memory sizes via Multiboot
- Loading tasks/kernel modules via Multiboot
- OS is now bundled with
DOS Multiboot loader
- User apps now at 4 meg (0x400000) instead of 1 gig (0x40000000)
- UNIX-like device architecture
- open() syscall; scans internal namespace for device names
- read(), write(), select(), and close() work with char devices
- Console character device
- NULL/ZERO character device
- Serial character device
- Console supports more ANSI escapes: ESC[A ESC[B ESC[C ESC[D
ESC[s ESC[u ESC[J ESC[K
Old features:
- Runs on 32-bit x86 CPU. Can run on old/slow system,
e.g. 486SX with 4 meg RAM
- Protection
- Tasks run at ring 3 in their own address spaces
- Separate kernel- and user-privilege stacks for each task.
- Task can not perform I/O
- Tasks that perform an illegal operation are killed
(the kernel keeps running)
- Kernel threads with priority levels: lower for idle thread,
higher for bottom-half interrupt handlers. Preemptive
multitasking (driven by timer interrupt). Round-robin
scheduling within same priority level.
- Keyboard driver with bottom-half interrupt handler thread.
Ctrl+Alt+Del reboots
- Text-mode VGA virtual consoles backed with kernel memory,
with software scrolling and a subset of ANSI escapes
- Realtime clock driver, time() syscall, unique JDN algorithm
- Tinylib; a small C library (libc)
- Make process creates disassembly and symbol table files
- Simple text-mode apps: clock, text echo, protection test, games
- Unified IRQ/exception/fault/interrupt handler
- Kernel thread to recover memory and resources used by dead tasks
Screen shots from Bochs:
What; no paging?! I had trouble adapting the paging code from
Cosmos 10 to work with Multiboot. Borealis 11 uses x86 segmentation
for address translation and (limited) memory protection. If you really
want paging, the old Cosmos 10 code is here,
but it no longer produces a working kernel.
OS discussion
- Message boards:
- Usenet:
- IRC chat:
- gear.wyldryde.net, port 6667, channel #osdev
- irc.freenode.net, port 6667, channel #osdev
Links
Small C kernels with source
Small assembly-language kernels with source
- Menuet. GUI, networking, sound.
Builds with FASM (Flat Assembler). ("But where is the source
code?" Download the demo disk, unzip it, and write it to a floppy.
After you do this, the source code will be on the floppy.)
- RDOS. Needs TASM 3.2
- SOLAR OS
- Triple-DOS
Small kernels with source written in other languages
Unsorted stuff that may be moved or deleted soon
Simulated Linear Framebuffer (MMU-assisted
page-flipping). Use simple LFB software with 16-bit video boards.
Supports/tested with S3 Trio 64V+ and Cirrus 5422.
BING bootloader, version 0.4. Works with DJGPP COFF
kernels only.
BING 0.4 screen shot
BING version 0.5. Does not work, but has more
features than version 0.4 :)
A small demo of paging
VGA info (corrected Jan 4, 2000)