idt
This commit is contained in:
@@ -36,7 +36,6 @@ Minimal operating systems to learn low level programming.
|
||||
1. [int $1](interrupt1.S)
|
||||
1. [Interrupt zero divide](interrupt_zero_divide.S)
|
||||
1. [Interrupt loop](interrupt_loop.S)
|
||||
1. [lidt (TODO)](lidt.S)
|
||||
1. in
|
||||
1. [in keyboard](in_keyboard.S)
|
||||
1. [in RTC](in_rtc.S)
|
||||
@@ -45,7 +44,9 @@ Minimal operating systems to learn low level programming.
|
||||
1. [in beep_illinois](in_beep_illinois.S)
|
||||
1. [in mouse (TODO)](in_mouse.S)
|
||||
1. [Protected mode](protected_mode.S)
|
||||
1. [Segment base](segment_base.S)
|
||||
1. [Segment base (TODO)](segment_base.S)
|
||||
1. [IDT TODO](idt.S)
|
||||
1. [IDT zero divide](idt_zero_divide.S)
|
||||
1. Segmentation fault handler: memory bound, ring, RWX violations
|
||||
1. APM
|
||||
1. [APM shutdown](apm_shutdown.S)
|
||||
|
||||
9
TODO.md
9
TODO.md
@@ -114,4 +114,13 @@
|
||||
|
||||
- mouse
|
||||
|
||||
Does not seem to be an easy BIOS way:
|
||||
|
||||
- DOS question: http://stackoverflow.com/questions/23043732/accessing-the-mouse-via-assembly-x86
|
||||
|
||||
- http://stackoverflow.com/questions/5754233/int-33h-doesnt-work
|
||||
|
||||
- Linux questions:
|
||||
|
||||
- http://stackoverflow.com/questions/15322892/linux-usb-mouse-drivers
|
||||
- http://stackoverflow.com/questions/25175960/which-drivers-are-used-by-usb-mouse-in-linux-kernel
|
||||
|
||||
38
common.h
38
common.h
@@ -53,6 +53,20 @@ so this cancels that one.
|
||||
pop %ax
|
||||
.endm
|
||||
|
||||
.macro PUSH_EADX
|
||||
push %eax
|
||||
push %ebx
|
||||
push %ecx
|
||||
push %edx
|
||||
.endm
|
||||
|
||||
.macro POP_EDAX
|
||||
pop %edx
|
||||
pop %ecx
|
||||
pop %ebx
|
||||
pop %eax
|
||||
.endm
|
||||
|
||||
/*
|
||||
Convert the low nibble of a r8 reg to ASCII of 8-bit in-place.
|
||||
reg: r8 to be converted
|
||||
@@ -155,7 +169,6 @@ Use the simplest GDT possible.
|
||||
.equ CODE_SEG, 8
|
||||
.equ DATA_SEG, gdt_data - gdt_start
|
||||
|
||||
cli
|
||||
/* Tell the processor where our Global Descriptor Table is in memory. */
|
||||
lgdt gdt_descriptor
|
||||
|
||||
@@ -177,6 +190,9 @@ Our GDT contains:
|
||||
- it is impossible execute the data segment
|
||||
Both start at 0 and span the entire memory,
|
||||
allowing us to access anything without problems.
|
||||
A real OS might have 2 extra segments: user data and code.
|
||||
This is better than modifying the privilege bit of the GDT
|
||||
as we'd have to reload it several times, losing cache.
|
||||
*/
|
||||
gdt_start:
|
||||
gdt_null:
|
||||
@@ -372,10 +388,7 @@ Loops around the to the top.
|
||||
*/
|
||||
.macro VGA_PRINT_STRING s
|
||||
LOCAL loop, end
|
||||
push %eax
|
||||
push %ebx
|
||||
push %ecx
|
||||
push %edx
|
||||
PUSH_EADX
|
||||
mov \s, %ecx
|
||||
mov vga_current_line, %eax
|
||||
mov $0, %edx
|
||||
@@ -400,10 +413,7 @@ loop:
|
||||
jmp loop
|
||||
end:
|
||||
incl vga_current_line
|
||||
pop %edx
|
||||
pop %ecx
|
||||
pop %ebx
|
||||
pop %eax
|
||||
POP_EDAX
|
||||
.endm
|
||||
|
||||
/*
|
||||
@@ -420,10 +430,7 @@ Expected output on screen:
|
||||
*/
|
||||
.macro VGA_PRINT_REG reg=<%eax>
|
||||
LOCAL loop
|
||||
push %eax
|
||||
push %ebx
|
||||
push %ecx
|
||||
push %edx
|
||||
PUSH_EADX
|
||||
/* Null terminator. */
|
||||
mov \reg, %ecx
|
||||
|
||||
@@ -448,8 +455,5 @@ loop:
|
||||
|
||||
/* Restore the stack. We have pushed 3 * 4 bytes. */
|
||||
add $12, %esp
|
||||
pop %edx
|
||||
pop %ecx
|
||||
pop %ebx
|
||||
pop %eax
|
||||
POP_EDAX
|
||||
.endm
|
||||
|
||||
2
debug.md
2
debug.md
@@ -6,7 +6,7 @@ This will only cover specifics, you have to know GDB debugging already.
|
||||
|
||||
First read the `make debug` target to get started. Those points will not be repeated here.
|
||||
|
||||
How to have debug symbols: <http://stackoverflow.com/a/32960272/895245> TODO implement here.
|
||||
How to have debug symbols: <http://stackoverflow.com/a/32960272/895245> TODO implement here. Needs to point GDB to an ELF file in addition to the remote listen.
|
||||
|
||||
How to step over `int` calls: <http://stackoverflow.com/questions/24491516/how-to-step-over-interrupt-calls-when-debugging-a-bootloader-bios-with-gdb-and-q>
|
||||
|
||||
|
||||
63
idt.S
Normal file
63
idt.S
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
# IDT
|
||||
|
||||
# Interrupt Descriptor Table
|
||||
|
||||
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
|
||||
|
||||
Analogous to lgdt but for the IDT.
|
||||
|
||||
## Bibliography
|
||||
|
||||
- http://www.jamesmolloy.co.uk/tutorial_html/4.-The%20GDT%20and%20IDT.html
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
BEGIN
|
||||
STAGE2
|
||||
CLEAR
|
||||
PROTECTED_MODE
|
||||
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
|
||||
handler:
|
||||
/* TODO needed? Molloy uses it. */
|
||||
/*cli*/
|
||||
VGA_PRINT_STRING $message
|
||||
iret
|
||||
message:
|
||||
.asciz "a"
|
||||
34
idt_zero_divide.S
Normal file
34
idt_zero_divide.S
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
# IDT Zero Divide
|
||||
|
||||
TODO why does it enter an infinite loop? How to prevent it?
|
||||
|
||||
Division by zero causes a Divide Error which Intel notes as `#DE`.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
BEGIN
|
||||
STAGE2
|
||||
CLEAR
|
||||
PROTECTED_MODE
|
||||
lidt idt_descriptor
|
||||
mov $0, %eax
|
||||
div %eax
|
||||
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
|
||||
handler:
|
||||
VGA_PRINT_STRING $message
|
||||
iret
|
||||
message:
|
||||
.asciz "a"
|
||||
@@ -24,7 +24,7 @@ before the interrupt came in.
|
||||
I think this is mandatory, e.g. a `jmp` wouldn't be enough because:
|
||||
|
||||
- we may have far jumped
|
||||
- iret also pops EFLAGS restoring
|
||||
- iret also pops EFLAGS restoring. TODO more things also seem restored: CS, EIP, EFLAGS, SS, and ESP
|
||||
|
||||
## ISR
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ BEGIN
|
||||
movw %cs, 0x02
|
||||
mov $0, %ax
|
||||
div %ax
|
||||
jmp fail
|
||||
hlt
|
||||
handler:
|
||||
PUTC $'a
|
||||
fail:
|
||||
hlt
|
||||
iret
|
||||
|
||||
Reference in New Issue
Block a user