[edit]Bingo! I still don't know why, but the exception happens because I enable interrupts.[/edit]
Alright, this post has the whole textconsole.pas file (renamed textconsole.c w/o actual translation, can somebody please fix that!) and equus.pas. All the variables and functions related to working the GDT and IDT are in my RTL and debugged as damn near bug-free as I've been able to make them.
Code: Select all
program Equus;
uses Multiboot,Textconsole,Basic_Exceptions;
var
lwMagic: longword; cvar;
pMBInfo: PMultibootInformation; cvar;
procedure RemapPICs(PIC1,PIC2: byte);
var
data1,data2: Byte;
begin
{PIC1_COMMAND_PORT = $20
PIC1_DATA_PORT = $21}
InFromPort($21,data1);
{PIC2_COMMAND_PORT = $A0
PIC2_DATA_PORT = $A1}
InFromPort($A1,data2);
{ICW1_INIT = $10
ICW1_ICW4 = $01}
OutToPort($20,Byte($10 + $01));
IOWait();
OutToPort($A0,Byte($10 + $01));
IOWait();
OutToPort($21,PIC1);
IOWait();
OutToPort($A1,PIC2);
IOWait();
OutToPort($21,Byte(4));
IOWait();
OutToPort($A1,Byte(2));
IOWait();
{ICW4_8086 = $01 -- 8086 mode}
OutToPort($21,Byte($01));
IOWait();
OutToPort($A1,Byte($01));
IOWait();
OutToPort($21,data1);
OutToPort($A1,data2);
end;
begin
{Exit if the Multiboot information isn't correct.}
if (lwMagic <> MULTIBOOT_MAGIC) or (CheckMultibootFlags(pMBINfo) = false) then
Exit;
//Clear the screen and notify the user of the correct Multiboot information.
SetTextColor(COLOR_WHITE,COLOR_BLACK);
ClearScreen();
WriteLn(PChar('Multiboot magic number and flags correct.'));
{Set up the GDT.}
SetGDTEntry(0,0,0,0,0);
//Ring 0 segments. First Data, then Code.
SetGDTEntry(1,0,$FFFFFFFF,$92,$CF);
SetGDTEntry(2,0,$FFFFFFFF,$9A,$CF);
//Ring 1 segments. First Data, then Code.
SetGDTEntry(3,0,$FFFFFFFF,$B2,$CF);
SetGDTEntry(4,0,$FFFFFFFF,$BA,$CF);
//Ring 2 segments. First Data, then Code.
SetGDTEntry(5,0,$FFFFFFFF,$D2,$CF);
SetGDTEntry(6,0,$FFFFFFFF,$DA,$CF);
//Ring 3 segments. First Data, then Code.
SetGDTEntry(7,0,$FFFFFFFF,$F2,$CF);
SetGDTEntry(8,0,$FFFFFFFF,$FA,$CF);
//Set the GDT pointer.
pGDT.wLimit:= sizeof(TGDTEntry) * 9 - 1;
pGDT.pBase:= @geGDT[0];
//Set the GDT and segment registers.
SetGDT();
SetSegmentRegisters($08,$10);
//Notify the user the GDT is set up.
WriteLn(PChar('The Global Descriptor Table is set up with code and data segments for rings 1, 2 and 3.'));
{Remap the Programmable Interrupt Controllers. This is done for two reasons:
1. So normal interrupts firing from IRQ 0-7 don't trigger interrupts.
2. So all the IRQs from 0-F have consecutive entries in the IDT.}
RemapPICs($20,$28);
WriteLn(PChar('The Programmable Interrupt Controllers have been remapped to put IRQs $00-$0F at IDT entries $20-$28.'));
{Set up the Interrupt Descriptor Table with our basic exception handlers.}
//Zero out the IDT itself.
FillChar(ieIDT[0],0,256 * sizeof(TIDTEntry));
//Set our first and basic exception handlers.
SetExceptionHandler(0,Pointer(@DivisionByZero),$10,$8E);
SetExceptionHandler(1,Pointer(@Debug),$10,$8E);
SetExceptionHandler(2,Pointer(@NonMaskableInterrupt),$10,$8E);
SetExceptionHandler(3,Pointer(@Breakpoint),$10,$8E);
SetExceptionHandler(4,Pointer(@IntoDetectedOverflow),$10,$8E);
SetExceptionHandler(5,Pointer(@OutOfBounds),$10,$8E);
SetExceptionHandler(6,Pointer(@InvalidOpcode),$10,$8E);
SetExceptionHandler(7,Pointer(@NoCoprocessor),$10,$8E);
SetExceptionHandler(8,Pointer(@DoubleFault),$10,$8E);
SetExceptionHandler(9,Pointer(@CoprocessorSegmentOverrun),$10,$8E);
SetExceptionHandler(10,Pointer(@BadTSS),$10,$8E);
SetExceptionHandler(11,Pointer(@SegmentNotPresent),$10,$8E);
SetExceptionHandler(12,Pointer(@StackFault),$10,$8E);
SetExceptionHandler(13,Pointer(@GeneralProtectionFault),$10,$8E);
SetExceptionHandler(14,Pointer(@PageFault),$10,$8E);
SetExceptionHandler(15,Pointer(@UnknownInterrupt),$10,$8E);
SetExceptionHandler(16,Pointer(@CoprocessorFault),$10,$8E);
SetExceptionHandler(17,Pointer(@AlignmentCheck),$10,$8E);
SetExceptionHandler(18,Pointer(@MachineCheck),$10,$8E);
SetExceptionHandler(19,Pointer(@Reserved),$10,$8E);
//Set the IDT pointer.
pIDT.wLimit:= 256 * sizeof(TIDTEntry) - 1;
pIDT.pBase:= @ieIDT[0];
SetIDT();
WriteLn(PChar('The basic exceptions are installed and so is the Interrupt Descriptor Table.'));
{We have the PICs and IDT set, so we should be able to enable interrupts.}
//Warning: enabling interrupts is DANGEROUS.
EnableInterrupts();
WriteLn(PChar('Interrupts are enabled.'));
//While loop forever.
while true do
begin
end;
end.