User:Mr.Confuzed
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