This commit is contained in:
Ciro Santilli
2015-10-21 21:41:07 +02:00
parent 71e104bab0
commit 9e58c1dc65
8 changed files with 135 additions and 25 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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
View 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"

View File

@@ -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

View File

@@ -9,8 +9,7 @@ BEGIN
movw %cs, 0x02
mov $0, %ax
div %ax
jmp fail
hlt
handler:
PUTC $'a
fail:
hlt
iret