User:Mr.Confuzed

From OSDev Wiki
Jump to navigation Jump to search

The following is the NASM source code for my OS (actually, it's just a boot program). It boots into protected mode and lets you type stuff on the text mode screen with a custom cursor. Really basic, but it now uses a GDT and an IDT.

I have some fairly lofty goals for this, but it is a hobby OS and I'm trying to keep it simple specifically for now while I'm still learning. I'm currently thinking about adding memory management.

Mr.Confuzed - Feb. 19, 2007


[BITS 16]
[ORG 0x7C00]



 Boot_loader:
;Parameter from BIOS: dl = boot drive

;Set default state
cli
xor bx,bx
mov es,bx
mov fs,bx
mov gs,bx
mov ds,bx
mov ss,bx
mov sp,0x7C00
sti

 jmp 0:Clear_cs
 Clear_cs:

;Load kernel from floppy disk
;Int 0x13 Function 0x02 (Load sectors)
;ah = Function 0x02
;al = Number of sectors
;cx = Cylinder and sector
;dx = Head and drive number
;es:bx = Destination
mov ax,0x020F
mov bx,0x7E00
mov cx,0x0002
xor dh,dh
int 0x13

;Set screen to 80x50 text mode (8x8 font)
mov ax,0x1112
xor bl,bl
int 0x10

;Enable A20 via keyboard controller
call Wait_for_keyboard_controller
;Out A20 control
mov al,0xD1
out 0x64,al
call Wait_for_keyboard_controller
;Out Enable A20
mov al,0xDF
out 0x60,al

;Enter protected mode
lgdt[Reference_GDT]
mov eax,cr0
or al,0x01
mov cr0,eax

;Jump to kernel
 jmp Code_GDT:Kernel



Wait_for_keyboard_controller:
mov cx,0xFFFF
Loop_Wait_for_keyboard_controller:
in al,0x64
test al,2
loopnz Loop_Wait_for_keyboard_controller
 ret



;Global Descriptor Table reference:
;16 Length
;32 Physical Address

;GDT descriptor format:
;16 Limit
;24 Base
;1 Present (1)
;2 Privilege (ring)
;1 (1)
;1 Executable
;1 Direction/Conforming
;1 Readable/Writable
;1 Accessed (0)
;1 Limit granularity (0=byte,1=4kilobyte)
;1 Size (1)
;2 (0)
;4 Limit
;8 Base

;Note that dd produces data in little endian order (bytes are backwards).

 Reference_GDT:
dw End_GDT - GDT - 1
dd GDT
 GDT:
dd 0x00000000
dd 0x00000000
 Code_GDT equ $ - GDT
dd 0x0000FFFF
dd 0x00CF9A00
 Data_GDT equ $ - GDT
dd 0x0000FFFF
dd 0x00CF9200
 Video_GDT equ $ - GDT
dd 0x80001F3F
dd 0x0000920B
 End_GDT:



;Fix boot sector size
times 510-($-$$) db 0
;Boot loader signature
dw 0xAA55



[BITS 32]



 Kernel:

;Set default state
cli
mov ax,Data_GDT 
mov ds,ax
mov es,ax
mov fs,ax
mov ss,ax
mov ax,Video_GDT
mov gs,ax
mov esp,0x00007C00

call Clear_screen

;Display Hello World in protected mode
mov esi,Hello_World
xor edi,edi
call Write_string
mov word [ds:Insertion_Point],di

;Program Programmable Interrupt Controllers:
;Source:Nanos
;IRQ 0-15 = Int 0x20-0x2F
;ICW1 (Initialize)
mov al,0x15
out 0x20,al
out 0xA0,al
;ICW2 (Vector offset)
mov al,0x20
out 0x21,al
add al,8
out 0xA1,al
;ICW3
mov al,4
out 0x21,al
mov al,2
out 0xA1,al
;ICW4
mov al,0x01
out 0x21,al
out 0xA1,al
;Enable IRQs at PICs (Keyboard)
mov al,11111101b
out 0x21,al
mov al,11111111b
out 0xA1,al

lidt[Reference_IDT]
sti

hlt

 jmp $



 Clear_screen:

xor edi,edi
.Loop_Clear_screen
mov dword [gs:edi],0x07000700
add edi,4
cmp edi,8000
jb .Loop_Clear_screen

 ret


 Write_string:
;Edits dl,esi,edi

;Get cursor location... or not!
;Initial write location parameter stored in DI
;Initial read location parameter stored in SI

mov byte dl,[ds:esi]
or dl,dl
jz .Exit_Write_string
mov byte [gs:edi],dl
inc esi
add edi,2
jmp Write_string
.Exit_Write_string

 ret



Hello_World db 'Protected mode successful. ',0



;Interrupt Descriptor Table
;Gate structure:
;16 Offset
;16 Selector
;8 cleared
;1 Present (1)
;2 Privilege (ring)
;1 cleared
;4 Gate type
;  Interrupt: 0xE
;  Task: 0x5
;  Trap: 0xF
;16 Offset

;Exceptions:
;Source:Nanos
;0 Divide Error
;1 Debug Exception
;2 NMI  Interrupt
;3 Breakpoint
;4 INTO - overflow
;5 BOUND Range exceeded
;6 Invalid opcode
;7 Device not available
;8 Double Fault
;9 Co-processor segment overrun
;A Invalid TSS
;B Segment Not Present
;C Stack Fault
;D General Protection Fault
;E Page Fault
;F
;10  Floating Point Error
;11  Alignment Check
;12-1F Reserved

;Source:Wikipedia.org
;IRQ 0 - System timer. Reserved for the system. Cannot be changed by a user.
;IRQ 1 - Keyboard. Reserved for the system. Cannot be altered even if no keyboard is present or needed.
;IRQ 2 - Second IRQ controller. See below for explanation.
;IRQ 3 - COM 2(Default) COM 4(User)
;IRQ 4 - COM 1(Default) COM 3(User)
;IRQ 5 - Sound card (Sound Blaster Pro or later) or LPT2(User)
;IRQ 6 - Floppy disk controller
;IRQ 7 - LPT1(Parallel port) or sound card (8-bit Sound Blaster and compatibles)
;IRQ 8 - Real time clock
;IRQ 9 - ACPI SCI or ISA MPU-401
;IRQ 10 - Free / Open interrupt / Available / SCSI
;IRQ 11 - Free / Open interrupt / Available / SCSI
;IRQ 12 - PS/2 connector Mouse / If no PS/2 connector mouse is used, this can be used for other peripherals
;IRQ 13 - Math co-processor. Cannot be changed
;IRQ 14 - Primary IDE. If no Primary IDE this can be changed
;IRQ 15 - Secondary IDE

 Reference_IDT:
dw End_IDT - IDT - 1
dd IDT
 IDT:
;Exceptions, not supported
dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000

dd 0x00000000
dd 0x00000000
;not supported
 Timer_IDT equ $ - IDT
dd 0x00000000
dd 0x00000000
;supported soon
 Keyboard_IDT equ $ - IDT
dw Interrupt.IRQ1
dw Code_GDT
dw 0x8E00
dw 0x0000
 End_IDT:



;Interrupt Service Routines:
 Interrupt.IRQ1
pusha

xor eax,eax

;get keycode
 read_kbd:
in al,0x64
and al,0x01
jz read_kbd
in al,0x60
call Scancode_To_ASCII

;send EOI to PIC
mov al,0x20
out 0x20,al
popa
 iret



 Display_Keypress:
xor ebx,ebx
mov word bx,[ds:Insertion_Point]
mov byte [gs:ebx],dl
add bx,2
call Move_Insertion_Point
 ret



 Scancode_To_ASCII:
;Uses ASCII db
cmp al,0x39
ja Above_Scancode_To_ASCII
add eax,ASCII
mov byte dl,[ds:eax]
call Display_Keypress
jmp End_Scancode_To_ASCII
Above_Scancode_To_ASCII:
call Virtual_Mouse
 End_Scancode_To_ASCII:
 ret



 Virtual_Mouse:
xor ebx,ebx
mov word bx,[ds:Insertion_Point]

cmp al,0x48
je Up_Virtual_Mouse
cmp al,0x4C
je Down_Virtual_Mouse
cmp al,0x50
je Down_Virtual_Mouse
cmp al,0x4B
je Left_Virtual_Mouse
cmp al,0x4D
je Right_Virtual_Mouse

jmp End_Virtual_Mouse

 Up_Virtual_Mouse:
cmp bx,160
jb End_Virtual_Mouse
sub bx,160
call Move_Insertion_Point
jmp End_Virtual_Mouse

 Down_Virtual_Mouse:
cmp bx,7840
jae End_Virtual_Mouse
add bx,160
call Move_Insertion_Point
jmp End_Virtual_Mouse

 Left_Virtual_Mouse:
cmp bx,0
je End_Virtual_Mouse
sub bx,2
call Move_Insertion_Point
jmp End_Virtual_Mouse

 Right_Virtual_Mouse:
cmp bx,7998
je End_Virtual_Mouse
add bx,2
call Move_Insertion_Point

 End_Virtual_Mouse
 ret



 Move_Insertion_Point:
;bx = new location
xor edi,edi
mov word di,[ds:Insertion_Point]
inc di
mov byte dl,[gs:edi]
xor dl,0xFF
mov byte [gs:edi],dl

mov word [ds:Insertion_Point],bx
inc bx
mov byte dl,[gs:ebx]
xor dl,0xFF
mov byte [gs:ebx],dl

 ret



Insertion_Point dw 0x0000
ASCII db 0,27,49,50,51,52,53,54,55,56,57,48,45,61,8,9,81,87,69,82,84,89,85,73,79,80,91,93,10,0,65,83,68,70,71,72,74,75,76,59,39,96,0,92,90,88,67,86,66,78,77,44,46,47,0,42,0,32



;Fix floppy image size
times 1474560-($-$$) db 0