DRY up IDT

This commit is contained in:
Ciro Santilli
2015-10-23 17:57:12 +02:00
parent d5d35fc39a
commit 9e7ef0b763
4 changed files with 63 additions and 38 deletions

View File

@@ -12,6 +12,8 @@ Minimal examples are useful because it is easier to observe the requirements for
Another advantage is that it is easier to DRY up minimal examples (here done simply through `#include` and macros), which is much harder on progressive OS template tutorials, which tend to repeat big chunks of code between the examples.
Using C or not is a hard choice. It does make it much easier to express higher level ideas, and gives portability. But in the end, it increases the complexity that one has to understand, so we've stayed away from it.
## Pre-requisites
OS dev is one of the most insanely hard programming tasks a person can undertake, and will push your knowledge of several domains to the limit.

View File

@@ -457,3 +457,52 @@ loop:
add $12, %esp
POP_EDAX
.endm
.macro IDT_START
idt_start:
.endm
.macro IDT_END
idt_end:
/* Exact same structure as gdt_descriptor. */
idt_descriptor:
.word idt_end - idt_start
.long idt_start
.endm
.macro IDT_ENTRY
/* Low handler address.
It is impossible to write:
.word (handler & 0x0000FFFF)
as we would like:
http://stackoverflow.com/questions/18495765/invalid-operands-for-binary-and
So this must be done at runtime.
*/
.word 0
/* Segment selector: byte offset into the GDT. */
.word CODE_SEG
/* Reserved 0. */
.byte 0
/*
Flags. Format:
- 1 bit: present. If 0 and this happens, triple fault.
- 2 bits: ring level we will be called from.
- 5 bits: fixed to 0xE.
*/
.byte 0x8E
/* High word of base. */
.word 0
.endm
/*
- index: r/m/imm32 Index of the entry to setup.
- handler: r/m/imm32 Address of the handler function.
*/
.macro IDT_SETUP_ENTRY index, handler
mov \index, %eax
mov \handler, %ebx
mov %bx, idt_start(%eax, 8)
shr $16, %ebx
mov $6, %ecx
mov %bx, idt_start(%ecx, %eax, 8)
.endm

31
idt.S
View File

@@ -7,8 +7,6 @@ Expected output: "a"
The first 32 handlers are reserved by the processor and have predefined meanings.
0 is division by zero.
TODO on Linux kernel.
## lidt
@@ -26,34 +24,13 @@ BEGIN
STAGE2
CLEAR
PROTECTED_MODE
IDT_SETUP_ENTRY $0, $handler
lidt idt_descriptor
int $0
jmp .
idt_start:
/* Low handler address. */
/* TODO get this proper version working. */
/*.word (handler & 0x0000FFFF)*/
.word handler
/* Segment selector: byte offset into the GDT. */
.word CODE_SEG
/* Reserved 0. */
.byte 0
/*
Flags. Format:
- 1 bit: present. If 0 and this happens, triple fault.
- 2 bits: ring level we will be called from.
- 5 bits: fixed to 0xE.
*/
.byte 0x8E
/* High word of base. */
/* TODO get this proper version working. */
/*.word (handler >> 16) & 0xFFFF*/
.word 0
idt_end:
/* Exact same structure as gdt_descriptor. */
idt_descriptor:
.word idt_end - idt_start
.long idt_start
IDT_START
IDT_ENTRY
IDT_END
handler:
/* TODO needed? Molloy uses it. */
/*cli*/

View File

@@ -3,6 +3,10 @@
Division by zero causes a Divide Error which Intel notes as `#DE`.
Expected output: "a"
It is then handled by IDT 0.
Remember that DE is not *only* for division by zero: it also happens on overflow!
Thus the name: Division Error, and not Division by zero.
@@ -15,6 +19,7 @@ BEGIN
STAGE2
CLEAR
PROTECTED_MODE
IDT_SETUP_ENTRY $0, $handler
lidt idt_descriptor
mov $0, %edx
mov $1, %eax
@@ -22,17 +27,9 @@ BEGIN
/* The iret jumps back here! */
div %ecx
jmp .
/* TODO DRY up with idt.S */
idt_start:
.word handler
.word CODE_SEG
.byte 0
.byte 0x8E
.word 0
idt_end:
idt_descriptor:
.word idt_end - idt_start
.long idt_start
IDT_START
IDT_ENTRY
IDT_END
handler:
VGA_PRINT_STRING $message
/* If we don't do this, we get an infinite loop! */