You are on page 1of 215

-



" "

:
:.

.
- .
.LATEX
c
.
/ .
.
) .(GNU


.I

Basics

.
.. . . . . . . . . . . . . . . . . . . . . . . . . . .
... . . . . . . . . . . . . . . . . .
... . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . . . . .
... ) :(- . . . . . .
... ) :(-

.
.. . . . . . . . . . . . . .
... . . . System Bus
... . . . . . . .
... . . .
.. . . . . . . . . . . . . . . . .
... . . . . .
... . CPU Modes
... . . Real Mode
... Protected Mode
... . . . . . x86

x86

.II

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

Boo ng

. Bootloader
.. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . . . Bootloader


.. . . . . . . . . . . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . .
... . . . . . . . . . . . . . . .
... . . . . . . . . . . . . . .
... . int 0x13
.. . . . . . . . . . . . . . . . . . . . FAT12
... . . . . . . . . . . . . . . . . . FAT12
... FAT12 . . . . . . . . . . .
... . . . . . . . . . . . . . . . .
... . . . . . . . . . . FAT12

.
.
.
.
.
.
.
.
.
.

. -
.. . . . . . . . . . . . . . . . . . .
... . . . Global Descriptor Table
... . PMode Memory Addressing
... . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . A20
... 8042 . . . . . . . A20
... . . . . . . . . . . . . . . A20
.. . . . . . . . . . . . . . . . . . . . . . VGA
... . . . . . . . . . . VGA
... . . . . . . . . . . . . .
... . . . . . . . . . . . strings
... . . . . . . . . . . Hardware Cursor
... . . . . . . . . . . . Clear Screen
.. . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.III

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

Kernel

.
.. . . . . .
...
.. . . . . .
... . .
.. . . . .
... Monolithic Kernel
... . . . MicroKernel
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.


... . Hybrid Kernel
.. . . . . . . . . . . .
... . . . . PE
... ++
... . . . .
.. . . . . . . .
.. . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

. Interrupts
.. . So ware Interrupts
... .
... .
... . . . . . . .
... GDT
.. Programmable Interrupt Controller
... . . . . . . . . Hardware Interrupts
... . . . . . . . . . . . . . . . . . PIC
.. . . . . . . . . . . . . . Programmable Interval Timer
... . . . . . . . . . . . . . . . . . . PIT
.. . . . . . . . . . . . . . . . . . . . . . . . HAL
... . . . . . . . . . . . . . . . . . . . . . PIC
... . . . . . . . . . . . . . . . . . . . . . PIT
... HAL . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
..
... . . . . . . . . .
... . . . . . Memory Map
... . . . . . . .
... . . . . . . . . .
.. Virtual Memory Management

.
.
.
.
.

Physical Memory Management

.
..

Device Driver

Keyboard Driver

.
.
.
.
.

. . . . . . . . . . . . . . .


.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . Assembly Language ..

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

. . Smallest Bootloader
. . Welcom to OS World
. . Bios Parameter Block
. . . . . . BPB example
. Hex value of bootloader
. . . Complete Example
. . . Reset Floppy Drive
Read Floppy Disk Sectors

. . . . . . Hello Stage2
. . . Load Root directory
. Find Stage2 Bootloader
. . . . . Load FAT Table

Convert Cluster number to LBA


. . . . . Convert LBA to CHS
. . . . . . . . Load Cluster
. . . . Read Sectors Rou ne
. . . . . . . Read FAT entry

..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..

. . . . . . . . . . . . . . . . . GDT ..
. . . . . . . . . Load GDT into GDTR ..
. . . . . Switching to Protected Mode ..
Enable A20 by System Control Port 0x92 ..
. . . . . . Enable A20 by BIOS int 0x15 ..
. . . . . . . . . . Wait Input/Output ..
. . . . . . . Enable A20 by Send 0xdd ..
Enable A20 by write to output port of Keyboard Controller ..
. . . . . . . . . . . . . . Print 'A' character on screen ..
. . . . . . . . . . . . . . . . . . . putch32 rou ne ..
. . . . . . . . . . . . . . . . . . . . puts32 rou ne ..
. . . . . . . . . . . . . . . . Move Hardware Cursor ..
. . . . . . . . . . . . . . . . . . . . . Clear Screen ..
. . . . . . . . . . . . . . . . . . . . . Hello Kernel ..

..............

Loading and Execu ng Kernel: Full Example

..

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

..
..
..
..
..
..
..
..
..
..
..
..
..

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. . . . . . . . . Example of interrupt descriptor ..


. . . . . . . . . . . . . . Value to put in IDTR ..
include/hal.h:Hardware Abstrac on Layer Interface ..
. . . . . . . . . . . . . hal/gdt.cpp:Install GDT ..
. . . . . . . . . . Ini aliza on Control Words 1 ..
. . . . . . . . . . Ini aliza on Control Words 2 ..
. . . . . . . . . . Ini aliza on Control Words 3 ..
. . . . . . . . . . Ini aliza on Control Words 4 ..
. . . . . . . . . . . . . . . . . . . Send EOI ..
. . . . . . . . . . . . . . . . PIT programming ..
. . . . . . . . . . . . . hal/pic.h: PIC Interface ..
. . . . . . . . . hal/pic.cpp: PIC Implementa on ..
. . . . . . . . . . . . . hal/pit.h: PIt Interface ..
. . . . . . . . . hal/pit.cpp: PIT Implementa on ..
. . . . . . . . . . . . . . . New HAL Interface ..
. . . . . . . . . . . . New HAL Impelmenta on ..
. . . . . . . . . . . . . . . . kernel/main.cpp ..
. . . . . . . . . . . . . . . kernel/excep on.h ..
. . . . . . . . . . . . . . kernel/excep on.cpp ..
. . . . . . . . . . . . . . . . kernel/panic.cpp ..

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

. . . . . . . . . Using int 0x12 to get size of memory


. Using int 0x15 Func on 0xe801 to get size of memory
. . . . . . . . . . . . Memory Map Entry Structure
. . . . . . . . . . . . . . . . . Get Memory Map

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

. . . Portable Executable Header


. . . . . . Ge ng Kernel entry
. . . Global new/delete operator
. Pure virtual func on call handler
. . . . . Floa ng Point Support
. . . . . . . . Object Ini alizer
. . . . . . . . . Delete Object
. . . . . . Kernel Entry rou ne

null.h:Deni on of NULL in C and C++


. size t.h:Deni on of size t in C/C++
. . . . . . stdint.h:typedef data type
. . . . cstdint:C++ typedef data type
. . ctype.h:determine character type

..
..
..
..

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

. . . Mul boot Inforam on Structure


. . . snippet from stage2 bootloader
. . . . . . . . . . . . Kernel Entry
. Physical Memory Manager Interface

Physical Memory Manager Implemeta on


. . . . Virtual Memory Manager Interface
. Virtual Memory Manager Implemeta on

..
..
..
..
..
..
..

. . . . . . . . . . . . . . . . . . . . . . Keybaord Driver Interface ..


. . . . . . . . . . . . . . . . . . . Keybaord Driver Implemeta on ..


.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

..
..
..
..
..
..
..
..
..
..
..
..
..

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.. . . . . . . . . . . . . . . . . . . . . .
.. FAT12 . . . . . . . . . . . . . . . . . . . . .

..
..
..
..
..

. . . . . . x86
. . . . . . . . . . . .
. . . . . . . . . . . . . .
Step Reckoner . . .
.
. . . . .
Z1
Atanaso Iowa State
. . . . . . . . . . . . . . . Harvard Mark I
. . . . . . . . .
colossus . . . . . . .
. . . . . . . . . . . . . . . . . . ENIAC
. . . . . . . . . . . . . . . . . . EDVAC
. . . . . . x86
x86
. . . . . . . . . .
. .
. . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.. . . . . . . . . . . . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . . . . . . .
..
..
..
..
..
..


. . . . . . PIC
. . . . 8253
. . . . . . . PIT
HAL
. .

8259A

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.


..
..
..
. .

. . . . . . x86
. x86
.
...................

.
.
.
.

.
.
.
.

.
.
.
.

...........
...........
...........
EFLAGS

Interrupt Vector Table .

. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . x86 Processor Excep ons Table ..
.. . . . . . . . . . . . . . . . . . . . x86
.. . . . . . . . . . . . . . . . . . . . . . . . IRR/ISR/IMR
.. . . . . . . . . . . . . . . . . . . . . . PIC
.. . . . . . . . . . . . . . . . . . . . . . . . . ICW1
ICW3 for Primary PIC . . . . . . . . . . .
ICW3 for Slave PIC . . . . . . . . . . . . .
ICW4 . . . . . . . . . . . . . . . . . . . . . . . . . .
.. . . . . . . . . . . . . . . . . . . . . . OCW2
.. . . . . . . . . . . . . . . . . . . . . . . . . . . . OCW2
.. . . . . . . . . . . . . . . . . . . . . 8253 PIT

..
..
..
..

..
. .
. .
. .
. .
. .
..
..
..
. .
. .
. .


) (

/ .

.

.

. )
( .




) (Embedded Device
) (Orbiter .
.
:

++ ) (Assembly
.
.



) (Bad Sectors .

.
.
) (
!
.
) (
/.
.
//

.I

Basics

.

.


) (Virtual Machine .
.

) (Processor ) (
.
).(Instruc on Set
.
. .
OPCODE .
:..

x86


) . (Machine Language 0 1
. 31744 AX
.101110001100000000000111
.
.

.
.

.
.: Assembly Language

Example

MOV AX,0x7C00 ; Instead of 101110001100000000000111


.

++
.

) (Compiler
.
2

DRAM ) (Capacitors )(Transistors
) (Memory Cells )
( )(
) (1 ) (0
.
) (Decode
.
) (.



.
) (Layer

.
Unix .

. ) .(Opera ng System

) ( . .
) ( ]?[ .
:..

) (Device Level )(Integrated Circuit


. Microarchitecure
) (Mircoprogram data path
) (Clock Cycle
) (Arithme c Logic Unit .
data path
)Instruc on
(Set Architecture ) (Machine Language
). (Device Controller


) .read(fd,buffer,size ) (

) (Kernel Mode .
.

..
.
) (
.

...
) (Machine Language Level



) (Buer .


.

...

) (

) (Mul tasking
) (Memory Blocks
.

..

.
.
.

..

... ) :(-

. )
(Pascaline ) .(.
:..

Go ried Wilhelm Leibniz


) (Step Reckoner
: ) .(.
:.. Step Reckoner

Charles Babbage
) Dierence engine (.
.

.

) . (Method of Finite Dierences
:..

.

Analy cal Engine
) .(. ) ( :
) (Memory ) (Computa on Unit )
(Punched Card Reader ) ( .
) (Word
.
) (
.
) (
.
) ( Ada Lovelace
.
.
.
Konrad Zuse
) (Relay ) Z1 (.
.

..
:..

. Z1 .
Z1
. John
:.. Z1

Vincent Atanaso )Atanaso ??(


) (Binray Arithme c .
Howard Aiken - ASCC Harvard Mark
- I ) .(.
.
.Harvard Mark II

.
:.. Atanaso

)(

Mark I

:..

Iowa State

)(
Harvard Mark I

... ) :(-


) Enigma Machine
.
.

..
:..

.Colossus
.

.
John Mauchley


ENIAC .Electronic Numerical Integrator And Computer
) (Vacuum Tubes ) (Relays
.
. .Switch

.
. .

.
:.. colossus

:..

ENIAC

EDSAC . JOHNIAC
. EDVAC
Electronic Discrete Variable Automa c Computer
) (. .
ILLIAC

..

:..

EDVAC

x86

x86 ) (John von Neumann architecture


:
. ).(Central Processing Unit
. ).(Memory
. ).(I/O Devices


). .
( ) (System Bus
.
:..

x86

x86

..
...

System Bus

(System Bus) ) (CPU .


. .
) .(Personal Computers :
) (Data Bus ) (Address Bus ).(Control Bus
:..

.Front-side Bus

x86

..

Data Bus

) (Lines .
) ( ) (Data )
(Control Unit .NorthBridge

).(Padding

.

Address Bus



. 8086
80286/80386



.

Control Bus


. )(
. WRITE
. READ
.
ACCESS

READ and
.WRITE
.

x86

...
) (Controllers .

.
.

) (Port
.
) (Interrupt .
)(NorthBridge
. .
) (Refresh
.
:..

.

...
) (SouthBridge
..

. ) ...(

.
) (Registers .

..

.

)ware Ports

(So

Ports




.
I/O ports in port address out port address

.

ACCESS ) (Control Bus
.
Memory Mapped I/O
.
0xa000:0x0
) (Memory Mapped .
x86 in/out
. port I/O
) (Port I/O
. .

..
.
) (
.

x86

:..

IVT
0x003
0x00000

0x004
0x00400

0x07b
0x00500

0x07d
0x07c00

0x9
0x07e00
Video RAM
0xa
0xa0000
Monochrome VRAM
0xb7777
0xb0000
Color VRAM
0xb
0xb8000
Video ROM BIOS
0xc7f
0xc0000
BIOS Shadow Area
0xe
0xc8000

0xf
0xf0000
x86

...

) (Clock ck .
) (Fetch
.
).(Decode
).(Execute
).(Write back

...

CPU Modes


) (Real Mode

) (hlt

) .(Mul tasking
.

..

x86

:..

Slave DMA controller


System
First Interrupt controller (8259 chip)
Second interrupt controller
Programable Interval Timer 1 (8254 chip)
Programable Interval Timer 2
System devices
NMI Enable / Real Time Clock
DMA Page registers
System devices
Slave interrupt controller
Master DMA controller
System devices
System devices
IDE Interface - Quaternary channel
IDE interface - Secondary channel
IDE Interface - Ter ary channel
IDE interface - Primary channel
Games Port (joys ck port)
Usually used by sound cards, also used by NOVEL NETWARE KEY CARD
Plug and Play hardware
Parallel Port *
Some mes used for LCD Display I/O
Alternate VGA Video Display Adaptor assignment (secondary address)
GPIB 0, data aquisi on card 0 (02E1 to 02E3 only)
Serial Port - COM 4
Serial Port - COM 2
O en used as a default for Network Interface cards (was prototype card)
ST506 and ESDI Hard Disk Drive Interface (mostly used in PX/XT and early PC/AT)
MPU-401 (midi) interface, on Sound Cards
Some mes used for Network Interface cards
Another address used by the Secondary IDE Controller (see 0170-0177)
Parallel Port *
FM (sound) synthesis port on sound cards
MDA, EGA and VGA Video Display Adaptor (only 03B0 to 03BB used)
Parallel Port (originally only ed to IBM mono display adaptors) *
EGA / VGA Video Display Adaptor, (Primary address)
PCIC PCMCIA Port Controller
Serial Port - COM 3
Floppy Disk Drive Interface
Another address used by the Primary IDE Controller (see 01F0-01F7)

Serial Port - COM 1


Windows sound system (used by many sound cards)


0000-000f
0010-001F
0020-0021
0030-0031
0040-0043
0048-004B
0050-006F
0070-0071
0080-008B
0090-009F
00A0-00A1
00C0-00DE
00F0-00FF
0100-0167
0168-016F
0170-0177
01E8-01EF
01F0-01F7
0200-0207
0220-022F
0270-0273
0278-027A
0280-028F
02B0-02DF
02E0-02E7
02E8-02EF
02F8-02FF
0300-031F
0320-023F
0330-0331
0360-036F
0376-0377
0378-037A
0388-038B
03B0-03BB
03BC-03BF
03C0-03DF
03E0-03E7
03E8-03EF
03F0-03F6
03F7-03f7
03F8-03FF
0533-0537

x86

...

Real Mode

x86



) (Protected Mode
. ) (ax,bx,cx,dx,...etc
: ) (Segment:Oset -
- 1 )Virtual
(Memory .
: )(Segment:Oset Addressing
8086
) (
) (Address Bus
.

SRAM .

) (Segments
) (Segment Number or Address
)(Osets
) ( .
Segments
)
- (CS,SS,DS,ES - Oset
.216

..
)
.(0x
) (Logical Address
Segment:Oset
.
) (Oset
) (Segment
. :
0x0

physical address = segment 0x10 + of f set

0x07c0:0x0000 0x07c0 ) 0x10


( 0x07c00 Oset
.0x07c00



.
0x07c0:0x0000 0x07c00
0x0000:0x7c00 .0x07c00
. .
Overlapping
.

...

Protected Mode

80286
) ( . ) (

) .(Descriptor Table 80386

. ) (Paging
) (Base Address ).(Oset
Daniel B. Sedory http://mirror.href.com/thestarman/asm/debug/
.Segments.html

x86

:..

.

.

CPU Rings


.
)(CPU Rings


. ) (Ring0 .(Ring3)
) (Kernel Mode

) (
. ) (User Mode
) cli (hlt
) (Virtual Address Space
. .

) (PMode

..
) (Kernel Mode
.
:..

...

x86

Instruc on Set
) ( ) . (
) (General Protec on Fault
) (Excep on Handler .
x86 ) (General Registers
) (Segments Registers
) (
. :
RAX (EAX(AX/AH/AL)), RBX (EBX(BX/BH/BL)), RCX (ECX(CX/CH/CL)), RDX :
)).(EDX(DX/DH/DL

:
. CS,SS,ES,DS,FS,GS:
RSI (ESI (SI)), RDI (EDI (DI)), RBP (EBP (BP)). RSP (ESP (SP)), RIP (EIP :
)).(IP
.RFLAGS (EFLAGS (FLAGS)) :
.DR0, DR1, DR2, DR3, DR4, DR5, DR6, DR7 :

x86

:..

LGDT GDTR
LLDT LDTR
LTR
MOV cr x
LMSW new Machine Status WORD
MOV dr x
CLTS Task Switch Flag
INVD
INVLPG
WBINVD
HLT
RDMSR
WRMSR
RDPMC
RDTSC

Invalidate Cache without writeback


Invalidate TLB Entry
Invalidate Cache with writeback



MSR
Performance Monitoring Counter
me Stamp Counter
MSR

.CR0, CR1, CR2, CR3, CR4, CR8 :

.TR1, TR2, TR3, TR4, TR5, TR6, TR7 :

mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, xmm0, xmm1, xmm2, :
.xmm3, xmm4, xmm5, xmm6, xmm7, GDTR, LDTR, IDTR, MSR, and TR

General Purpose Registers

) (
: ) (High Order Word )Low
(Order Word : )High
(Order Byte ) (Low Order Byte .
EAX ) ( AX
AH .AL
.

:EAX .

..

:EBX
.Base Address

:ECX .

:EDX .

Segment Registers

) (Segments
:

:CS .

:DS .

:SS .

:ES .

:FS .

:GS .

) (PMode
)
( -
.-

Oset Registers


x86
. :

:SI .

:DI .

:BP
.

x86

:SP .

Instruc on Pointer

) (IP ) (CS
CS:IP . ) (EIP
) (IP
MOV .

FLAGS Register

) (EFLAGS ) (FLAGS
) (
) (Status
) (Control ) .(System .
.
IOPL ) (CLI,STI,IN,OUT
Current Priviledge Level
IOPL
).(Ring0

Control Registers

CR0, CR1, CR2,CR3, CR4,

CR8
) (Kernel Moder/Ring0 .
CR0
) (PMode )(Paging
CR0 .
Bit 0 (PE) : Puts the system into protected mode.
Bit 1 (MP) : Monitor Coprocessor Flag This controls the opera on of the WAIT instruc on.
Bit 2 (EM) : Emulate Flag. When set, coprocessor instruc ons will generate an excep on

) (Ring0 .

..

EFLAGS

:..

Carry Flag - Status bit

Parity Flag

Adjust Flag - Status bit

Zero Flag - Status bit


Sign Flag - Status bit
Trap Flag - System Flag
Interrupt Enabled Flag - System Flag
Direc on Flag - Control Flag
Overow Flag - Status bit
I/O Priviledge Level - Control Flag
Nested Task Flag - Control Flag

Resume Flag (386+ Only) - Control Flag


v8086 Mode Flag (386+ Only) - Control Flag
Alignment Check (486SX+ Only) - Control Flag
Virtual Interrupt Flag (Pen um+ Only) - Control Flag
Virtual Interrupt Pending (Pen um+ Only) - Control Flag
Iden ca on (Pen um+ Only) - Control Flag

CF
PF
AF
ZF
SF
TF
IF
DF
OF
IOPL
NT
RF
VM
AC
VIF
VIP
ID
-

0
1
2
3
4
5
6
7
9
9
10
11
12-13
14
15
16
17
18
19
20
21
22-31

x86

Bit 3 (TS) : Task Switched Flag This will be set when the processor switches to another task.
Bit 4 (ET) : ExtensionType Flag. This tells us what type of coprocesor is installed.
0 - 80287 is installed
1 - 80387 is installed.
Bit 5 (NE): Numeric Error
0 - Enable standard error repor ng
1 - Enable internal x87 FPU error repor ng
Bits 6-15 : Unused
Bit 16 (WP): Write Protect
Bit 17: Unused
Bit 18 (AM): Alignment Mask
0 - Alignment Check Disable
1 - Alignment Check Enabled (Also requires AC ag set in EFLAGS and ring 3)
Bits 19-28: Unused
Bit 29 (NW): Not Write-Through
Bit 30 (CD): Cache Disable
Bit 31 (PG) : Enables Memory Paging.
0 - Disable
1 - Enabled and use CR3 register

.II

Boo ng

Bootloader



.
FAT12
.

..
) (Boot-Strapping

) ( MotherBoard )Power Supply
.(Unit PSU
Power Good . BIOS
) ( Power on Self Test
POST ) ...(
. POST BIOS POST
BIOS 0xFFFF0 ) ( jump
POST CS:IP
. BIOS BIOS
) ( Interrupt Vector Table

BIOS Setup BIOS
) ( Halt
BIOS )
( 0x07c00 .
) ( bit 1 .

Bootloader

) ( BIOS
0x0
.
int 0x19
0x07c00 .
) (
0xAA55
.
Real Mode Protected Mode
- ) ( Excep on .

..

Bootloader

.
:
. 512 .
. : 1 0 0
.
. .
.
. Flat Binary

object code

header,symbol table,...etc


32-bit
) ( A20
.

. Mul -Stage Boot Loader
:
1

Safe Mode

..



0xAA55
510 . 511 ) (0x19
.
!
. 32-bit 16-bit

- - 16-bit
.
) ( ELF,PE,COFF,...etc

-
. -
Object Code .Flat Binary
) (Assembly 16-bit
)
( Backward Compa bility 16-bit
- - 32-bit
run- me library .Machine Language
!
) ( GRUB,NTLDR,LILO...etc
run- me loader
. main

..
. .

Bootloader

:..

0x07c00
) (
) (Memory Mapped
0xf0000
). (Memory Mapped

..
. NASM
. object code
oppy disk or CD
). (Virtual Machine

..
.: Smallest Bootloader

Example

;Simple Bootloader do nothing.

; 16bit real mode.

bits 16

; label are pointer.


; clear interrupt.
; halt the system.
; append zeros.

db

start:

cli
hlt

) times 510($$$

; $ is the address of first instruction (should be 0x07c00).


; $$ is the address of current line.
; $$$ means how many byte between start and current.

; if cli and hlt take 4 byte then time directive will fill
; 5104 = 506 zero's.

; finally the boot signature 0xaa55


db
0x55 ; first byte of a boot signature.
db
0xaa ; second byte of a boot signature.

0x0000:0x7c00
) (real mode
cli hlt
)(garbage
) (Crash . 512
510
0xaa55 times 510
) (
.

...
.
int 0x10 . 0xe

Bootloader

Example

.: Welcom to OS World

;Hello Bootloader

; 16bit real mode.


; this number will added to all addresses (relocating).

bits 16
org

0x0

start:

jmp main

; jump over data and function to entry point.

; data
;

hello msg

db

"Welcome to eqraOS, Coded by Ahmad Essam",0xa,0xd,0

; puts16: prints string using BIOS interrupt


;
;
;
;

input:
es: pointer to data segment.
si: point to the string

puts16:

lodsb
; read character from ds:si to al ,and increment si if
df=0.

cmp al,0
; check end of string ?
je end puts16 ; yes jump to end.

mov ah,0xe
int 0x10

; print character routine number.


; call BIOS.

jmp puts16

; continue prints until 0 is found.

end puts16:

..

ret

;
;
;

entry point of bootloader.

main:

;
; intit registers
;

; because bootloader are loaded at 0x07c00 we can refrence this


location with many different combination of segment:offset
addressing.

; So we will use either 0x0000:0x7c000 or 0x:07c0:0x0000 , and in


this example we use 0x07c0 for segment and 0x0 for offset.

mov ax,0x07c0
mov ds,ax
mov es,ax

mov si,hello msg


call puts16

cli
hlt

; clear interrupt.
; halt the system.

times 510($$$ )

db

; append zeros.

; finally the boot signature 0xaa55


db
0x55
db
0xaa

code segment
( 512 )
.
cs:ip far jump
data segment

Bootloader

.ds,es,ss,fs,gs
0x07c00 4000
0x07c0:0x0 0x0:0x7c00
.
) 0x07c0
( ) (label 0x0
0x0
org ) (reloca ng
0x0
0x0
0x7c00 0x0
org relocate . 0x7c00

...
boot sector
OEM
) BIOS Parameter Block (BPB
. 3
.
.: Bios Parameter Block

Example

; Name of your OS, Must

"

OEM ID

db
"eqraOS
be 8 byte! no more no less.

0x200
0x1
0x1

dw
db
dw

; two fats.
; root dir has 224

0x2
0xe0

db
dw

; 2880 sectors in the

0xb40

dw

; 512 byte per sector.


; 1 sector per cluster.
; boot sector is

bytes per sector


sectors per cluster
reserved sectors

reserved.
total fats
root directory

entries.
total sectors

volume.

..
media descriptor
sectors per fat
sectors per track
number of heads
hidden sectors
total sectors large

db
dw
dw
dw
dd
dd

0xf0
0x9
0x12
0x2
0x0
0x0

;
;
;
;
;

1.44 floppy disk.


9 sector per fat.
18 sector per track.
2 heads per platter.
no hidden sector.

; Extended BPB.

drive number

db
db
signature
db
volume id
dd
when foramt the disk.
volume label
db
system id
db

flags

0x0
0x0
0x29
0x0

; must be 0x28 or 0x29.


; serial number written

"MOS FLOPPY " ; 11 byte.


"fat12
"
; 8 byte.

.OEM and BPB .


Example

.: BPB example

;Hello Bootloader

bits 16
org

0x0

; 16bit real mode.


; this number will added to all addresses (relocating).

start:

jmp main

; jump over data and function to entry point.

;
; OEM Id and BIOS Parameter Block (BPB)

; must begin at byte 3(4th byte), if not we should add nop

instruction.

OEM ID

db
"eqraOS
be 8 byte! no more no less.

"

; Name of your OS, Must

Bootloader
bytes per sector
sectors per cluster
reserved sectors

dw
db
dw

0x200
0x1
0x1

db
dw

0x2
0xe0

; two fats.
; root dir has 224

dw

0xb40

; 2880 sectors in the

db
dw
dw
dw
dd
dd

0xf0
0x9
0x12
0x2
0x0
0x0

;
;
;
;
;

; 512 byte per sector.


; 1 sector per cluster.
; boot sector is

reserved.
total fats
root directory

entries.
total sectors

volume.
media descriptor
sectors per fat
sectors per track
number of heads
hidden sectors
total sectors large

1.44 floppy disk.


9 sector per fat.
18 sector per track.
2 heads per platter.
no hidden sector.

; Extended BPB.

drive number

db
db
signature
db
volume id
dd
when foramt the disk.
volume label
db
system id
db

flags

0x0
0x0
0x29
0x0

; must be 0x28 or 0x29.


; serial number written

"MOS FLOPPY " ; 11 byte.


"fat12
"
; 8 byte.

; data
;

hello msg

db

"Welcome to eqraOS, Coded by Ahmad Essam",0xa,0xd,0

; puts16: prints string using BIOS interrupt


;
;
;
;

input:
es: pointer to data segment.
si: point to the string

puts16:

..

lodsb
; read character from ds:si to al ,and increment si if
df=0.

cmp al,0
; check end of string ?
je end puts16 ; yes jump to end.

mov ah,0xe
int 0x10

; print character routine number.


; call BIOS.

jmp puts16

; continue prints until 0 is found.

end puts16:

ret

;
;
;

entry point of bootloader.

main:

;
; intit registers
;

; because bootloader are loaded at 0x07c00 we can refrence this


location with many different combination
; of segment:offset addressing.

; So we will use either 0x0000:0x7c000 or 0x07c0:0x0000


; and in this example we use 0x07c0 for segment and 0x0 for
offset.

mov ax,0x07c0
mov ds,ax
mov es,ax

mov si,hello msg


call puts16

Bootloader

cli
hlt

; clear interrupt.
; halt the system.

times 510($$$ )

db

; append zeros.

; finally the boot signature 0xaa55


db
0x55
db
0xaa

Hex Editor .
) (
.
Example

.: Hex value of bootloader

O f f s e t ( h ) 00 01 02 03 04 05 06 07
00000000
00000008
00000010
00000018
00000020
00000028
00000030
00000038
00000040
00000048
00000050
00000058
00000060
00000068
00000070
00000078
00000080
00000088

000001F0

E9
53
02
12
00
00
4C
74
6C
20
20
79
45
AC
10
8E
E6
00

72
20
E0
00
00
00
4F
31
63
65
43
20
73
3C
E9
D8
FF
00

00
20
00
02
00
00
50
32
6F
71
6F
41
73
00
F4
8E
FA
00

65
00
40
00
00
4D
50
20
6D
72
64
68
61
74
FF
C0
F4
00
...
...
00 00 00 00

71
02
0B
00
00
4F
59
20
65
61
65
6D
6D
07
C3
BE
00
00

72
01
F0
00
00
53
20
20
20
4F
64
61
0A
B4
B8
3E
00
00

61
01
09
00
29
20
66
57
74
53
20
64
0D
0E
C0
00
00
00

4F
00
00
00
00
46
61
65
6F
2C
62
20
00
CD
07
E8
00
00

00 00 00 00

r . eqraO
S .....
. .@ . . .
........
......).
. . . MOS F
LOPPY f a
t12
We
lcome t o
eqraOS ,
Coded b
y Ahmad
Essam . . .
<. t . .
. .
..>.
. . . .
........

........

..
000001F8

00 00 00 00 00 00 55 AA

. . . . . . U


!

Disassembler
.
Example

.: Complete Example

;Hello Bootloader

bits 16
org

0x0

; 16bit real mode.


; this number will added to all addresses (relocating).

start:

jmp main

; jump over data and function to entry point.

;
; OEM Id and BIOS Parameter Block (BPB)

; must begin at byte 3(4th byte), if not we should add nop

instruction.

OEM ID

db
"eqraOS
be 8 byte! no more no less.

"

; Name of your OS, Must

bytes per sector


sectors per cluster
reserved sectors

reserved.
total fats
root directory
entries.
total sectors
volume.
media descriptor

dw
db
dw

0x200
0x1
0x1

db
dw

0x2
0xe0

; two fats.
; root dir has 224

dw

0xb40

; 2880 sectors in the

db

0xf0

; 1.44 floppy disk.

; 512 byte per sector.


; 1 sector per cluster.
; boot sector is

.source code

Bootloader
sectors per fat
sectors per track
number of heads
hidden sectors
total sectors large

dw
dw
dw
dd
dd

0x9
0x12
0x2
0x0
0x0

;
;
;
;

9 sector per fat.


18 sector per track.
2 heads per platter.
no hidden sector.

; Extended BPB.

drive number

db
db
signature
db
volume id
dd
when foramt the disk.
volume label
db
system id
db

flags

0x0
0x0
0x29
0x0

; must be 0x28 or 0x29.


; serial number written

"MOS FLOPPY " ; 11 byte.


"fat12
"
; 8 byte.

; data
;

hello msg

db

"Welcome to eqraOS, Coded by Ahmad Essam",0xa,0xd,0

; puts16: prints string using BIOS interrupt


;
;
;
;

input:
es: pointer to data segment.
si: point to the string

puts16:

lodsb
; read character from ds:si to al ,and increment si if
df=0.

cmp al,0
; check end of string ?
je end puts16 ; yes jump to end.

mov ah,0xe
int 0x10

; print character routine number.


; call BIOS.

..

jmp puts16

; continue prints until 0 is found.

end puts16:

ret

;
;
;

entry point of bootloader.

main:

;
; intit registers
;

; because bootloader are loaded at 0x07c00 we can refrence this


location with many different combination
; of segment:offset addressing.

; So we will use either 0x0000:0x7c000 or 0x07c0:0x0000


; and in this example we use 0x07c0 for segment and 0x0 for
offset.

mov ax,0x07c0
mov ds,ax
mov es,ax

mov si,hello msg


call puts16

cli
hlt

; clear interrupt.
; halt the system.

times 510($$$ )

db

; append zeros.

; finally the boot signature 0xaa55


db
0x55
db
0xaa

Bootloader

...

int 0x13




.
. int 0x13

sector
0x0 int 0x13

.
:

.0x0 : ah

: dl .0x0

: ah.

0x1 : CF 0x0 .

:
.: Reset Floppy Drive

Example

reset floppy:

; reset floppy routine number.


; drive number

mov ah,0x0
mov dl,0x0

; call BIOS

int 0x13

; try again if error occur.

jc reset floppy

..

sectors


) (sectors . RAM
:
:ah 0x2
:al .

int 0x13

0x2

:ch ) (Cylinder .

:cl 5 - 0
.disk
:dh .

: dl .0x0

: es:bx .

hard

:
: ah.
:al .

0x1 : CF 0x0 .

:
.: Read Floppy Disk Sectors

Example

read sectors:

reset floppy:

; reset floppy routine number.


; drive number

mov ah,0x0
mov dl,0x0

; call BIOS

int 0x13

; try again if error occur.

jc reset floppy

Bootloader

; init buffer.
mov ax,0x1000
mov es,ax
xor bx,bx

read:

mov
mov
mov
mov

ah,0x2
; routine number.
al,1
?; how many sectors
ch,1
; cylinder or track number.
cl,2
; sector number "fisrt sector is 1 not 0",now we read
the second sector.
mov dh,0
; head number "starting with 0".
mov dl,0
; drive number ,floppy drive always zero.

; call BIOS.
; if error, try again.

int 0x13
jc read

; jump to execute the second sector.

..

jmp 0x1000:0x0

FAT12




bad sectors
Defragmenta on
.
!
!
:

).(Driver

Data Structure .

..

FAT12


FAT12
.

...

FAT12

FAT12
: FAT12

.Root Directory

) (Cluster 12 .212

12.

4077 .

16

0x01

)ons

MB

.32

.(Par

... FAT12
(Format) FAT12 : .
:.. FAT12


. FAT12

Bootloader

) (Boot Sector ) (
BPB and OEM id : 1 0
0 int 0x13
.
Absolute Sector
.
) (Logical Sector Addressing
LBA )(Boot Sector
0 1 .
) int 0x13
( -
.- ) (
Extra Reserved Sectors
FAT
reserved sectors BPB
) (
2 0 0 .1
. FAT
12 ) (Cluster



) 12( :

:0x00 .

: 0x01 .

0x02 : 0xfef )
(.

0xff0 :0xff6 .

: 0xff6 .Bad Cluster

0xff8 :0xfff .

..

FAT12

FAT
) Root Directory ( index
FAT 0x02 0xfef
index
. FAT 1 9
10

. FAT
backup Root Directory
224 32


index FAT
.
root directory :

:7-0 ) 8
(.

:10-8 ) (.

:11 :
:0 .
:1.
:2 .
:3 .Volume Label
:4 .
:5.
:6.
:7 .

:12 .

:13 .MS

Bootloader

:15-14 :
:4-0 ).(29-0
:10-5 ).(59-0
:15-11 ).(23-0
:17-16 :
:4-0 ).(2107=127 ;1980=0
:8-5 )=1; =12(.
:15-9 ).(23-0
:19-18 ) (.
.EA index :21-20
:23-22 ) .(15-14
:25-24 ) .(17-16

:27-26 .
:29-28 .

Fixed Lenght Record


8
.Space

...
) Pla er ( ) (Tracks
.
1.44 MB 80 ) 0 (79 18
80 18 2 2880.

) ( : 1 0 0
: 2 0 0
18 0 0
: 1 0 1
...
.

..

...

FAT12

FAT12

) (

FAT12 ) Root
(directory
FAT12
FAT
. Root directory
Second Stage Bootloader

32.

:
FAT12

. Root Directory
.
. FAT .
. .


FAT12
Root Directory FAT

FAT12

. .
.: Hello Stage2

Example

; Second Stage Bootloader.


; loaded by stage1.bin at address 0x050:0x0 (0x00500).

Bootloader

bits 16
org

0x0

; 16bit real mode.


; offset to zero.

start:

jmp stage2

; data and variable


hello msg db

"Welcome to eqraOS Stage2",0xa,0xd,0

; include files:
%include "stdio.inc"

; standard i/o routines.

; entry point of stage2 bootloader.


;

stage2:

push cs
pop ds

; ds = cs.

mov si,hello msg


call puts16

cli
hlt

; clear interrupt.
; halt the system.

stage2.asm
3 8
.Root Directory Spaces FAT12
(FAT12 )
.( )
stage2.sys

FAT12

..
Root Directory

Root Directory
( stage2.sys )
. "stage2 sys"

.( Buer)
.
Example

.: Load Root directory

;
; Compute Root Directory Size
;

xor cx,cx
mov ax,32
; every root entry size are 32 byte.
mul word[root directory] ; dx:ax = 32224 bytes
div word[bytes per sector]
xchg ax,cx
; cx = number of sectors to load.
;
; Get start sector of root directory
;

mov al,byte[total fats]


; there are 2 fats.
mul word[sectors per fat]
; 92 sectors
add ax,word[reserved sectors] ; ax = start sector of root
directory.

mov word[data region],ax


add word[data region],cx

; data region = start sector of data.

;
; Load Root Dir at 0x07c0:0x0200 above bootloader.
;

mov bx,0x0200
; es:bs = 0x07c0:0x0200.
call read sectors

Bootloader



. .
Example

.: Find Stage2 Bootloader

;
; Find stage2.sys
;

mov di,0x0200
; di point to first entry in root dir.
mov cx,word[root directory] ; loop 224 time.

find stage2:

mov si,kernel loader name


push cx
push di
mov cx,11
; file name are 11 char long.

rep cmpsb
pop di
je find successfully

mov di,32
pop cx

; point to next entry.

loop find stage2

; no found ?
jmp find fail

find successfully:
;
; Get first Cluster.
;

mov ax,word[di+26]
; 27 byte in the di entry are cluster
number.
mov word[cluster number],ax

..

FAT12

FAT
FAT

Root Directory .
Root Directory FAT
.
.
.: Load FAT Table

Example

;
; Compute FAT size
;

xor cx,cx
xor ax,ax
xor dx,dx

; there are 2 fats.


; 92 sectors

]mov al,byte[total fats


]mul word[sectors per fat
xchg ax,cx
;
; Get start sector of FAT
;

]add ax,word[reserved sectors


;
; Load FAT at 0x07c0:0x0200
; Overwrite Root dir with FAT, no need to Root Dir now.
;

mov bx,0x0200
call read sectors

Bootloader


Sector FAT12
Cluster Internel
Fragmenta on FAT12
.
Absolute Address
LBA .
Cluster LBA :
.: Convert Cluster number to LBA

Example

; cluster to lba: convert cluster number to LBA


;

input:
;
ax: Cluster number.
; output:
;
ax: lba number.
;
cluster to lba:
; lba = (cluster 2) sectors per cluster
; the first cluster is always 2.

sub ax,2

xor cx,cx
]mov cl, byte[sectors per cluster
mul cx

; cluster start from data area.

]add ax,word[data region


ret

2 FAT12 - 2
.-
LBA : Absolute Address
.: Convert LBA to CHS

Example

; lba to chs: Convert LBA to CHS.

FAT12
;
;
;
;
;
;
;

..

input:
ax: LBA.
output:
absolute sector
absolute track
absolute head

lba to chs:

; absolute sector =
; absolute track =
; absolute head
=

(lba % sectors per track) + 1


(lba / sectors per track) / number of heads
(lba / sectors per track) % number of heads

xor
div
inc
mov

dx,dx
word[sectors per track]
dl
byte[absolute sector],dl

xor
div
mov
mov

dx,dx
word[number of heads]
byte[absolute track],al
byte[absolute head],dl

ret

Root Directory
Abolsute Address LBA LBA
. int 0x13
Example

.: Load Cluster

;
; Load all clusters(stage2.sys)
; At address 0x050:0x0
;

xor bx,bx
mov ax,0x0050
mov es,ax

load cluster:

Bootloader

mov ax,word[cluster number]


; ax = cluster number
call cluster to lba
; convert cluster number to LBA
addressing.

xor cx,cx
mov cl,byte[sectors per cluster]

; cx = 1 sector

call read sectors bios

; load cluster.

int 0x13
.32-bit
Example
;

.: Read Sectors Rou

ne

; read sectors bios: load sector from floppy disk


;
;
;
;
;

input:
es:bx : Buffer to load sector.
ax:
first sector number ,LBA.
cx:
number of sectors.

read sectors bios:

begin:
mov di,5

; try 5 times to load any sector.

load sector:

push ax
push bx
push cx

call lba to chs

mov
mov
mov
mov
mov
mov

ah,0x2
; load sector routine number.
al,0x1
; 1 sector to read.
ch,byte[absolute track]
; absolute track number.
cl,byte[absolute sector] ; absolute sector number.
dh,byte[absolute head]
; absolute head number.
dl,byte[drive number]
; floppy drive number.

FAT12

..

int 0x13

; call BIOS.

jnc continue

; if no error jmp.

; reset the floppy and try read again.

mov ah,0x0
mov dl,0x0
int 0x13

; reset routine number.


; floppy drive number.
; call BIOS.

pop cx
pop bx
pop ax

dec di
jne load sector

; error.
int 0x18

continue:

mov si,progress msg


call puts16

pop cx
pop bx
pop ax

add ax,1
; next sector
add bx,word[bytes per sector] ; point to next empty block in
buffer.

loop begin

; cx time

ret

FAT

Bootloader

.
FAT 12
0 FAT 12
16 ) ( mask 4
) ( . 1
FAT 23-12 12 16
23-8 4.
:

)cluster = cluster + (cluster/2

16 Mask 4
4 .
.
.: Read FAT entry

Example

read cluster fat entry:

]mov ax,word[cluster number


Every FAT entry are 12bit long( byte and half one).
so we must map the cluster number to this entry.
to read cluster 0 we need to read fat[0].
cluster 1 > fat[1].
cluster 2 > fat[3],...etc.

;
;
;
;
;

cx,ax
; cx = cluster number.
cx,1
; divide cx by 2.
cx,ax
; cx = ax + (ax/2).
di,cx
di,0x0200
dx,word[di] ; read 16bit form FAT.

mov
shr
add
mov
add
mov

; Now, because FAT entry are 12bit long, we should remove 4


bits.
; if the cluster number are even, we must mask the last four
bits.
; if it odd, we must do four right shift.

FAT12

..

test ax,1
jne odd cluster

even cluster:

and dx,0x0fff
jmp next cluster

odd cluster:

shr dx,4

next cluster:
mov word[cluster number],dx

; next cluster to load.

cmp dx,0x0ff0
jb load cluster

; check end of file, last cluster?


; no, load the next cluster.

; yes jmp to end


jmp end of first stage

find fail:

mov si,fail msg


call puts16

mov ah,0x0
int 0x16
int 0x19

; wait keypress.
; warm boot.

end of first stage:

; jump to stage2 and begin execute.


push 0x050
; segment number.
push 0x0
; offset number.

retf

; cs:ip = 0x050:0x0

Bootloader

times 510($$$ )

db

; append zeros.

; finally the boot signature 0xaa55


db
0x55
db
0xaa

. -

stage 2
:

.PMode

A20 4 .

.Interrupt Handler

.Safe Mode

Boot

Mul .

..
Real Mode
1
Paging Virtual Memory .

cr0

Descriptor Table General Protec on
Fault GPF triple fault .
) (Global Descriptor Table GDT


.

. -

...

Global Descriptor Table

PMode

. ) (Code
) (Data .
GDT ) Descriptors 64( :
GDT

:Null Descriptor .

:Code Descriptor .Code

:Data Descriptor .Data

Descriptor :

:15-0 ) (15- 0 .

:39-16 .Base Address

:40 ) Access Bit .(Virtual Memory

:41-43 :Descriptor Type


:41 :
:Data Descriptor 0 1 .
:Code Descriptor 0 execute 1 .
.Expansion direc on (Data segments), conforming (Code Segments) :42
:43 :
:0 .
:1 .

:Descriptor Bit :44


.System descriptor:0
.Code or Data Descriptor :1
:46-45 Privilege Level
.(Ring 0) Highest :0
.(Ring 3) Lowest :3

..
.Segment is in memory (Used with Virtual Memory) :47
. 19- 16 :51-48

. :52
. :53
:Segment type :54
. 16 :0
. 32 :1

:Granularity :55
.None :0
.Limit gets mul plied by 4K :1
.Base Address 32- 23 :63-56

Code and Data Descriptor


.0xffffffff
Example

.: GDT

;
; Global Descriptor Table

begin of gdt:

; Null Descriptor: start at 0x0.

dd
dd

0x0
0x0

; fill 8 byte with zero.

; Code Descriptor: start at 0x8.

dw
dw
db
db
db
db

0xffff
0x0
;
0x0
;
10011010b
11001111b
0x0
;

; limit low.
base low.
base middle.
; access byte.
; granularity byte.
base high.

. -

; Data Descriptor: start at 0x10.

; limit low.
base low.
base middle.
; access byte.
; granularity byte.
base high.

0xffff
0x0
;
0x0
;
10010010b
11001111b
0x0
;

dw
dw
db
db
db
db

end of gdt:

Null Descriptor 8
Code Descriptor

Kernel Mode .
.
Code Descriptor 0x8
CS 15-0 Segment Limit 0xffff
.0xffff
39-16 23-0 Base Address
0x0 0x0 . 0x
6 Access Byte
:
Access Bit :0 .0

:3 1 .Code Segment

:4 1 .

:6-5 0
Ring0 .Kernel Mode
:7 .

:1 1
.0xffff-0x0
on :2

expansion direc .0

..
7 granularity
:

:3-0 19-16 Segment Limit 0xf


0xfffff 1
A20 4 .
:5-4 .

:6 1 32.

:7 1

KB

.4

) (8 32-24
0x0 0x0 .
Code Descriptor
.Code Segment
Data Descriptor 0x10
43 .
) (GDT gdtr
GDT
) lgdt (Ring0 .
.: Load GDT into GDTR

Example

; real mode.

16

bits

;
; load gdt: Load GDT into GDTR.
;

load gdt:

cli
; clear interrupt.
pusha
; save registers
]lgdt [gdt ptr
; load gdt into gdtr
sti
; enable interrupt
popa
; restore registers.

. -
ret

;
; gdt ptr: data structure used by gdtr

gdt ptr:

dw end of gdt begin of gdt 1


; size 1
dd begin of gdt
; base of gdt

...

PMode Memory Addressing

Segment:Oset
) (Segments Registers
0x10 oset
.Address Bus
PMode Descriptor:Oset
) CS 0x8 DS
(0x10 oset Base Address
Segment Limit
.
32-bit 4 .

...
GDT GDTR
cr0
.

CS far jump
.
A20 .

..
Example

.: Switching to Protected Mode

;
; Load gdt into gdtr.
;

call load gdt


;
; Go to PMode.
;
; just set bit 0 from cr0 (Control Register 0).

cli
; important.
mov eax,cr0
or eax,0x1
mov cr0,eax
; entering pmode.

;
; Fix CS value
;
; select the code descriptor
jmp 0x8:stage3

;
; entry point of stage3

bits 32

; code now 32bit

stage3:

;;
; Set Registers.
;;

mov ax,0x10
mov ds,ax
mov ss,ax

; address of data descriptor.

. -
; stack begin from 0x90000.

mov es,ax
mov esp,0x90000

;;
; Hlat the system.
;;
cli
; clear interrupt.
hlt
; halt the system.

..

A20

A20 Gate OR Gate System Bus


Address Line ) (80286
20 )( ) (20 address line IBM PC
80286 32 4
A20
A31-A20.
8042 ) (Keyboard Controller
1 ) (output data port
A20 4 0xffffffff-0x0

.

.

... 8042

A20

) (PMode
. A20

in .out

20

..

A20

) (8042 Integrated Circuit


) (Motherboard .South Bridge
Make Code
8042
). (Hardware Port 8042 Make code Scan Code
Buer 0x60 IBM and Compa ble PC
) (in .

.A20

...

A20

System Control Port 0x92

I/O part 0x92 A20



:

:0 reset .

:1 0 A20 1.
:2 .
power on password bytes :3
:5-4 .
: HDD ac vity LED :7-6 o :0 :1

.on

.
.: Enable A20 by System Control Port 0x92

Example

;
; enable a20 port 0x92:

Enable A20 with System Control port 0x92

enable a20 port 0x92:

. -
push ax

; save register.

mov al,2
; set bit 2 to enable A20
out 0x92,al

pop ax
ret

; restore register.


.

int 0x15 0x2401 A20
.
.
0x2400

.: Enable A20 by BIOS int 0x15

Example

;
; enable a20 bios:

Enable A20 with BIOS int 0x15 routine 0x2401

enable a20 bios:

; save all registers

pusha

mov ax,0x2401 ; Enable A20 routine.


int 0x15

; restore registers

popa
ret


: 0x60 ) buer
Buer Input Buer 0x64
Output

..

A20

) .(Status 0x64
) buer (0x60 .0x60
) (
) (
.
) (0x64
.
:

:0 :Output Buer
:0 Output Buer ) (.
:1 Output Buer ) (.

:1 :Input Buer
:0 Input Buer ) (.
:1 Input Buer ) (.

) (wait input
).(wait output
.: Wait Input/Output

Example

;
; wait output: wait output buffer to be full.
;

wait output:

in al,0x64
; read status
test al,0x1
?; is output buffer is empty
je wait output ; yes, hang.

; no,there is a result.

ret

;
; wait input: wait input buffer to be empty.

. -

command executed already.

wait input:

in al,0x64
; read status
test al,0x2
?; is input buffer is full
jne wait input ; yes, hang.

; no,command executed.

ret

0x64

.
:
:0xad .

:0xae .

:0xd0 .Output Port

:0xd1 .Output Port


:0xdd .A20

:0xdf .A20

0xdd A20
.
.: Enable A20 by Send 0xdd

Example

;
; enable a20 keyboard controller:

Enable A20 with command 0xdd

enable a20 keyboard controller:

;cli

..
; save register.

push ax

A20

; Enable A20 Keyboard Controller Command.

mov al,0xdd
out 0x64,al

; restore register.

pop ax
ret

Output Port
0xd0 0xd1 .
) d0 ( :

:System Reset :0
.Reset Computer :0
.Normal Opera on :1

:1 :A20
:0.
:1.

:3-2 .

.Input Buer Full :4

.Output Buer Empty :5

:Keyboard Clock :6
.High-Z :0
.Pull Clock Low :1

:Keyboard Data :7
.High-Z :0
.Pull Data Low :1

1 A20 or
. . 0xd1
A20 Output Port .

- .
Example

.: Enable A20 by write to output port of Keyboard Controller

;
; enable a20 keyboard controller output port:
;

Enable A20 with write to keyboard output port.

enable a20 keyboard controller output port:

cli
pusha

; save all registers

call wait input

; wait last operation to be finished.

;
; Disable Keyboard
;
mov al,0xad
; disable keyboard command.
out 0x64,al
call wait input
;
; send read output port command
;
mov al,0xd0
; read output port command
out 0x64,al
call wait output
; wait output to come.
; we don't need to wait input bescause when output came we know
that operation are executed.
;
; read input buffer
;
in al,0x60
push eax
; save data.
call wait input
;
; send write output port command.
;

..
mov al,0xd1
; write output port command.
out 0x64,al
call wait input
;
; enable a20.
;
pop eax
or al,2
; set bit 2.
out 0x60,al
call wait input
;
; Enable Keyboard.
;
mov al,0xae
; Enable Keyboard command.
out 0x64,al
call wait input

VGA

; restore registers

popa
sti

ret

) (0xad wait input


) (0xda
wait output
) (Stack
) (0xd1
1 A20
.

..

VGA

1987 IBM Video Graphics Array


VGA Array signle chip
MDA CGA EGA VGA

. -
Graphics Controller , Sequencer unit , CRT Controller , Video DAC ,Video Buer
. Controller
Video Buer segment of memory Memory Mapped
0xa0000
Memory Mapping
Graphics Controller
.Video buer
VGA Text Mode APA Graphics
Mode Video buer .
All Point Addressable Graphics Mode
. .
Text Mode Characters Video
Controller two buers Character Map
Screen
Buer .
VGA Monochrome Display Adapter
MDA IBM 1981 MDA
) (Mode 7 80 24 ) .(25*80 IBM
) Color Graphics Adapter (CGA 16
. .Enhanced Graphics Adapter
VGA Backward Compa ble
) Mode 7 (MDA
80 25.
A ribute

...

VGA

0xa0000 0xbffff
) Video memroy (VGA :

0xb0000 :0xb7777 .Monochrome Text Mode

0xb8000 .Color Text Mode :0xbffff


A .
.

..
.: Print 'A' character on screen

VGA

Example

; Base Address of Mapped Video

0xb8000

%define VIDEO MEMORY

Memory.
; White chracter on black background.

0x7

%define CHAR ATTRIBUTE

mov edi,VIDEO MEMORY

; print A
; in white foreground black

' mov [edi],'A

mov [edi+1],CHAR ATTRIBUTE

background.

...
Video Memory
) (x,y
.Video Memoey ) (x,y ) (0,0
Video Memory
.(Color text Mode) 0xb8000 ) (x,y ) (0,1
0xb8001 ) (x,y Video
:Memory
videomemory = 0xb0000
videomemory+ = x + y 80

80 y . 80
). (4,4
address = x + y 80

address = 4 + 4 80 = 324
; now add the base address of video memory.
address = 324 + 0xb8000 = 0xb8144

0xb8144
) (.
Mode 7

. -
A
0xb8000 0xb8001
.
) ( :

:2-0 :
:0.
:1.
:2.
:3 ) 0 1 (.

:6-4 :
:0.
:1.
:2.
:7 ) 0 1 (.

4 :

0: Black.
1: Blue.

2: Green.
3: Cyan.
4: Red.

5: Magneta.
6: Brown.

7: Light gray.

8: Dark Gray.
9: Light Blue.

10: Light Green.


11: Light Cyan.

VGA

..

12: Light Red.


13: Light Magneta.
14: Light Brown.
15: White.

Mode 7
( underline ) Cursor

putch32 . 0xa
.PMode
Example

.: putch32 rou

ne

; putch32: print character in protected mode.


;
;
;

input:
bl: character to print.

bits

32

%define VIDEO MEMORY

0xb8000

Memory.
%define COLUMNS
80
%define ROWS
25
%define CHAR ATTRIBUTE

; Base Address of Mapped Video

; text mode (mode 7) has 80 columns,


; and 25 rows.
31
; white on blue.

x pos
y pos

db
db

0
0

; current x position.
; current y position.

putch32:

pusha

; Save Registers.

;
; Check if bl is new line ?
;

- .

cmp bl,0xa
je new row

; if character is newline ?
; yes, jmp at end.

;
; Calculate the memory offset
;
; because in text mode every character take 2 bytes: one for the
character and one for the attribute, we must calculate the
memory offset with the follwing formula:
; offset = x pos 2 + y pos COLUMNS2

xor eax,eax

mov al,2
mul byte[x pos]
push eax
; save the first section of formula.

xor eax,eax
xor ecx,ecx
mov ax,COLUMNS2
mov cl,byte[y pos]
mul ecx

; 802

pop ecx
add eax,ecx

add eax,VIDEO MEMORY

; eax = address to print the character.

;
; Print the chracter.
;

mov edi,eax

mov byte[edi],bl
; print the character,
mov byte[edi+1],CHAR ATTRIBUTE
; with respect to the
attribute.
;
; Update the postions.

..
;

VGA

]inc byte[x pos


cmp byte[x pos],COLUMNS
je new row

jmp putch32 end

new row:

; clear the x pos.


; increment the y pos.

mov byte[x pos],0


]inc byte[y pos

putch32 end:

; Restore Registers.

popa

ret

) (bl
0xa x y
.
Mode 7
) (x,y .
videomemory = 0xb0000
videomemory+ = x 2 + y 80 2

eax
. ) (x,y
x
y x .

...

strings


puts32 .
ne

.: puts32 rou

Example

- .

; puts32: print string in protected mode.


;
;
;

input:
ebx: point to the string

bits

32

puts32:

pusha

; Save Registers.

mov edi,ebx

@loop:
mov bl,byte[edi]

; read character.

cmp bl,0x0
je puts32 end

; end of string ?
; yes, jmp to end.

call putch32

; print the character.

inc edi

; point to the next character.

jmp @loop

puts32 end:
;
; Update the Hardware Cursor.
;
; After print the string update the hardware cursor.

mov bl,byte[x pos]


mov bh,byte[y pos]

call move cursor

popa

; Restore Registers.

..

VGA

ret

)
(0x0 CRT Controller
.

...

Hardware Cursor


. CRT Controller
Data Register .Index Register
Index
Register Data Register x86
0x3d5 Index Register .0x3d4
.Index Register
0x0: Horizontal Total.
0x1: Horizontal Display Enable End.
0x2: Start Horizontal Blanking.
0x3: End Horizontal Blanking.
0x4: Start Horizontal Retrace Pulse.
0x5: End Horizontal Retrace.
0x6: Ver cal Total.
0x7: Overow.
0x8: Preset Row Scan.
0x9: Maximum Scan Line.
0xa: Cursor Start.
0xb: Cursor End.
0xc: Start Address High.

. -
0xd: Start Address Low.

0xe: Cursor Loca on High.


0xf : Cursor Loca on Low.

0x10: Ver cal Retrace Start.


0x11: Ver cal Retrace End.

0x12: Ver cal Display Enable End.


0x13: Oset.

0x14: Underline Loca on.

0x15: Start Ver cal Blanking.


0x16: End Ver cal Blanking.
0x17: CRT Mode Control.
0x18: Line Compare.

Index Reigster
.Data Register 0xf x
0xe y. x,y
CRT
) (x,y .
videomemory = x + y 80

move cursor .
.: Move Hardware Cursor

Example

; move cursor: Move the Hardware Cursor.

input:
bl: x pos.
bh: y pos.

;
;
;
;

32

bits

VGA

..

move cursor:

pusha

; Save Registers.

;
; Calculate the offset.
;
; offset = x pos + y pos COLUMNS

xor ecx,ecx
mov cl,byte[x pos]

mov eax,COLUMNS
mul byte[y pos]

add eax,ecx
mov ebx,eax
;
; Cursor Location Low.
;

mov al,0xf
mov dx,0x3d4
out dx,al

mov al,bl
mov dx,0x3d5
out dx,al
;
; Cursor Location High.
;

mov al,0xe
mov dx,0x3d4
out dx,al

mov al,bh
mov dx,0x3d5
out dx,al

- .

popa

; Restore Registers.

ret

Clear Screen

...

( Mode 7 25*80)
. . (x,y)
Example

.: Clear Screen

; clear screen: Clear Screen in protected mode.


;

bits

32

clear screen:

pusha
cld

; Save Registers.

mov edi,VIDEO MEMORY


mov cx,2000
; 2580
mov ah,CHAR ATTRIBUTE
background.
mov al,' '

; base address of video memory.


; 31 = white character on blue

rep stosw

mov byte[x pos],0


mov byte[y pos],0

popa

; Restore Registers.

ret

..

..
Second Stage Bootloader
.
.
Pure Binary
++
.
PMode int 0x13

.
4
0x100000 1 .
0x100000 0x3000
0x100000 .
.
.: Hello Kernel

Example

; kernel will load at 1 MB.

org

0x100000

; PMode.

32

bits

jmp kernel entry

" %include "stdio.inc

kernel message

db
"0xa,0xa,0xa,
eqraOS v0.1
"Copyright (C) 2010 Ahmad Essam
db
0xa,0xa,
"
University of Khartoum Faculty
of Mathematical Sceinces.",0

- .
logo message

\ /

db

db

db

db
0xa,0xa,0xa,"
/"
0xa,
"
\ \ "
0xa,
"
/ "
0xa,
"

/ )

`/

/\ , / /

`/ / / / /

\ , /

//

/ /
",0

;
; Entry point.

kernel entry:

;
; Set Registers
;

mov
mov
mov
mov
mov

ax,0x10
; data selector.
ds,ax
es,ax
ss,ax
esp,0x90000
; set stack.

;
; Clear Screen and print message.
;

call clear screen

mov ebx,kernel message


call puts32

mov ebx,logo message


call puts32
;
; Halt the system.
;

cli

..

hlt



int 0x13 1 .
Root Directory
index ) FAT
( index
.
stage2.asm
) oppy.inc .inc (
fat12.inc stdio.inc
A20 a20.inc
gdt.inc common.inc .
ng Kernel: Full Example

.: Loading and Execu

Example

; 16bit real mode.

bits 16
org 0x500

jmp stage2

start:

;
; include files:

standard I/O routines.


GDT load routine.
Enable A20 routines.
FAT12 driver.
common declarations.

;
;
;
;
;

" %include "stdio.inc


" %include "gdt.inc
" %include "a20.inc
" %include "fat12.inc
" %include "common.inc

;
; data and variable

.
example/ch3/boot/ .

- .
hello msg

db
db
reboot...",0

fail message

0xa,0xd,"Welcome to eqraOS Stage2",0xa,0xd,0


0xa,0xd,"KERNEL.SYS is Missing. press any key to

; entry point of stage2 bootloader.


;

stage2:

;
; Set Registers.
;

cli

xor ax, ax
mov ds, ax
mov es, ax

mov ax, 0x0


mov ss, ax
mov sp, 0xFFFF

sti
;
; Load gdt into gdtr.
;

call load gdt


;
; Enable A20.
;
call enable a20 keyboard controller output port
;
; Display Message.

..

;
mov si,hello msg
call puts16
;
; Load Root Directory
;
call load root
;
; Load Kernel
;
xor ebx,ebx
mov bp,KERNEL RMODE BASE

; bx:bp buffer to load kernel

mov si,kernel name


call load file

mov dword[kernel size],ecx


cmp ax,0
je enter stage3

mov si,fail message


call puts16

mov ah,0
int 0x16
int 0x19
cli
hlt

; wait any key.


; warm boot.
; cannot go here!

;
; Go to PMode.
;

enter stage3:

; just set bit 0 from cr0 (Control Register 0).

cli

; important.

- .

mov eax,cr0
or eax,0x1
mov cr0,eax

; entering pmode.

;
; Fix CS value
;
; select the code descriptor
jmp CODE DESCRIPTOR:stage3

;
; entry point of stage3

bits 32

; code now 32bit

stage3:

;;
; Set Registers.
;;

mov
mov
mov
mov
mov

ax,DATA DESCRIPTOR
; address of data descriptor.
ds,ax
ss,ax
es,ax
esp,0x90000
; stack begin from 0x90000.

;
; Clear Screen and print message.
;

call clear screen

mov ebx,stage2 message


call puts32

mov ebx,logo message


call puts32

..

;
; Copy Kernel at 1 MB.
;
mov eax,dword[kernel size]
movzx ebx,word[bytes per sector]
mul ebx
mov ebx,4
div ebx

cld

mov
mov
mov
rep

esi,KERNEL RMODE BASE


edi,KERNEL PMODE BASE
ecx,eax
movsd

;
; Execute the kernel.
;
jmp CODE DESCRIPTOR:KERNEL PMODE BASE
;;
; Hlat the system.
;;
cli
; clear interrupt.
hlt
; halt the system.

. -

:..

:..

.III

Kernel

.
) (Kernel
.

.
++
.

..
.

)
( .
) (

!



.
.

.

.

...



.
:

.
.
.
:

Firmware

) (Firmware ) (EEPROM
.
.
: ) (

.
: ) (
) (



) (GDT .

..
: ) (

) (Applica on Progeamming Interface ).(API

..

) (User Program
.
.

...


) (Fragmenta on
.
)(Posi on Independent
) (Base Address .
binary
0x0
.
0x0
) (Virtual Address Space
0x0 .reloca on
) (VAS 0x0

.VAS
VAS )
( . .
)Memory
.

.
.(Management Unit Cache
- .-

..

) (Hardware Abstrac on
) (So ware Layer ) HAL
(Hardware Abstrac on Layer HAL
.


) (Por ng ) (SPARC,MIPS,...etc
HAL ) (Implementa on
) (Devcie Drivers .

...

Monolithic Kernel

Monoli c
) (System Process .


.
.
DOS
.NT
HAL /
!
Mono Lithic
.

..

...

MicroKernel

MicroKernel

) (IPC
) (
) (
.

) (Message Passing ) (Shared Memory Interprocess
.Communica on .

...

Hybrid Kernel

MicroKernel
Monolithic Kernel Hybrid Kernel .Modied MicroKernel
NT BeOS .Plane 9

..

) (Inline Assemlby )
(.

) dll( )
( .
) new
(.
++

) (RunTime Library ++
) (RunTime Library .
++ ++
) (Standard C/C++ Library printf scanf

.
malloc/new .free/delete
32 32
32 ++ . )(
) (Flat Binary .Headers,...etc
) (main rou ne .
++
.
++
++ )Portable
(Executable ))((main
++
) (Pure Virtual Func on
) (Excep ons . ++

...

PE

++ ) (Portable Executable

. ++ ) (g++
ELF / .
PE .
) (headers PE
. ++.
.: Portable Executable Header

Example

// header information format for PE files

IMAGE DOS HEADER { // DOS .EXE header


short e magic; // Magic number (Should be MZ
;short e cblp
// Bytes on last page of file
;short e cp
// Pages in file
;short e crlc
// Relocations
short e cparhdr; // Size of header in paragraphs
;short e minalloc
// Minimum extra paragraphs needed

typedef struct

unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

..

unsigned short e maxalloc;


// Maximum extra paragraphs needed
unsigned short e ss;
// Initial (relative) SS value
unsigned short e sp;
// Initial SP value
unsigned short e csum;
// Checksum
unsigned short e ip;
// Initial IP value
unsigned short e cs;
// Initial (relative) CS value
unsigned short e lfarlc;
// File address of relocation table
unsigned short e ovno;
// Overlay number
unsigned short e res[4];
// Reserved words
unsigned short e oemid;
// OEM identifier (for e oeminfo)
unsigned short e oeminfo; // OEM information; e oemid specific
unsigned short e res2[10];
// Reserved words
long
e lfanew;
// File address of new exe header
} IMAGE DOS HEADER, PIMAGE DOS HEADER;

// Real mode stub program

IMAGE FILE HEADER {


short Machine;
short NumberOfSections;
long
TimeDateStamp;
long
PointerToSymbolTable;
long
NumberOfSymbols;
short SizeOfOptionalHeader;
short Characteristics;
HEADER, PIMAGE FILE HEADER;

typedef struct

unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
} IMAGE FILE

IMAGE OPTIONAL HEADER {


short Magic;
char
MajorLinkerVersion;
char
MinorLinkerVersion;
long
SizeOfCode;
long
SizeOfInitializedData;
long
SizeOfUninitializedData;
long
AddressOfEntryPoint;
// offset of kernel entry
long
BaseOfCode;
long
BaseOfData;
long
ImageBase;
// Base address of kernel entry
long
SectionAlignment;
long
FileAlignment;

typedef struct

unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

unsigned short MajorOperatingSystemVersion;


unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
unsigned long
Reserved1;
unsigned long
SizeOfImage;
unsigned long
SizeOfHeaders;
unsigned long
CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
unsigned long
SizeOfStackReserve;
unsigned long
SizeOfStackCommit;
unsigned long
SizeOfHeapReserve;
unsigned long
SizeOfHeapCommit;
unsigned long
LoaderFlags;
unsigned long
NumberOfRvaAndSizes;
IMAGE DATA DIRECTORY DataDirectory[DIRECTORY ENTRIES];
} IMAGE OPTIONAL HEADER, PIMAGE OPTIONAL HEADER;

( kernel entry())
IMAGE OPTIONAL HEADER ( header)

.
e lfanew IMAGE DOS HEADER
IMAGE FILE HEADER
ImageBase oset AddressOfEntryPoint
oset
) .call
.(KERNEL PMODE BASE
Example

.: Ge

ng Kernel entry

mov ebx,[KERNEL PMODE BASE+60]


add ebx,KERNEL PMODE BASE
; ebx =

IMAGE FILE HEADER

add ebx,24

; ebx =

IMAGE OPTIONAL HEADER

..

; ebx point to AddressOfEntryPoint

add ebx,16

; epb = AddressOfEntryPoint

]mov ebp,dword[ebx

; ebx point to ImageBase

add ebx,12

; epb = kernel entry

]add ebp,dword[ebx

cli

call ebp

... ++
++ )(startup

(C++ Run me Library) ++
) (
.
) (Global Object
) (new,delete RTTI ).(Excep ons

Global Operator

) (new ) (delete ++
. .
.: Global new/delete operator
};int size){return 0
};int size){return 0
}{)p
}{)p

Example

void

cdecl ::operator new (unsigned


void
cdecl operator new[] (unsigned
void
cdecl ::operator delete (void
void
cdecl operator delete[] (void

.
Pure virtual func on call handler

) (Pure virtual func on


)( purecall Pure virtual
Pure virtual purecall .
on call handler

.: Pure virtual func

} ;cdecl :: purecall() { for (;;); return 0

Example

int

Floa ng Point Support

) (Floa ng Point ++ 1 fltused


)( ftol2 sse float long.
ng Point Support

.: Floa

Example

{ )(ftol2 sse

)declspec (naked

extern "C" long

;int a
#ifdef i386
{ asm
]fistp [a
mov ebx, a

#endif

;fltused = 1

extern "C" int

Pure virtual ) (Abstract


) (Override .
++. .

..

) (Dynamic ini alizer


..crt
) .(Constructor
.crt )(Preprocessor
.
.crt ) (Func on Pointer
.
.crt:xcu dollar sign

.crt:xcu .crt:xca
.crt:xcu .crt:xcz
.crt:xcu .
.crt
. .data
.
alizer

.: Object Ini

Example

// Function pointer typedef for less typing

;)cdecl PVFV)(void

( typedef void

x c a points to beginning of initializer table

//

)" #pragma data seg(".CRT$XCA

;} x c a [] = { 0

PVFV

//

x c z points to end of initializer table


)" #pragma data seg(".CRT$XCZ
PVFV
;} x c z [] = { 0

// Select the default data segment again (.data) for the rest of the

unit
)( #pragma data seg

.data

.code

.stack

.
// Now, move the CRT data into .data section so we can read/write to

it
#pragma comment(linker, "/merge:.CRT=.data")

// initialize all global initializers (ctors, statics, globals, etc

..)
void

cdecl

initterm (

PVFV pfbegin,

PVFV pfend ) {

//! Go through each initializer


while ( pfbegin < pfend )

//! Execute the global initializer


if ( pfbegin != 0 )
(pfbegin) ();

//! Go to next initializer inside the initializer table


++pfbegin;

// execute all constructors and other dynamic initializers


void

cdecl init ctor() {

atexit init();
initterm( xc a ,

x c z );


(deini alizer array) ( Objects)

atexit (exit() )
++
.
.
Example

.: Delete Object

..

/! function pointer table to global deinitializer table


static

PVFV pf atexitlist = 0;

// Maximum entries allowed in table. Change as needed


static unsigned max atexitlist entries = 32;

// Current amount of entries in table


static unsigned cur atexitlist entries = 0;

//! initialize the deinitializer function table


void

cdecl

atexit init(void) {

max atexitlist entries = 32;

// Warning: Normally, the STDC will dynamically allocate this.


Because we have no memory manager, just choose
// a base address that you will never use for now
pf atexitlist = ( PVFV )0x5000;

//! adds a new function entry that is to be called at shutdown

cdecl atexit( PVFV fn) {

int

//! Insure we have enough free space


if (cur atexitlist entries>=max atexitlist entries)
return 1;
else {

//! Add the exit routine


(pf atexitlist++) = fn;
cur atexitlist entries++;

return 0;

//! shutdown the C++ runtime; calls all global deinitializers


void

cdecl exit () {

//! Go through the list, and execute all global exit routines
while (cur atexitlist entries) {

//! execute function


((pf atexitlist)) ();

...
kernel entry() PE ( Parsing)

main() ( Stack)
.(Hang) main()

Example

.: Kernel Entry rou

ne

extern void
extern void
extern void

cdecl main ();


// main function.
cdecl init ctor();
// init constructor.
cdecl exit ();
// exit.

void

cdecl kernel entry ()

#ifdef i386

asm {
cli

mov ax, 10h


mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
mov ebp, esp
push ebp

// select data descriptor in GDT.

// Set up base stack


// store current stack pointer

#endif

..

// Execute global constructors


;)(init ctor

// Call kernel entry point


;)(main

// Cleanup all dynamic dtors


;)(exit

#ifdef i386

asm cli

#endif

;);;(for

)( main .

..

) (Expandibility
HAL
.

) (Interface
.
) (Impelmenta on
.
eqraOS:
boot: rst-stage and second-stage bootloader.
core:
kernel:Kernel program PE executable le type.

Bootloader .

.
hal:Hardware abstrac on layer.
lib:Standard library run me and standard C/C++ library.
include:Standard include headers.
debug:Debug version of eqraOS.
release:Final release of eqraOS.

..
++
++
.
NULL

.(void*)0 0 NULL ++
Example

.: null.h:Deni

on of NULL in C and C++

#ifndef NULL H
#define NULL H

#if define ( MSC VER) && ( MSC VER

> = 1020)

#pargma once
#endif

#ifdef NULL
#undev NULL
#endif

#ifdef

cplusplus
extern "C"

#endif

/ C++ NULL definition

..
#define NULL 0

#ifdef

cplusplus

#else

/ C NULL definition

#define NULL (void)0

#endif

#endif //NULL H

++
.

cplusplus

size t

.(unsigned) 32-bit size t


Example

.: size t.h:Deni

on of size t in C/C++

#ifndef SIZE T H
#define SIZE T H

#ifdef

cplusplus

extern "C"

#endif

/ Stdandard definition of size t


typedef unsigned size t;

#ifdef

cplusplus

#endif

#endif //SIZE T H


( Data Types)
. ( typedef)
Example

.: stdint.h:typedef data type

#ifndef STDINT H
#define STDINT H`

#define
#define

need wint t
need wchar t

/ Exactwidth integer type


typedef
typedef
typedef
typedef
typedef
typedef
typedef
typedef

/
char
int8 t;
unsigned char
uint8 t;
short
int16 t;
unsigned short
uint16 t;
int
int32 t;
unsigned int
uint32 t;
long long
int64 t;
unsigned long long uint64 t;

// to be continue..

#endif //STDINT H

cstdint ++
. ++
Example

.: cstdint:C++ typedef data type

#ifndef CSTDINT H

. ++

..
#define CSTDINT H

#include

<stdint.h>

#endif //CSTDINT H


( )Macros) ctype.h
.(...
Example

.: ctype.h:determine character type

#ifndef CTYPE H
#define CTYPE H

#ifdef

MSC VER

#pragma warning (disable:4244)


#endif

#ifdef

cplusplus

extern "C"

#endif

extern char

ctype[];

/ constants

#define CT UP
#define CT LOW
#define CT DIG
#define CT CTL
#define CT PUN
#define CT WHT
#define CT HEX
#define CT SP

0x01 // upper case


0x02 // lower case
0x04 // digit
0x08 // control
0x10 // punctuation
0x20 // white space (space,cr,lf,tab).
0x40 // hex digit
0x80 // sapce.

.
/ macros

#define isalnum(c)

( ( ctype+1)[(unsigned)(c)] & (CT UP | CT LOW |

CT DIG) )
#define isalpha(c)

(( ctype + 1)[(unsigned)(c)] & (CT UP | CT LOW)

)
#define iscntrl(c)

(( ctype + 1)[(unsigned)(c)] & (CT CTL))

// to be continue..

#ifdef

cplusplus

#endif

#endif // CTYPE H

Interrupts

) (Current Process
.
) (Interrupt
) (
) (Interrupt Handler ) (Interrupt Service Roun ne
)
(
. )(Hardware Interrupt
) (So ware Interrupt
.int n )
(Page Fault )(Excep ons
) (Error Handler .

..

So ware Interrupts

) (int n
) (Interrupt handler
) (Ring3 user mode )
(.

...
) )(Interrupt Request
(IRQ )Interrupt
(Vector Table 0x0 0x3ff
) (IR .
:

Interrupts

Interrupt Vector Table :..


Descrip on
Interrupt Number
Divide by 0
0
Single step (Debugger)
1
Non Maskable Interrupt (NMI) Pin
2
Breakpoint (Debugger)
3
Overow
4
Bounds check
5
Undened Opera on Code
6
No coprocessor
7
Double Fault
8
Coprocessor Segment Overrun
9
nvalid Task State Segment (TSS)I
10
Segment Not Present
11
Stack Segment Overrun
12
General Protec on Fault (GPF)
13
tPage Faul
14
Unassigned
15
Coprocessor error
16
Alignment Check (486+ Only)
17
Machine Check (Pen um/586+ Only) 18
Reserved excep ons
19-31
Interrupts free for so ware use
32-255

Base Address
0x000
0x004
0x008
0x00C
0x010
0x014
0x018
0x01C
0x020
0x024
0x028
0x02C
0x030
0x034
0x038
0x03C
0x040
0x044
0x048
0x05C
0x068 - 0x3FF

Byte 0: Low oset address of IR.


Byte 1: High oset address of IR.
Byte 2: Low Segment address of IR.
Byte 3: High Segment Address of IR.

1024 ) 256
(
.

. IVT . ( )

So ware Interrupts

..

...
Interrupt Descriptor)


256 IVT IDT ( Table
8 ( 256 )
GDT ( selector type: code or data) ( IR)
.
Bits 0-15:
Interrupt / Trap Gate: Oset address Bits 0-15 of IR
Task Gate: Not used.
Bits 16-31:
Interrupt / Trap Gate: Segment Selector (Useually 0x10)
Task Gate: TSS Selector
Bits 31-35: Not used
Bits 36-38:
Interrupt / Trap Gate: Reserved. Must be 0.
Task Gate: Not used.
Bits 39-41:
Interrupt Gate: Of the format 0D110, where D determins size
01110 - 32 bit descriptor
00110 - 16 bit descriptor
Task Gate: Must be 00101
Trap Gate: Of the format 0D111, where D determins size
01111 - 32 bit descriptor
00111 - 16 bit descriptor
Bits 42-44: Descriptor Privedlge Level (DPL)
00: Ring 0
01: Ring 1
10: Ring 2
11: Ring 3

Interrupts
) Bit 45: Segment is present (1: Present, 0:Not present
Bits 46-62:
Interrupt / Trap Gate: Bits 16-31 of IR address
Task Gate: Not used


.
.: Example of interrupt descriptor

Example

idt descriptor:

; 010001110

dw
0x0
dw
0x8
db
0x0
db
0x8e
dw
0x0

baseLow
selector
reserved
flags
baseHi

baseLow 16 IR
baseHi 0x0 .0x0
)( ) (Data selector
0x8 ) (Code Selector ) .(GDT
flags 010001110b 32-bit
).(Ring0
) (
IDT idt start
idt end idt ptr
:
.: Value to put in IDTR

Example

idt ptr:

limit dw idt end idt start ; bits 015 is size of idt


base dd idt start
; base of idt

) IDTR ( lidt

][idt ptr

.lidt

idtr
) (CPL ag .

..

So ware Interrupts


) IDT (IDTR
int num * 8 IDT 8 .

. EFLAGS CS
IP ) (Stack )Error
(Code . 32-bit .
Bit 0: External event
0: Internal or so ware event triggered the error.
1: External or hardware event triggered the error.
Bit 1: Descrip on loca on
0: Index por on of error code refers to descriptor in GDT or current LDT.
1: Index por on of error code refers to gate descriptor in IDT.
Bit 2: GDT/LDT. Only use if the descriptor loca on is 0.
0: This indicates the index por on of the error code refers to a descriptor in the current GDT.
1: This indicates the index por on of the error code refers to a segment or gate descriptor in
the LDT.

Bits 3-15: Segment selector index. This is an index into the IDT, GDT, or current LDT to the segment
or gate selector bring refrenced by the error code.

Bits 16-31: Reserved.

iret iretd
) .(FLAGS .

...

:

:Fault
.

:Trap .

Interrupts

x86 Processor Excep ons Table :..


Descrip on
Class
Interrupt Number
Divide by 0
Fault
0
Single step
Trap/Fault 1
Non Maskable Interrupt (NMI) Pin Unclassed 2
Breakpoint
Trap
3
Overow
Trap
4
Bounds check
Fault
5
Unvalid OPCode
Fault
6
Device not available
Fault
7
Double Fault
Abort
8
Coprocessor Segment Overrun
Abort
9
Invalid Task State Segment
Fault
10
Segment Not Present
Fault
11
Stack Fault Excep on
Fault
12
General Protec on Fault
Fault
13
Page Fault
Fault
14
Unassigned
15
x87 FPU Error
Fault
16
Alignment Check
Fault
17
Machine Check
Abort
18
SIMD FPU Excep on
Fault
19
Reserved
20-31
Avilable for so ware use
32-255

:Abort .

. .
)
(cli General Protec on Fault
cli
.
IDT .
Prpgrammable Interval Timer
PIT System Timer
.

..

So ware Interrupts

.


Programmable Interrupt Controller PIC
.
) (IDT 256
)(GDT
) ( PIC
.

...

GDT


HAL
HAL - -

HAL
. HAL
HAL
.
on Layer Interface

.: include/hal.h:Hardware Abstrac

Example

#ifndef HAL H
#define HAL H

#ifndef i386
" #error "HAL is not implemented in this platform
#endif

><stdint.h

#include

#ifdef

)declspec(naked

MSC VER
#define interrupt
#else

) (GDT,LDT and IDT .HAL

Interrupts
#define interrupt
#endif

#define far
#define near

Interface /

extern int

;)(cdecl hal init


;)(cdecl hal close
;) extern void cdecl gen interrupt(int
extern int

#endif // HAL H

HAL extern
) (Implementa on . )( hal init
)( hal close
gen interrupt
.
) (GDT
.
:

:i386 gdt init


.

:i386 gdt set desc .

:gdt install
.GDTR

.
.: hal/gdt.cpp:Install GDT
...
.
.hal/gdt.h

Example

So ware Interrupts

..

#include

<string.h>

#include "gdt.h"

static struct gdt desc


static struct gdtr

gdt[MAX GDT DESC];


gdtr;

static void gdt install();

static void gdt install()

#ifdef

MSC VER

asm lgdt [ gdtr];


#endif

extern void i386 gdt set desc(uint32 t index,uint64 t base,uint64 t

limit,uint8 t access,uint8 t grand) {

if ( index > MAX GDT DESC )


return;

// clear the desc.


memset((void)& gdt[index],0,sizeof(struct gdt desc));

// set limit and base.


gdt[index].low base = uint16 t(base & 0xffff);
gdt[index].mid base = uint8 t((base >> 16) & 0xff);
gdt[index].high base = uint8 t((base >> 24) & 0xff);
gdt[index].limit = uint16 t(limit & 0xffff);

// set flags and grandularity bytes


gdt[index].flags = access;
gdt[index].grand = uint8 t((limit >> 16) & 0x0f);
gdt[index].grand = gdt[index].grand | grand & 0xf0;

extern gdt desc i386 get gdt desc(uint32 t index)

if ( index >= MAX GDT DESC )


return 0;

Interrupts

else
return & gdt[index];

extern int i386 gdt init()

// init gdtr
gdtr.limit = sizeof(struct gdt desc) MAX GDT DESC 1;
gdtr.base = (uint32 t)& gdt[0];

// set null desc.


i386 gdt set desc(0,0,0,0,0);

// set code desc.


i386 gdt set desc(1,0,0xffffffff,
I386 GDT CODE DESC | I386 GDT DATA DESC | I386 GDT READWRITE |
// 10011010
I386 GDT MEMORY,
I386 GDT LIMIT HI | I386 GDT 32BIT | I386 GDT 4K
11001111

//

);

// set data desc.


i386 gdt set desc(2,0,0xffffffff,
I386 GDT DATA DESC | I386 GDT READWRITE | I386 GDT MEMORY, //
10010010
I386 GDT LIMIT HI | I386 GDT 32BIT | I386 GDT 4K
// 11001111
);

// install gdtr
gdt install();

return 0;

..

..

Programmable Interrupt Controller

Programmable Interrupt

Controller

) (PMode

PIT

.

) (.

PIC Programmable Interrupt Controller
8259A .PIC
:..

...

8259A

Hardware Interrupts

PIC

) (Interrupt Driven .
) (loop
Polling

) (
)(Asynchronous
) .(Synchronous

ng

.Busy Wai

Interrupts

:..
)(
Timer
0x08
IRQ0

0x09
IRQ1
PIC
0x0a
IRQ2

0x0b
IRQ3

0x0c
IRQ4

0x0d
IRQ5

0x0e
IRQ6

0x0f
IRQ7
CMOS
0x70
IRQ8/IRQ0
x86

IRQ9/IRQ1
IRQ10/IRQ2
IRQ11/IRQ3
IRQ12/IRQ4
IRQ13/IRQ5
IRQ14/IRQ6
IRQ15/IRQ7

0x71
0x72
0x73
0x74
0x75
0x76
0x77

CGA ver cal retrace

FPU



. .
.

...

PIC

PIC ) (Signals
PIC
PIC

. ) (IRQ
PIC ). (Secondary/Slave PIC
) (Primary PIC
). (SouthBridge

..

Programmable Interrupt Controller

PIC's Pins

) (

) .(Digital Logic . .
D0-D7
PIC CAS0, CAS1, CAS2
PIC INT
INTR INTA
INTA

IF and TF INTR
PIC
:.. PIC
INT

PIC ) End Of
(Interrupt . IR0...IR7
)
( PIC
PIC PIC
.
IR0 .

PIC

PIC :

) :(Command Reigster
.EOI

) :(Status Register .

) :(Interrupt Request Register


) (Acnowledges .
.

Interrupts

Bit Number
0
1
2
3
4
5
6
7


0x20
0x21
0xA0
0xA1

:.. IRR/ISR/IMR
)IRQ Number (Slave controller) IRQ Number (Primary controller
IRQ8
IRQ0
IRQ9
IRQ1
IRQ10
IRQ2
IRQ11
IRQ3
IRQ12
IRQ4
IRQ13
IRQ5
IRQ14
IRQ6
IRQ15
IRQ7

:..

PIC

Primary PIC Command and Status Register


Primary PIC Interrupt Mask Register and Data Register
Secondary (Slave) PIC Command and Status Register
Secondary (Slave) PIC Interrupt Mask Register and Data Register

)) :(In Service Register (ISR


.

)) :(Interrupt Mask Register (IMR


.

. .x86

PIC

PIC
.
Ini aliza on Control Words ICW
PIC Opera on Control Words . OCW
PIC . ICW1

..

Programmable Interrupt Controller

:..

ICW4
IC4
0
SNGL PIC
1
x86
ADI
2
LTIM
3

1
4
x86
0
5
x86
0
6
x86
0
7
ICW1

.
.
ICW4
ICW4
PIC Level Triggered
Mode Edge Triggered Mode
PIC .x86 .
PIC .
aliza on Control Words 1

.: Ini

Example

; Setup to initialize the primary PIC. Send ICW 1


mov al, 0x11
; 00010001
out 0x20, al

; Send ICW 1 to second PIC command register


out 0xA0, al

ICW2 IVT IRQ


IRQ .

) IRQ ( . .
IRQ PIC -
-
.

Interrupts

:..

S0-S7 IRQ
0-7

ICW3 for Primary PIC

:..

ID0 IRQ
0-2
3-7
3-7

ICW3 for Slave PIC

aliza on Control Words 2

.: Ini

Example

; send ICW 2 to primary PIC


mov al, 0x20
out 0x21, al
; Primary PIC handled IRQ 0..7. IRQ 0 is now mapped to interrupt
number 0x20

; send ICW 2 to secondary PIC


mov al, 0x28
out 0xA1, al
; Secondary PIC handles IRQ's 8..15. IRQ 8 is now mapped to use
interrupt 0x28

ICW3 PIC
IRQ . x86
IRQ2
. . .
PIC
IRQ IRQ
IRQ2 ) 0000100b (0x4
IRQ )
(010 ) (. .
.
aliza on Control Words 3

.: Ini

Example

..

:..

x86
EOI
ICW4


0
1
2
3
4
5-7

Programmable Interrupt Controller

uPM
AEOI
M/S
BUF
SFNM
0

If set (1), selects buer master. Cleared if buer slave.


If set, controller operates in buered mode
x86
x86

; Send ICW 3 to primary PIC


mov al, 0x4
); 0x04 => 0100, second bit (IR line 2
out 0x21, al ; write to data register of primary PIC

; Send ICW 3 to secondary PIC


mov al, 0x2
; 010=> IR line 2
out 0xA1, al ; write to data register of secondary PIC


..

. x86 . PIC .
ICW4

aliza on Control Words 4


; bit 0 enables 80x86 mode

.: Ini

Example

mov al, 1

; send ICW 4 to both primary and secondary PICs


out 0x21, al
out 0xA1, al

PIC

) ( .
OCW OCW2

. . . -
.. .

Interrupts

:..


L0/L1/L2
0
EOI
SL
R

0-2
3-4
5
6
7

R Bit
0
0
0
0
1
1
1
1

SL Bit
0
0
1
1
0
0
1
1

OCW2

Interrupt level upon which the controller must react

)End of Interrupt (EOI


Selec on
Rota on op on

:..

EOI Bit
0
1
0
1
0
1
0
1

OCW2

Descrip on
)Rotate in Automa c EOI mode (CLEAR
Non specic EOI command
No opera on
Specic EOI command
)Rotate in Automa c EOI mode (SET
Rotate on non specic EOI
Set priority command
Rotate on specic EOI

) (EOI .Non specic EOI command


.: Send EOI

Example

; send EOI to primary PIC

; set bit 4 of OCW 2


; write to primary PIC command register

mov al, 0x20


out 0x20, al



) PIC PIT (IR0
IR0 PIC IRQ
) (Interrupt Request Register . IRR
IRQ
0 .IR0 PIC Interrupt

..

Programmable Interval Timer

Mask Register
. PIC
INTA .
IF

) (Acnowledges INTR PIC INTA
IRQ D0-D7 In Service Register
.
CS and EIP
IVT

.
EOI .

..

Programmable Interval Timer

) Dual Inline Package (DIP ) (Counters or Channels


) .(. )(System Timer
) (IRQ0 PIC

) (Mul task and Mul thread
) (Process )Process
(Queue
.
) (RAM refreshing
) (Memory Controller .
.(PC Speaker)

) (POST .

Interrupts

:..

...

8253

PIT

) (MotherBoard DIP ).(SouthBridge



.

PIT's Pins


) (Data Bus
D0...D7
.
) ( WR


RD
:.. PIT
.
CS
CS ) (Address Bus
) .(Control Bus - A0,A1
- . )(CLK, OUT, and GATE

) (CLK (Clock Input) and GATE ) (OUT
) ( PIC
) (IRQ0 PIC
.

..

Programmable Interval Timer

PIT

PIT ) (
.

. ) (Control Word

. .
) (A0,A1
) ( .
:.. 8253 PIT
RD WR A0 A1

Counter 0

0x40

Counter 1

0x41

Counter 2

0x42

Control Word

0x43

1
0
1
0
1
0
1
0

0
1
0
1
0
1
0
1

0
0
0
0
1
1
1
1

0
0
1
1
0
0
1
1

0
0
1
1
2
2
Control Word

) ( .
Bit 0: (BCP) Binary Counter
0: Binary
) 1: Binary Coded Decimal (BCD
Bit 1-3: (M0, M1, M2) Opera ng Mode. See above sec ons for a descrip on of each.
000: Mode 0: Interrupt or Terminal Count
001: Mode 1: Programmable one-shot
010: Mode 2: Rate Generator
011: Mode 3: Square Wave Generator
100: Mode 4: So ware Triggered Strobe
101: Mode 5: Hardware Triggered Strobe
110: Undened; Don't use

Interrupts

111: Undened; Don't use


Bits 4-5: (RL0, RL1) Read/Load Mode. We are going to read or send data to a counter register
00: Counter value is latched into an internal control register at the me of the I/O write
opera on.

01: Read or Load Least Signicant Byte (LSB) only


10: Read or Load Most Signicant Byte (MSB) only
11: Read or Load LSB rst then MSB
Bits 6-7: (SC0-SC1) Select Counter. See above sec ons for a descrip on of each.
00: Counter 0
01: Counter 1
10: Counter 2
11: Illegal value

(milliseconds )100Hz .
.
Example

.: PIT programming
; COUNT = input hz / frequency

mov dx, 1193180 / 100 ; 100hz, or 10 milliseconds

; FIRST send the command word to the PIT. Sets binary counting,
; Mode 3, Read or Load LSB first then MSB, Channel 0

mov al, 110110b


out 0x43, al

; Now we can write to channel 0. Because we set the "Load LSB first
then MSB" bit, that is
; the way we send it

mov ax, dx
out 0x40, al
xchg ah, al
out 0x40, al

;LSB
;MSB

..

..

HAL

HAL

HAL
. PIC

). (IRQ0

...

PIC

.. PIC
. PIC ) (hal/pic.h
) (hal/pic.cpp .
. )
( .
.: hal/pic.h: PIC Interface

Example

// PIC 1 Devices IRQ


#define I386 PIC IRQ TIMER

0
1
3
4

#define I386 PIC IRQ KEYBOARD


#define I386 PIC IRQ SERIAL2
#define I386 PIC IRQ SERIAL1
#define I386 PIC IRQ PARALLEL2

#define I386 PIC IRQ DESKETTE

#define I386 PIC IRQ PARALLEL1

// PIC 2 Devices IRQ


#define I386 PIC IRQ CMOSTIMER

0
1

#define I386 PIC IRQ CGARETRACE


#define I386 PIC IRQ AUXILIRY

4
5
6

#define I386 PIC IRQ FPU


#define I386 PIC IRQ HDC

) // Operation Commamd Word 2 (OCW2

1
2
4

#define I386 PIC OCW2 MASK L1


#define I386 PIC OCW2 MASK L2
#define I386 PIC OCW2 MASK L3

.. .

Interrupts

#define I386 PIC OCW2 MASK EOI

0x20
0x40
#define I386 PIC OCW2 MASK ROTATE 0x80
#define I386 PIC OCW2 MASK SL

// Operation Commamd Word 3 (OCW3)


#define I386 PIC OCW3 MASK RIS

1
2
PIC OCW3 MASK MODE
4
PIC OCW3 MASK SMM
0x20
PIC OCW3 MASK ESMM
0x40
PIC OCW3 MASK D7
0x80

#define I386 PIC OCW3 MASK RIR


#define I386
#define I386
#define I386
#define I386

// PIC 1 port address


#define I386 PIC1 COMMAND REG
#define I386 PIC1 STATUS REG
#define I386 PIC1 IMR REG
#define I386 PIC1 DATA REG

0x20
0x20
0x21
0x21

// PIC 2 port address


#define I386 PIC2 COMMAND REG
#define I386 PIC2 STATUS REG
#define I386 PIC2 IMR REG
#define I386 PIC2 DATA REG

0xa0
0xa0
0xa1
0xa1

// Initializing Commamd Word 1 (ICW1) Mask


#define I386 PIC ICW1 MASK IC4
#define I386 PIC ICW1 MASK SNGL
#define I386 PIC ICW1 MASK ADI
#define I386 PIC ICW1 MASK LTIM
#define I386 PIC ICW1 MASK INIT

0x1
0x2
0x4
0x8
0x10

// Initializing Commamd Word 4 (ICW4) Mask


#define I386 PIC ICW4 MASK UPM

0x1
0x2
#define I386 PIC ICW4 MASK MS
0x4
#define I386 PIC ICW4 MASK BUF
0x8
#define I386 PIC ICW4 MASK SFNM
0x10
#define I386 PIC ICW4 MASK AEOI

HAL

..

// Initializing command 1 control bits


#define I386 PIC ICW1 IC4 EXPECT

#define I386 PIC ICW1 IC4 NO

#define I386 PIC ICW1 SNGL YES

2
0
PIC ICW1 ADI CALLINTERVAL4
4
PIC ICW1 ADI CALLINTERVAL8
0
PIC ICW1 LTIM LEVELTRIGGERED 8
PIC ICW1 LTIM EDGETRIGGERED 0
PIC ICW1 INIT YES
0x10
PIC ICW1 INIT NO
0

#define I386 PIC ICW1 SNGL NO


#define I386
#define I386
#define I386
#define I386
#define I386
#define I386

// Initializing command 4 control bits


#define I386 PIC ICW4 UPM 86MODE

1
0

#define I386 PIC ICW4 UPM MCSMODE


#define I386 PIC ICW4 AEOI AUTOEOI

2
0
4
0

#define I386 PIC ICW4 AEOI NOAUTOEOI


#define I386 PIC ICW4 MS BUFFERMASTER
#define I386 PIC ICW4 MS BUFFERSLAVE
#define I386 PIC ICW4 BUF MODEYES

8
0

#define I386 PIC ICW4 BUF MODENO


#define I386 PIC ICW4 SFNM NESTEDMODE
#define I386 PIC ICW4 SFNM NOTNESTED

0x10
0

extern uint8 t i386 pic read data(uint8 t pic num);


extern void i386 pic send data(uint8 t data,uint8 t pic num);
extern void i386 pic send command(uint8 t cmd,uint8 t pic num);
extern void i386 pic init(uint8 t base0,uint8 t base1);


. .
.
Example

.: hal/pic.cpp: PIC Implementa

on

uint8 t i386 pic read data(uint8 t pic num)

if (pic num > 1)


return 0;

Interrupts

uint8 t reg = (pic num == 1)?I386 PIC2 DATA REG:I386 PIC1 DATA REG;
return inportb(reg);

void i386 pic send data(uint8 t data,uint8 t pic num)

if (pic num > 1)


return;

uint8 t reg = (pic num == 1)?I386 PIC2 DATA REG:I386 PIC1 DATA REG;
outportb(reg,data);

void i386 pic send command(uint8 t cmd,uint8 t pic num)

if (pic num > 1)


return;

uint8 t reg = (pic num == 1)?I386 PIC2 COMMAND REG:


I386 PIC1 COMMAND REG;
outportb(reg,cmd);

void i386 pic init(uint8 t base0,uint8 t base1)

uint8 t icw = 0;

disable irq();

/ disable hardware interrupt (cli) /

/ init PIC, send ICW1 /


icw = (icw & I386 PIC ICW1 MASK INIT) | I386 PIC ICW1 INIT YES;
icw = (icw & I386 PIC ICW1 MASK IC4) | I386 PIC ICW1 IC4 EXPECT;
/ icw = 0x11 /

i386 pic send command(icw,0);


i386 pic send command(icw,1);
/ ICW2 : remapping irq /
i386 pic send data(base0,0);

HAL

i386 pic send data(base1,1);

/ ICW3 : irq for master/slave pic/


i386 pic send data(0x4,0);
i386 pic send data(0x2,1);

/ ICW4: enable i386 mode. /


icw = (icw & I386 PIC ICW4 MASK UPM) | I386 PIC ICW4 UPM 86MODE ;
/ icw = 1 /
i386 pic send data(icw,0);
i386 pic send data(icw,1);

..

PIT
Example

.: hal/pit.h: PIt Interface

#define I386 PIT COUNTER0 REG


#define I386 PIT COUNTER1 REG
#define I386 PIT COUNTER2 REG
#define I386 PIT COMMAND REG

0x40
0x41
0x42
0x43

#define I386 PIT OCW MASK BINCOUNT


#define I386 PIT OCW MASK MODE
#define I386 PIT OCW MASK RL
#define I386 PIT OCW MASK COUNTER

0x1
0xe
0x30
0xc0

#define I386 PIT OCW BINCOUNT BINARY


#define I386 PIT OCW BINCOUNT BCD

0x0
0x1

#define I386 PIT OCW MODE TERMINALCOUNT

0x0
0x2
RATEGEN
0x4
SQUAREWAVEGEN
0x6
SOFTWARETRIG
0x8
HARDWARETRIG
0xa

#define I386 PIT OCW MODE ONESHOT


#define I386 PIT OCW MODE
#define I386 PIT OCW MODE
#define I386 PIT OCW MODE
#define I386 PIT OCW MODE

...

Interrupts
#define I386 PIT OCW RL LATCH

0x0
0x10
0x20
0x30

#define I386 PIT OCW RL LSBONLY


#define I386 PIT OCW RL MSBONLY
#define I386 PIT OCW RL DATA

#define I386 PIT OCW COUNTER 0

0x0
0x40
0x80

#define I386 PIT OCW COUNTER 1


#define I386 PIT OCW COUNTER 2

extern void i386 pit send command(uint8 t cmd);


extern void i386 pit send data(uint16 t data,uint8 t counter);
extern uint8 t i386 pit read data(uint16 t counter);
extern uint32 t i386 pit set tick count(uint32 t i);
extern uint32 t i386 pit get tick count();
extern void i386 pit start counter(uint32 t freq,uint8 t counter,

uint8 t mode);
extern void cdecl i386 pit init();
extern bool cdecl i386 pit is initialized();

Example

.: hal/pit.cpp: PIT Implementa

on

static volatile uint32 t


static bool

pit ticks = 0;
pit is init = false;

void

cdecl i386 pit irq();

void i386 pit send command(uint8 t cmd)

outportb(I386 PIT COMMAND REG,cmd);

void i386 pit send data(uint16 t data,uint8 t counter)

uint8 t port;

if (counter == I386 PIT OCW COUNTER 0)


port = I386 PIT COUNTER0 REG;
else if ( counter == I386 PIT OCW COUNTER 1)
port = I386 PIT COUNTER1 REG;
else
port = I386 PIT COUNTER2 REG;

HAL

..
outportb(port,uint8 t(data));

uint8 t i386 pit read data(uint16 t counter)

uint8 t port;

if (counter == I386 PIT OCW COUNTER 0)


port = I386 PIT COUNTER0 REG;
else if ( counter == I386 PIT OCW COUNTER 1)
port = I386 PIT COUNTER1 REG;
else
port = I386 PIT COUNTER2 REG;

return inportb(port);

uint32 t i386 pit set tick count(uint32 t i)

uint32 t prev =
pit ticks = i;
return prev;

uint32 t i386 pit get tick count()

pit ticks;

return

pit ticks;

void i386 pit start counter(uint32 t freq,uint8 t counter,uint8 t

mode) {
if (freq == 0)
return;

uint16 t divisor = uint16 t(1193181/uint16 t(freq));


/ send operation command
uint8 t ocw = 0;

ocw = (ocw & I386 PIT OCW MASK MODE) | mode;


ocw = (ocw & I386 PIT OCW MASK RL) | I386 PIT OCW RL DATA;
ocw = (ocw & I386 PIT OCW MASK COUNTER) | counter;

i386 pit send command(ocw);

Interrupts

/ set frequency rate /


i386 pit send data(divisor & 0xff,0);
i386 pit send data((divisor >> 8) & 0xff,0);

/ reset ticks count /


pit ticks = 0;

cdecl i386 pit init() {


set vector(32,i386 pit irq);
pit is init = true;

void

cdecl i386 pit is initialized() {


return pit is init;

bool

void

cdecl i386 pit irq() {

asm {
add esp,12
pushad

pit ticks++;

int done(0);

asm {
popad
iretd

HAL ...
HAL
Example

.: New HAL Interface

HAL

..

extern int

cdecl hal init();


cdecl hal close();
extern void cdecl gen interrupt(int);
extern void cdecl int done(unsigned int n);
extern void cdecl sound(unsigned int f);
extern unsigned char cdecl inportb(unsigned short port num);
extern void cdecl outportb(unsigned short port num,unsigned char
value);
extern void cdecl enable irq();
extern void cdecl disable irq();
extern void cdecl set vector(unsigned int int num,void ( cdecl far &
vect)());
extern void ( cdecl far cdecl get vector(unsigned int int num))();
extern const char cdecl get cpu vendor();
extern int cdecl get tick count();

extern int

Example

.: New HAL Impelmenta

on

cdecl hal init() {


i386 cpu init();
i386 pic init(0x20,0x28);
i386 pit init();
i386 pit start counter(100,I386 PIT OCW COUNTER 0,
I386 PIT OCW MODE SQUAREWAVEGEN);

int

/ enable irq
enable irq();

return 0;

cdecl hal close() {


i386 cpu close();
return 0;

int

cdecl gen interrupt(int n) {


MSC VER
asm {
mov al, byte ptr [n]

void

#ifdef

Interrupts

mov byte ptr [address+1], al


jmp address

address:
int 0

// will execute int n.

#endif

cdecl int done(unsigned int n) {


if (n > 16)
return;

void

if (n > 7)
/ send EOI to pic2 /
i386 pic send command(I386 PIC OCW2 MASK EOI,1);

/ also send toi the primary pic /


i386 pic send command(I386 PIC OCW2 MASK EOI,0);

cdecl sound(unsigned int f) {


outportb(0x61,3 | unsigned char(f << 2));

void

cdecl inportb(unsigned short port num) {


MSC VER

unsigned char
#ifdef

asm {
mov dx,word ptr [port num]
in al,dx
mov byte ptr [port num],al

#endif

return unsigned char(port num);

void

cdecl outportb(unsigned short port num,unsigned char value) {


MSC VER

#ifdef

HAL

..
asm {
mov al,byte ptr[value]
mov dx,word ptr[port num]
out dx,al

#endif

cdecl enable irq() {


MSC VER

asm sti
#endif
void

#ifdef

cdecl disable irq() {


MSC VER

asm cli
#endif
void

#ifdef

void

cdecl set vector(unsigned int int num,void ( cdecl far & vect)
()) {
i386 idt install ir(int num,I386 IDT 32BIT | I386 IDT PRESENT /
10001110/,0x8 /code desc/,vect);

cdecl get vector(unsigned int int num))() {


idt desc desc = i386 get idt ir(int num);

void ( cdecl far

if (desc == 0)
return 0;

uint32 t address = desc>base low | (desc>base high << 16);

I386 IRQ HANDLER irq = (I386 IRQ HANDLER) address;


return irq;

const char

cdecl get cpu vendor() {


return i386 cpu vendor();

Interrupts

cdecl get tick count() {


return i386 pit get tick count();

int

Example
int

.: kernel/main.cpp

cdecl main()

hal init();
enable irq();

set
set
set
set
set
set
set
set
set
set
set
set
set
set
set
set
set
set

vector(0,(void ( cdecl &)(void))divide by zero fault);


vector(1,(void ( cdecl &)(void))single step trap);
vector(2,(void ( cdecl &)(void))nmi trap);
vector(3,(void ( cdecl &)(void))breakpoint trap);
vector(4,(void ( cdecl &)(void))overflow trap);
vector(5,(void ( cdecl &)(void))bounds check fault);
vector(6,(void ( cdecl &)(void))invalid opcode fault);
vector(7,(void ( cdecl &)(void))no device fault);
vector(8,(void ( cdecl &)(void))double fault abort);
vector(10,(void ( cdecl &)(void))invalid tss fault);
vector(11,(void ( cdecl &)(void))no segment fault);
vector(12,(void ( cdecl &)(void))stack fault);
vector(13,(void ( cdecl &)(void))general protection fault);
vector(14,(void ( cdecl &)(void))page fault);
vector(16,(void ( cdecl &)(void))fpu fault);
vector(17,(void ( cdecl &)(void))alignment check fault);
vector(18,(void ( cdecl &)(void))machine check abort);
vector(19,(void ( cdecl &)(void))simd fpu fault);

...

Example
/

.: kernel/excep

on.h

Execption Handler /

/ Divide by zero

extern void

cdecl divide by zero fault(uint32 t cs,uint32 t eip,


uint32 t eflags);

HAL

..

/ Single step
extern void

/
cdecl single step trap(uint32 t cs,uint32 t eip,uint32 t

eflags);

/ No Maskable interrupt trap


extern void

/
cdecl nmi trap(uint32 t cs,uint32 t eip,uint32 t eflags)

/ Breakpoint hit
extern void

/
cdecl breakpoint trap(uint32 t cs,uint32 t eip,uint32 t

eflags);

/ Overflow trap
extern void

/
cdecl overflow trap(uint32 t cs,uint32 t eip,uint32 t

eflags);

/ Bounds check

extern void

cdecl bounds check fault(uint32 t cs,uint32 t eip,


uint32 t eflags);

/ invalid opcode instruction

/
cdecl invalid opcode fault(uint32 t cs,uint32 t eip,
uint32 t eflags);

extern void

/ Device not available


extern void

cdecl no device fault(uint32 t cs,uint32 t eip,uint32 t

eflags);

/ Double Fault

/
cdecl double fault abort(uint32 t cs,uint32 t err,
uint32 t eip,uint32 t eflags);

extern void

/ Invalid TSS

extern void

cdecl invalid tss fault(uint32 t cs,uint32 t err,


uint32 t eip,uint32 t eflags);

/ Segment not present

/
cdecl no segment fault(uint32 t cs,uint32 t err,uint32 t
eip,uint32 t eflags);

extern void

Interrupts

/ Stack fault

/
cdecl stack fault(uint32 t cs,uint32 t err,uint32 t eip,
uint32 t eflags);

extern void

/ General Protection Fault

extern void

cdecl general protection fault(uint32 t cs,uint32 t err,


uint32 t eip,uint32 t eflags);

/ Page Fault

/
cdecl page fault(uint32 t cs,uint32 t err,uint32 t eip,
uint32 t eflags);

extern void

/ FPU error

extern void

cdecl fpu fault(uint32 t cs,uint32 t eip,uint32 t eflags

);

/ Alignment Check

/
cdecl alignment check fault(uint32 t cs,uint32 t err,
uint32 t eip,uint32 t eflags);

extern void

/ Machine Check

extern void

cdecl machine check abort(uint32 t cs,uint32 t eip,


uint32 t eflags);

/ FPU Single Instruction Multiple Data (SIMD) error


extern void

/
cdecl simd fpu fault(uint32 t cs,uint32 t eip,uint32 t

eflags);

Example

.: kernel/excep

on.cpp

/ Divide by zero

/
cdecl divide by zero fault(uint32 t cs,uint32 t eip,uint32 t
eflags) {
kernel panic("Divide by 0");
for (;;);

void

Example

.: kernel/panic.cpp

void

cdecl kernel panic(const char msg,...) {

HAL

..

disable irq();

va
va
/
va

list args;
start(args,msg);
missing /
end(args);

char panic = "\nSorry, eqraOS has encountered a problem and has


been shutdown.\n\n";

kclear(0x1f);
kgoto xy(0,0);
kset color(0x1f);
kputs(panic);
kprintf(" STOP: %s",msg);

/ hang /
for (;;) ;

HAL

:..

Interrupts

:..

.
) (RAM

.
) (Memory Manager

.

.

..

Physical Memory Management

) (Physical Memoery
)
(DRAM
) (North Bridge

0x0 0x1
.

.
). (Physical Address Space

n n-1 2n-1
) (Holes
.


.
RAM

...


.

.
.

int 0x12

) (0x413

. .

.: Using int 0x12 to get size of memory

Example

;
; get conventional memory size
; ret ax=KB size from address 0

;
get conventional memory size:

int 0x12
ret

0x15

0xe801

:CF .

:EAX 1 MB .16 MB

:EBX 16 MB
.

Physical Memory Management

..

. .EBX EAX EDX ECX


.
Example

.: Using int 0x15 Func

on 0xe801 to get size of memory

; get memory size:


; get a total memory size.except the first MB.
; return:
;
;
;
;

ax=KB between 1MB and 16MB


bx=number of 64K blocks above 16MB
bx=0 and ax= 1 on error

get memory size:

push ecx
push edx
xor ecx,ecx
xor edx,edx

mov ax,0x801
int 0x15

jc .error
cmp ah,0x86
je .error
cmp ah,0x80
je .error

jcxz .use eax

mov ax,cx
mov bx,dx

.use eax:
pop edx
pop ecx
ret

.error:

; BIOS get memory size

.
ax,1
bx,0
edx
ecx

mov
mov
pop
pop
ret


) (ax
bx
2*64 128.

...

Memory Map

)
(
. int 0x15
e820 :

:CF .

:eax 0x534d4150 SMAP ASCII


.ah

:ebx .

:ecx .

:es:di .

:eax .0xe820

:ebx .

:ecx ) (buer .

:edx 0x534d4150 SMAP .ASCII

:es:di buer .

..

Physical Memory Management

Buer
ebx . ..
.: Memory Map Entry Structure

Example

; Memory Map Entry Structure


struc memory map entry

.base addr resq 1


.length
resq 1
.type
resd 1
.acpi null resd 1
endstruc

.
:

:1 .

:2 .

ACPI Reclaim Memory :3 .

ACPI NVS Memory:4 .

. .
.: Get Memory Map

Example

; get memory map:


; Input:

0x0000E820
continuation value or 0 to start at beginning of map
)size of buffer for result (Must be >= 20 bytes
)'0x534D4150h ('SMAP
= Buffer for result

= EAX
= EBX
= ECX
= EDX
ES:DI

;
;
;
;
;
;

; Return:

CF = clear if successful

.
;
;
;
;
;
;

EAX = 0x534D4150h ('SMAP')


EBX = offset of next entry to copy from or 0 if done
ECX = actual length returned in bytes
ES:DI = buffer filled
If error, AH containes error code

get memory map:

pushad
xor ebx,ebx
xor bp,bp
mov edx,'PAMS'
; 0x534D4150
mov eax,0xe820
mov ecx,24
int 0x15
; BIOS get memory map.

jc .error
cmp eax,'PAMS'
jne .error

test ebx,ebx
je .error

jmp .start

.next
mov
mov
mov
int

entry:
edx,'PAMS'
; 0x534D4150
eax,0xe820
ecx,24
0x15
; BIOS get memory map.

.start:
jcxz .skip entry

mov ecx,[es:di + memory map entry.length]


test ecx,ecx
jne short .good entry
mov ecx,[es:di + memory map entry.length+4]
jecxz .skip entry

.good entry:

..

Physical Memory Management

inc bp
add di,24

entry:
ebx,0
.next entry
.done

.skip
cmp
jne
jmp

; set carry flag

.error:
stc

.done:
popad
ret

endstruc

...
) (Bootloader
.
) (Mul boot Informa on .

.

.

) (Machine State
:

:eax 0x2BADB002
.

:ebx .

.
0x0 / :cs
.0x

:ds,es,fs,gs,ss
.0x

.a20

) ) ( 0 :cr0
.(

0x0


ebx


. .(stack)
.
Example

.: Mul

boot Inforam on Structure

boot info:

istruc multiboot info

at
at
at
at
at
at
at
at
at
at
at
at
at
at
at
at
at

multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot
multiboot

info.flags,
dd 0
info.mem low,
dd 0
info.mem high,
dd 0
info.boot device,
dd 0
info.cmd line,
dd 0
info.mods count,
dd 0
info.mods addr,
dd 0
info.sym0,
dd 0
info.sym1,
dd 0
info.sym2,
dd 0
info.mmap length,
dd 0
info.mmap addr,
dd 0
info.drives length,
dd 0
info.drives addr,
dd 0
info.config table,
dd 0
info.bootloader name,
dd 0
info.apm table,
dd 0

Physical Memory Management

at
at
at
at
at
iend

multiboot
multiboot
multiboot
multiboot
multiboot

..

info.vbe
info.vbe
info.vbe
info.vbe
info.vbe

control info,
dd
mode info,
dw 0
interface seg, dw
interface off, dw
interface len, dw

0
0
0
0

ags
mem high mem low ags[0]
mem low ags .
mem high
mmap length mmap addr
. .
.
Example

.: snippet from stage2 bootloader

...
; when stage2 begin started, BIOS put drive number where stage1 are

loaded from in dl
mov [boot info+multiboot info.boot device],dl

...

;
; Get Memory Size

xor eax,eax
xor ebx,ebx
call get memory size

mov [boot info+multiboot info.mem low],ax


mov [boot info+multiboot info.mem high],bx

...

;
; Pass MultiBoot Info to the Kernel

mov eax,0x2badb002

mov ebx,0
mov edx,[kernel size]
push dword boot info

call ebp

; Call Kernel


) (
. . .
Example

void

.: Kernel Entry
cdecl kernel entry (multiboot info boot info)

#ifdef i386

asm {
cli

mov
mov
mov
mov
mov

ax,
ds,
es,
fs,
gs,

10h
ax
ax
ax
ax

// select data descriptor in GDT.

#endif

// Execute global constructors


init ctor();

// Call kernel entry point


main(boot info);

// Cleanup all dynamic dtors


exit();

#ifdef i386

asm {
cli
hlt

Physical Memory Management

..

#endif

for(;;);

...
Example

.: Physical Memory Manager Interface

#ifndef PMM H
#define PMM H

#include

<stdint.h>

extern void pmm init(size t size,uint32 t base);


extern void pmm init region(uint32 t base,size t size);
extern void pmm deinit region(uint32 t base,size t size);

extern void pmm alloc();

extern void pmm allocs(size t size);


extern void pmm dealloc(void);

extern void pmm deallocs(void,size t);


extern size t pmm get mem size();
extern uint32 t pmm get block count();
extern uint32 t pmm get used block count();
extern uint32 t pmm get free block count();
extern uint32 t pmm get block size();
extern void pmm enable paging(bool);
extern bool pmm is paging();
extern void pmm load PDBR(uint32 t);
extern uint32 t pmm get PDBR();

#endif // PMM H

Example

.: Physical Memory Manager Implemeta

on

.
#include

<string.h>

#include "pmm.h"
#include "kdisplay.h"

#define PMM BLOCK PER BYTE

#define PMM PAGE SIZE

4096
PMM PAGE SIZE
#define PMM BLOCK ALIGN
PMM BLOCK SIZE
#define PMM BLOCK SIZE

static uint32 t

pmm mem size = 0;


pmm max blocks = 0;
static uint32 t pmm used blocks = 0;
static uint32 t pmm mmap = 0;
static uint32 t

inline void mmap set(int bit)

pmm mmap[bit/32] =

pmm mmap[bit/32] | (1 << (bit%32)) ;

inline void mmap unset(int bit)

pmm mmap[bit/32] =

pmm mmap[bit/32] & (1 << (bit%32));

{
return pmm mmap[bit/32] & (1 << (bit%32));

inline bool mmap test(int bit)

int mmap find first()

for (uint32 t i=0;i<pmm get free block count()/32;++i) {


if ( pmm mmap[i] != 0xffffffff) {
for (int j=0;j<32;++j) {
int bit = 1 << j;
if (!( pmm mmap[i] & bit))
return i32+j;

return 1;

Physical Memory Management

..

int mmap find squence(size t s)

if (s == 0)
return 1;

if (s == 1)
return mmap find first();

for (uint32 t i=0;i<pmm get free block count()/32;++i) {


if ( pmm mmap[i] != 0xffffffff) {
for (int j=0;j<32;++j) {
int bit = 1 << j;
if (!( pmm mmap[i] & bit)) {

int start bit = i32 + bit;


uint32 t free bit = 0;

for (uint32 t count=0;count<=s;++count) {


if (!(mmap test(start bit+count)))
free bit++;

if (free bit == s)
return i32+j;

return 1;

void pmm init(size t size,uint32 t mmap base)

pmm
pmm
pmm
pmm

mem size = size;


mmap = (uint32 t )mmap base;
max blocks = pmm mem size 1024 / PMM BLOCK SIZE;
used blocks = pmm max blocks; // all memory used by default

memset( pmm mmap,0xf, pmm max blocks/PMM BLOCK PER BYTE);

.
void pmm init region(uint32 t base,size t size)

int align = base/PMM BLOCK SIZE;


int blocks = size/PMM BLOCK SIZE;

for (;blocks >=0;blocks) {


mmap unset(align++);
pmm used blocks;

mmap set(0);

void pmm deinit region(uint32 t base,size t size)

int align = base/PMM BLOCK SIZE;


int blocks = size/PMM BLOCK SIZE;

for (;blocks >=0;blocks) {


mmap set(align++);
pmm used blocks++;

void pmm alloc()

if (pmm get free block count() <= 0)


return 0;

int block = mmap find first();

if (block == 1)
return 0;

mmap set(block);

uint32 t addr = block PMM BLOCK SIZE;


pmm used blocks++;

return (void) addr;

void pmm allocs(size t s)

if (pmm get free block count() <= s)

Physical Memory Management

..

return 0;

int block = mmap find squence(s);

if (block == 1)
return 0;

for (uint32 t i=0;i<s;++i)


mmap set(block+i);

uint32 t addr = block PMM BLOCK SIZE;


pmm used blocks += s;

return (void) addr;

void pmm dealloc(void p)

uint32 t addr = (uint32 t)p;


int block = addr / PMM BLOCK SIZE;
mmap unset(block);
pmm used blocks;

void pmm deallocs(void p,size t s)

uint32 t addr = (uint32 t)p;


int block = addr / PMM BLOCK SIZE;

for (uint32 t i=0;i<s;++i)


mmap unset(block+i);

pmm used blocks = s;

size t pmm get mem size()

return

pmm mem size;

uint32 t pmm get block count()

return

pmm max blocks;

.
uint32 t pmm get used block count()

return

uint32 t pmm get free block count()

return

uint32 t pmm get block size()

pmm max blocks pmm used blocks;

pmm used blocks;

return PMM BLOCK SIZE;

void pmm enable paging(bool val)

#ifdef

MSC VER
asm {

mov eax,cr0
cmp [val],1
je enable
jmp disable

enable:
or eax,0x80000000
mov cr0,eax
jmp done

// set last bit

disable:
and eax,0x7fffffff // unset last bit
mov cr0,eax

done:

#endif

bool pmm is paging()

uint32 t val = 0;
#ifdef MSC VER

asm {

mov eax,cr0

Virtual Memory Management

..

mov [val],eax

if ( val & 0x80000000 )


false;

else

true;
#endif

void pmm load PDBR(uint32 t addr)

#ifdef

MSC VER
asm {
mov eax,[addr]
mov cr3,eax

#endif

uint32 t pmm get PDBR()


#ifdef

MSC VER

asm {
mov eax,cr3
ret

#endif

Virtual Memory Management


Example

.: Virtual Memory Manager Interface

#ifndef VMM H
#define VMM H

#include

<stdint.h>

#include "vmm pte.h"


#include "vmm pde.h"

..

#define PTE N 1024


#define PDE N 1024

struct page table

uint32 t pte[PTE N];

};

struct page dir table

uint32 t pde[PDE N];

};

extern void vmm init();

extern bool vmm alloc page(uint32 t e);


extern void vmm free page(uint32 t e);

extern bool vmm switch page dir table(page dir table );


extern page dir table vmm get page dir table();
extern void vmm flush tlb entry(uint32 t addr);

extern void vmm page table clear(page table pt);


extern uint32 t vmm vir to page table index(uint32 t addr);

extern uint32 t vmm page table lookup entry(page table pt,uint32 t

addr);
extern uint32 t vmm vir to page dir table index(uint32 t addr);
extern void vmm page dir table clear(page dir table pd);

extern uint32 t vmm page dir table lookup entry(page dir table pd,

uint32 t addr);

#endif // VMM H

Example

.: Virtual Memory Manager Implemeta

on

#include "vmm.h"

#include

<string.h>

#include "vmm.h"
#include "pmm.h"

#define PAGE SIZE

4096

Virtual Memory Management

..

#define PT ADDRESS SPACE SIZE 0x400000


#define PD ADDRESS SPACE SIZE 0x100000000

page dir table


uint32 t

cur page dir = 0;


cur page dir base register = 0;

void vmm init()

page table pt = (page table ) pmm alloc();


if (!pt)
return ;

vmm page table clear(pt);

for (int i=0, frame =0; i < 1024 ; ++i, frame += 4096) {
uint32 t page = 0;
pte add attrib(&page,I386 PTE PRESENT);
pte set frame(&page,frame);

pt>pte[vmm vir to page table index(frame)] = page;

page dir table pd = (page dir table ) pmm allocs(3);


if (!pd)
return ;

vmm page dir table clear(pd);

uint32 t pde = vmm page dir table lookup entry(pd,0);


pde add attrib(pde,I386 PDE PRESENT);
pde add attrib(pde,I386 PDE WRITABLE);
pde set frame(pde,(uint32 t)pt);

cur page dir base register = (uint32 t) &pd>pde;


vmm switch page dir table(pd);

pmm enable paging(true);

bool vmm alloc page(uint32 t e)

void p = pmm alloc();

if (!p)
return false;

pte set frame(e,(uint32 t)p);


pte add attrib(e,I386 PTE PRESENT);

return true;

void vmm free page(uint32 t e)

void p = (void)pte get frame(e);

if (p)
pmm dealloc(p);

pte del attrib(e,I386 PTE PRESENT);

bool vmm switch page dir table(page dir table pd)

if (!pd)
return false;

cur page dir = pd;


pmm load PDBR( cur page dir base register);
return true;

page dir table vmm get page dir table()

return

cur page dir;

void vmm flush tlb entry(uint32 t addr)

#ifdef

MSC VER
asm {
cli
invlpg addr
sti

#endif

Virtual Memory Management

..

void vmm page table clear(page table pt)

if (pt)
memset(pt,0,sizeof(page table));

uint32 t vmm vir to page table index(uint32 t addr)

if ( addr >= PT ADDRESS SPACE SIZE )


return 0;
else
return addr / PAGE SIZE;

uint32 t vmm page table lookup entry(page table pt,uint32 t addr)

uint32 t vmm vir to page dir table index(uint32 t addr)

void vmm page dir table clear(page dir table pd)

if ( addr >= PD ADDRESS SPACE SIZE )


return 0;
else
return addr / PAGE SIZE;

if (pt)
return &pt>pte[vmm vir to page table index(addr)];
else
return 0;

if (pd)
memset(pd,0,sizeof(page dir table));

uint32 t vmm page dir table lookup entry(page dir table pd,uint32 t

addr) {
if (pd)
return &pd>pde[vmm vir to page table index(addr)];
else
return 0;

Example

Device Driver

Keyboard Driver

..

.: Keybaord Driver Interface

#ifndef KEYBOARD H
#define KEYBOARD H

#include

<stdint.h>

enum KEY CODE {

KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY

SPACE
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
G
H
I
J
K

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

' ',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',

Device Driver

KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY

L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
RETURN
ESCAPE
BACKSPACE
UP
DOWN
LEFT
RIGHT
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
DOT
COMMA
COLON
SEMICOLON

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'\r',
0x1001,
'\b',
0x1100,
0x1101,
0x1102,
0x1103,
0x1201,
0x1202,
0x1203,
0x1204,
0x1205,
0x1206,
0x1207,
0x1208,
0x1209,
0x120a,
0x120b,
0x120b,
0x120c,
0x120d,
0x120e,
'.',
',',
':',
';',

Keyboard Driver

..

KEY SLASH
KEY BACKSLASH
KEY PLUS
KEY MINUS
KEY ASTERISK
KEY EXCLAMATION
KEY QUESTION
KEY QUOTEDOUBLE
KEY QUOTE
KEY EQUAL
KEY HASH
KEY PERCENT
KEY AMPERSAND
KEY UNDERSCORE
KEY LEFTPARENTHESIS
KEY RIGHTPARENTHESIS
KEY LEFTBRACKET
KEY RIGHTBRACKET
KEY LEFTCURL
KEY RIGHTCURL
KEY DOLLAR
KEY POUND
KEY EURO
KEY LESS
KEY GREATER
KEY BAR
KEY GRAVE
KEY TILDE
KEY AT
KEY CARRET
KEY KP 0
KEY KP 1
KEY KP 2
KEY KP 3
KEY KP 4
KEY KP 5
KEY KP 6
KEY KP 7
KEY KP 8
KEY KP 9
KEY KP PLUS

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

'/',
' \\ ',
'+',
'',
'',
'!',
'?',
'\"',
'\'',
'=',
'#',
'%',
'&',
' ',
'(',
')',
'[',
']',
'{',
'}',
'$',
'',
'$',
'<',
'>',
' | ',
'`',
'',
'@',
'',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',

Device Driver

KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY
KEY

KP MINUS
KP DECIMAL
KP DIVIDE
KP ASTERISK
KP NUMLOCK
KP ENTER
TAB
CAPSLOCK
LSHIFT
LCTRL
LALT
LWIN
RSHIFT
RCTRL
RALT
RWIN
INSERT
DELETE
HOME
END
PAGEUP
PAGEDOWN
SCROLLLOCK
PAUSE
UNKNOWN,
NUMKEYCODES

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

'',
'.',
'/',
'',
0x300f,
0x3010,
0x4000,
0x4001,
0x4002,
0x4003,
0x4004,
0x4005,
0x4006,
0x4007,
0x4008,
0x4009,
0x400a,
0x400b,
0x400c,
0x400d,
0x400e,
0x400f,
0x4010,
0x4011,

};

extern bool keyboard get scroll lock();


extern bool keyboard get caps lock();
extern bool keyboard get num lock();
extern bool keyboard get alt();
extern bool keyboard get ctrl();
extern bool keyboard get shift();
extern void keyboard ignore resend();
extern bool keyboard check resend();
extern bool keyboard get diagnostic res();
extern bool keyboard get bat res();
extern bool keyboard self test();
extern uint8 t keyboard get last scan();
extern KEY CODE keyboard get last key();

Keyboard Driver

..

extern void keyboard discard last key();


extern void keyboard set leds(bool nums,bool caps,bool scroll);
extern char keyboard key to ascii(KEY CODE k);
extern void keyboard enable();
extern void keyboard disable();
extern bool keyboard is disabled();
extern void keyboard reset system();
extern void keyboard install(int);

#endif // KEYBOARD H

Example

.: Keybaord Driver Implemeta

void keyboard install(int irq)

on
{

// Install interrupt handler (irq 1 uses interrupt 33)


set vector(irq, i386 keyboard irq);

// assume BAT test is good. If there is a problem, the IRQ handler


where catch the error
keyboard bat res = true;
scancode = 0;

// set lock keys and led lights


numlock = scrolllock = capslock = false;
keyboard set leds (false, false, false);

// shift, ctrl, and alt keys


shift = alt = ctrl = false;

//

keyboard interrupt handler


void cdecl i386 keyboard irq () {

asm add esp, 12


asm pushad
asm cli

static bool

extended = false;

Device Driver

int code = 0;

// read scan code only if the keyboard controller output buffer is


full (scan code is in it)
if (keyboard ctrl read status () & KEYBOARD CTRL STATS MASK OUT BUF
) {

// read the scan code


code = keyboard enc read buf ();

// is this an extended code? If so, set it and return


if (code == 0xE0 | | code == 0xE1)
extended = true;
else {

// either the second byte of an extended scan code or a single


byte scan code
extended = false;

// test if this is a break code (Original XT Scan Code Set


specific)
if (code & 0x80) { //test bit 7

// covert the break code into its make code equivelant


code = 0x80;

// grab the key


int key = keyboard scancode std [code];

// test if a special key has been released & set it


switch (key) {

case KEY LCTRL:


case KEY RCTRL:
ctrl = false;
break;

case KEY LSHIFT:


case KEY RSHIFT:
shift = false;

Keyboard Driver

..

break;

case KEY LALT:


case KEY RALT:
alt = false;
break;

else {
// this is a make code set the scan code
scancode = code;

// grab the key


int key = keyboard scancode std [code];

// test if user is holding down any special keys & set it


switch (key) {

case KEY LCTRL:


case KEY RCTRL:
ctrl = true;
break;

case KEY LSHIFT:


case KEY RSHIFT:
shift = true;
break;

case KEY LALT:


case KEY RALT:
alt = true;
break;

case KEY CAPSLOCK:


capslock = ( capslock) ? false : true;
keyboard set leds ( numlock, capslock, scrolllock);
break;

case KEY KP NUMLOCK:


numlock = ( numlock) ? false : true;

Device Driver

keyboard set leds ( numlock,


break;

capslock,

scrolllock);

case KEY SCROLLLOCK:


scrolllock = ( scrolllock) ? false : true;
keyboard set leds ( numlock, capslock, scrolllock);
break;

// watch for errors


switch (code) {

case KEYBOARD ERR BAT FAILED:


keyboard bat res = false;
break;

case KEYBOARD ERR DIAG FAILED:


keyboard diag res = false;
break;

case KEYBOARD ERR RESEND CMD:


keyboard resend res = true;
break;

// tell hal we are done


int done(0);

// return from interrupt handler


asm sti
asm popad
asm iretd



.
.
.
. .



.

.
NASM

.
) GRUB
( .

.
First Fit

.Bit Map

Device Driver

.
FAT12,FAT16,FAT32,EXT3,EXT4,...etc .
:
.POSIX

.FAT12,FAT16,FAT32,EXT3,EXT4,...etc

) (port gcc,g++ x11 .

Bibliography
[] William Stallings, Operating System: Internals and Design Principles. Prentice Hall, 5th
Edition, 2004.
[] Andrew S. Tanenbaum ,Albert S Woodhull, Operating Systems Design and Implementation.
Prentice Hall, 3rd Edition, 2006.
[] Michael Tischer, Bruno Jennrich, PC Intern: The Encyclopedia of System Programming.
Abacus Software, 6th Edition, 1996.
[] Hans-Peter Messmer, The Indispensable PC Hardware Book. Addison-Wesley Professional, 4th Edition, 2001.
[] Andrew S. Tanenbaum, Structured Computer Organization. Prentice Hall, 4th Edition,
1998.
[] Ytha Yu,Charles Marut, Asssembly Language Programming and Organization IBM PC.
McGraw-Hill/Irwin, 1st Edition, 1992.
[] Intel Manuals, Intel 64 and IA-32 Architectures Software Developer's Manuals. http:
//www.intel.com/products/processor/manuals/
[] OSDev: http://wiki.osdev.org
[] brokenthorn: http://brokenthorn.com
[] Computer Sciense Student's Community in Sudan: http://sudancs.com
[] Wikipedia: http://wikipedia.org

.

.
++ .

..
..

You might also like