idt
This commit is contained in:
@@ -36,7 +36,6 @@ Minimal operating systems to learn low level programming.
|
|||||||
1. [int $1](interrupt1.S)
|
1. [int $1](interrupt1.S)
|
||||||
1. [Interrupt zero divide](interrupt_zero_divide.S)
|
1. [Interrupt zero divide](interrupt_zero_divide.S)
|
||||||
1. [Interrupt loop](interrupt_loop.S)
|
1. [Interrupt loop](interrupt_loop.S)
|
||||||
1. [lidt (TODO)](lidt.S)
|
|
||||||
1. in
|
1. in
|
||||||
1. [in keyboard](in_keyboard.S)
|
1. [in keyboard](in_keyboard.S)
|
||||||
1. [in RTC](in_rtc.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 beep_illinois](in_beep_illinois.S)
|
||||||
1. [in mouse (TODO)](in_mouse.S)
|
1. [in mouse (TODO)](in_mouse.S)
|
||||||
1. [Protected mode](protected_mode.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. Segmentation fault handler: memory bound, ring, RWX violations
|
||||||
1. APM
|
1. APM
|
||||||
1. [APM shutdown](apm_shutdown.S)
|
1. [APM shutdown](apm_shutdown.S)
|
||||||
|
|||||||
11
TODO.md
11
TODO.md
@@ -114,4 +114,13 @@
|
|||||||
|
|
||||||
- mouse
|
- mouse
|
||||||
|
|
||||||
- DOS question: http://stackoverflow.com/questions/23043732/accessing-the-mouse-via-assembly-x86
|
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
|
pop %ax
|
||||||
.endm
|
.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.
|
Convert the low nibble of a r8 reg to ASCII of 8-bit in-place.
|
||||||
reg: r8 to be converted
|
reg: r8 to be converted
|
||||||
@@ -155,7 +169,6 @@ Use the simplest GDT possible.
|
|||||||
.equ CODE_SEG, 8
|
.equ CODE_SEG, 8
|
||||||
.equ DATA_SEG, gdt_data - gdt_start
|
.equ DATA_SEG, gdt_data - gdt_start
|
||||||
|
|
||||||
cli
|
|
||||||
/* Tell the processor where our Global Descriptor Table is in memory. */
|
/* Tell the processor where our Global Descriptor Table is in memory. */
|
||||||
lgdt gdt_descriptor
|
lgdt gdt_descriptor
|
||||||
|
|
||||||
@@ -177,6 +190,9 @@ Our GDT contains:
|
|||||||
- it is impossible execute the data segment
|
- it is impossible execute the data segment
|
||||||
Both start at 0 and span the entire memory,
|
Both start at 0 and span the entire memory,
|
||||||
allowing us to access anything without problems.
|
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_start:
|
||||||
gdt_null:
|
gdt_null:
|
||||||
@@ -372,10 +388,7 @@ Loops around the to the top.
|
|||||||
*/
|
*/
|
||||||
.macro VGA_PRINT_STRING s
|
.macro VGA_PRINT_STRING s
|
||||||
LOCAL loop, end
|
LOCAL loop, end
|
||||||
push %eax
|
PUSH_EADX
|
||||||
push %ebx
|
|
||||||
push %ecx
|
|
||||||
push %edx
|
|
||||||
mov \s, %ecx
|
mov \s, %ecx
|
||||||
mov vga_current_line, %eax
|
mov vga_current_line, %eax
|
||||||
mov $0, %edx
|
mov $0, %edx
|
||||||
@@ -400,10 +413,7 @@ loop:
|
|||||||
jmp loop
|
jmp loop
|
||||||
end:
|
end:
|
||||||
incl vga_current_line
|
incl vga_current_line
|
||||||
pop %edx
|
POP_EDAX
|
||||||
pop %ecx
|
|
||||||
pop %ebx
|
|
||||||
pop %eax
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -420,10 +430,7 @@ Expected output on screen:
|
|||||||
*/
|
*/
|
||||||
.macro VGA_PRINT_REG reg=<%eax>
|
.macro VGA_PRINT_REG reg=<%eax>
|
||||||
LOCAL loop
|
LOCAL loop
|
||||||
push %eax
|
PUSH_EADX
|
||||||
push %ebx
|
|
||||||
push %ecx
|
|
||||||
push %edx
|
|
||||||
/* Null terminator. */
|
/* Null terminator. */
|
||||||
mov \reg, %ecx
|
mov \reg, %ecx
|
||||||
|
|
||||||
@@ -448,8 +455,5 @@ loop:
|
|||||||
|
|
||||||
/* Restore the stack. We have pushed 3 * 4 bytes. */
|
/* Restore the stack. We have pushed 3 * 4 bytes. */
|
||||||
add $12, %esp
|
add $12, %esp
|
||||||
pop %edx
|
POP_EDAX
|
||||||
pop %ecx
|
|
||||||
pop %ebx
|
|
||||||
pop %eax
|
|
||||||
.endm
|
.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.
|
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>
|
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:
|
I think this is mandatory, e.g. a `jmp` wouldn't be enough because:
|
||||||
|
|
||||||
- we may have far jumped
|
- 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
|
## ISR
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ BEGIN
|
|||||||
movw %cs, 0x02
|
movw %cs, 0x02
|
||||||
mov $0, %ax
|
mov $0, %ax
|
||||||
div %ax
|
div %ax
|
||||||
jmp fail
|
hlt
|
||||||
handler:
|
handler:
|
||||||
PUTC $'a
|
PUTC $'a
|
||||||
fail:
|
iret
|
||||||
hlt
|
|
||||||
|
|||||||
Reference in New Issue
Block a user