John Burger's Demo
In 1995, I had been tinkering with the '386 for a few years, learning about different aspects of it and the PC that used it. Back then the World Wide Web had barely been invented, and there certainly weren't dedicated sites like this one for discussing arcane or even beginner questions on the operation of the PC.
But back then there was UseNet, a way of sending messages under different categories to other readers interested in that category. I laugh when I think about how it was considered "rude" to use UseNet to advertise products: that was considered "spam", and people were shunned when they tried. Alas...
Today Google has archives of those newsgroups, and you can see most of the old posts today. Some have been lost - one of the failings of UseNet - but new posts are being added all the time.
Two groups that I followed carefully were
alt.lang.asm - the former more serious, while the latter more alternative (hence the designators). But then as now there were newbies that asked the same questions over and over, so I decided to do something about it.
I posted a five-part demo (https://groups.google.com/d/topic/comp.lang.asm.x86/RmpXt19VGHk/), in x86 assembly, showing one way to perform the following steps:
- Set up the GDT
- Set up the IDT
- Set up the interrupt and fault handlers
- Initialise the A20 gate
- Initialise the PICs to revector the IRQs
- Modify the timer to interrupt more often
- Switch to protected mode
- Set up some on-screen (text) tasks to execute
- Switch between the different tasks
- When the <Esc> key was pressed, return to real mode
- Restore the timer
- Restore the PICs
- Restore the A20 gate
- Exit the program
This demo was useful, since it allowed me to make changes to the code, try them out immediately, and when I pressed <Esc> it would return to DOS (gasp!). I could then reload the IDE and try the next thing. I didn't have to set up a boot floppy every time (USB stick? Back then? Nope!) and reboot every time to try it.
Updated demo, for today's environment
Reading various pages on this Wiki and Forum, it's apparent that people are still interested in the steps I demonstrated above. The problem is that today, the development environment is a whole lot more sophisticated, and it's a lot harder to do the code/assemble/test/code merry-go-round that was so easy before.
Nevertheless, in the following pages I present a working demonstration of the steps necessary to get a '386 into protected mode, and what to do once you get there. It won't demonstrate some sophisticated features, like Paging, various device drivers, or modules like networking or file systems, but it will provide a testbed to explore various aspects of low-level OS development:
- What happens when a stack overflows?
- What does an Invalid TSS exception need to do?
- What is the effect of slowing down or speeding up the clock?
- How can I get information between different Tasks?
The 80386 (and later) is able to run in 32-bit mode in what is commonly called the "Flat" Memory Model, with none of that 'pesky' Segmentation. Where's the fun in that? Personally, I find the extra protection offered by Segments a benefit while programming and debugging, and well worth the extra considerations.
I want to demonstrate many things with this code:
- Supervisor vs User modes. This requires at least one TSS;
- Segmentation. This requires more GDT entries for system tables such as LDTs and TSSs;
- Local Descriptor Tables. Allow each Task their own private segments;
- Task State Segments. Why not demo the CPU's native switching mechanism?