I think I'm doing ok...
But it doesn't work well....
I have two files. First file is boot_loader.. make PMode and IDTs
and Second File is my kernel... It's very simple code...
and I'm using Vmware... Because I'm studying in my lap top computer..
First time I just boot my Vmware with just boot_loader...
And I works very well.... until jmp $
but if I just make an Image file with boot_loader.o and kernel.o files, I has some fault... Vmware said it's stack fault...
I don't know what is wrong... um....
I'll attach my code here...
Code: Select all
; segmentselector.inc
SysCodeSelector equ 0x08
SysDataSelector equ 0x10
VideoSelector equ 0x18
Code: Select all
; boot_loader.asm
%include "segmentselector.inc"
;************************ real mode **************************
;************************ 16 bit mode ************************
[ORG 0] ; Origin location
[bits 16]
jmp 0x07C0:main
;---------------------- Main Program ----------------------;
main: ; Label for the start of the main program
mov ax,cs ; Location of data is DS:Offset
mov ds,ax ; This can not be loaded directly it has to be in two steps.
; 'mov ds, 0x0000' will NOT work due to limitations on the CPU
mov es,ax
mov si, NextLine
call PutStr
mov si, BootLoader ; Load the string into position for the procedure.
call PutStr ; Call/start the procedure
call _floppy_reset
call _floppy_load_kernel
; make the floppy driver stop
mov dx, 0x3F2
xor al, al
out dx, al
mov si, StartKernel ; Load the string into position for the procedure.
call PutStr ; Call/start the procedure
; icw1
mov al, 0x11 ; initialize pic
out 0x20, al ; master pic
dw 0x00eb, 0x00eb ; jmp $+2, jmp $+2
out 0xA0, al ; slave pic
dw 0x00eb, 0x00eb
; icw2
mov al, 0x20
out 0x21, al
dw 0x00eb, 0x00eb
mov al, 0x28
out 0xA1, al
dw 0x00eb, 0x00eb
; icw3
mov al, 0x04
out 0x21, al
dw 0x00eb, 0x00eb
mov al, 0x02
out 0xA1, al
dw 0x00eb, 0x00eb
; icw4
mov al, 0x01 ; use 8086 mode
out 0x21, al
dw 0x00eb, 0x00eb
out 0xA1, al
dw 0x00eb, 0x00eb
;disable all interrupts
mov al, 0xFF
out 0xA1, al
dw 0x00eb, 0x00eb
mov al, 0xFB
out 0x21, al
;setup gdt
lgdt[gdtr]
mov eax, cr0
or eax, 0x00000001
mov cr0, eax
jmp $+2
nop
nop
mov bx, SysDataSelector
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx
jmp $ ; [b]I just stop the everything here[/b]
jmp dword SysCodeSelector:0x10000 ; JUMP TO KERNEL
;---------------------- Procedures ----------------------;
PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0x0E ; The function to display a chacter (teletype)
mov bh,0x00 ; Page number
mov bl,0x07 ; Normal text attribute
.nextchar ; Internal label (needed to loop round for the next character)
lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
; Loads [SI] into AL and increases SI by one
; Check for end of string '0'
or al,al ; Sets the zero flag if al = 0
; (OR outputs 0's where there is a zero bit in the register)
jz .return ; If the zero flag has been set go to the end of the procedure.
; Zero flag gets set when an instruction returns 0 as the answer.
int 0x10 ; Run the BIOS video interrupt
jmp .nextchar ; Loop back round tothe top
.return ; Label at the end to jump to when complete
ret ; Return to main program
global _floppy_reset
_floppy_reset: ; Reset the floppy drive
mov ax,0 ;
mov dl,0 ; Drive=0 (=A)
int 13h ;
jc _floppy_error ; ERROR => reset again
ret
;end _floppy_reset
global _floppy_error
_floppy_error:
mov si, Error
call PutStr
hlt
ret
global _floppy_load_kernel
_floppy_load_kernel:
push es
_floppy_load_kernel_loop:
mov ax,1000h ; ES:BX = 1000h:0000h
mov es,ax ;
mov bx,0 ;
mov ah,2 ; Load disk data to ES:BX
mov al,8 ; Load 8 sectors
mov ch,0 ; Cylinder=0
mov cl,2 ; Sector=2
mov dh,0 ; Head=0
mov dl,0 ; Drive=0
int 13h ; Read!
jc _floppy_load_kernel_loop ; ERROR => Try again
pop es
ret
;end _floppy_load_kernel
;-------------- Data Section -----------------------;
;gdt data
gdtr:
dw gdt_end - gdt -1
dd gdt+0x10000
gdt:
dd 0, 0 ; Null Descriptor
dd 0x0000FFFF, 0x00CF9A01 ; Kernel Code Descriptor
; base addr = 0x10000, limit = 0xFFFFF
; DPL = 0(kernel), G = 1(4KB), D = 1(32bit), code,
; readable, non-conforming
dd 0x0000FFFF, 0x00CF9201 ; Kernel Data Descriptor
; base addr = 0x10000, limit = 0xFFFFF
; DPL = 0(kernel), G = 1(4KB), D = 1(32bit), data,
; writable, expand-up
dd 0x8000FFFF, 0x0040920B ; Video Memory Selector
; base addr = 0xB8000, limit = 0xFFFF
; DPL = 0(kernel), G = 0(byte), D = 1(32bit), data,
; writable, expand-up
gdt_end:
NextLine db 13,10,0
BootLoader db 'Boot Loader',13,10,0
StartKernel db 'Start Kernel',13,10,0
Error db 'Error',13,10,0
; End Matter
times 510-($-$$) db 0 ; Fill the rest with zeros
dw 0xAA55 ; Boot loader signature
Code: Select all
;kernel.asm
%include "segmentselector.inc"
;**************** Protected Mode from here ******************
;********************* 32 bits mode *************************
;---------------- Start Protected Mode ------------------;
[org 0x10000]
[bits 32]
PM_Start:
mov bx, SysDataSelector ; identify all selector with SysDataSelector
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx
lea esp, [PM_Start]
mov edi, 2*5 * 80*2*0 ; set position to (5, 0)
lea esi, [msgOS]
call PM_printf
mov edi, 2*30 + 80*2*0 ; set position to (30, 0)
lea esi, [PMode]
call PM_printf
;setup 256 idt(s)
cld
mov ax, SysDataSelector
mov es, ax
xor eax, eax
xor ecx, ecx
mov ax, 256
mov edi, 0
;call _test
;mov edi, 2*0 + 80*2*5
;lea esi, [msg_test]
;call PM_printf
loop_idt:
; initialize all interrupts (make ignored)
lea esi, [idt_ignore]
mov cx, 8
rep movsb
dec ax
jnz loop_idt
; register timer interrupt 0x20
mov edi, 8*0x20
lea esi, [idt_timer]
mov cx, 8
rep movsb
; register keyboard interrupt 0x21
mov edi, 8*0x21
lea esi, [idt_keyboard]
mov cx, 8
rep movsb
lidt[idtr]
; enable bit0 and bit1 -> 0xFC
; bit0 = timer interrupt, bit1 = keyboard interrupt
mov al, 0xFC
out 0x21, al
sti
jmp $
;---------------------- Procedures ----------------------;
global _test
_test:
push eax
push es
push ds
push edi
push esi
mov ax, SysDataSelector
mov ds, ax
xor eax, eax
mov edi, 2*0 + 80*2*6 ; set position to (0, 6)
lea esi, [msg_test]
call PM_printf
pop esi
pop edi
pop ds
pop es
pop eax
ret
; PM_printf - Print Characters on the video memory
; write characters from esi to es:edi
; pre - edi = position to write( 2*x + 80*2*y ), esi = phy addr of characters
PM_printf:
push eax ; use eax register
push es
mov ax, VideoSelector
mov es, ax
.printf_loop:
mov al, byte[esi] ; move byte from esi to al
mov byte[es:edi],al ; move byte from al to video memory
inc edi ; increase edi( to position of color )
mov byte[es:edi],0x06 ; write foreground color
inc esi ; increase esi( character pointer )
inc edi ; increase edi( to position of next character )
or al, al ; check if al is 0
jz .printf_end ; if al is 0, jump to .printf_end
jmp .printf_loop
.printf_end:
pop es
pop eax ; restore eax register
ret ; return to next line of caller
;------------------------ Data Section --------------------;
;idt data
idtr:
dw 256*8-1 ; the limit of IDT
dd 0 ; base address of IDT
;Character Data
msg_test db "This is message for test", 0
msgOS db "PYS Operating System", 0
PMode db "Protected Mode Start", 0
msg_isr_ignore db "This is an ignorable interrupt", 0
msg_isr_32_timer db ".This is the timer interrupt", 0
msg_isr_33_keyboard db ".This is the keyboard interrupt", 0
;------------------------- ISR Section ---------------------;
isr_ignore:
push gs
push fs
push es
push ds
pushad
pushfd
mov al, 0x20
out 0x20, al
mov ax, VideoSelector
mov es, ax
mov edi, 2*0 + 80*2*4 ; set position to (30, 0)
lea esi, [msg_isr_ignore]
call PM_printf
popfd
popad
pop ds
pop es
pop fs
pop gs
iret
isr_32_timer:
push gs
push fs
push es
push ds
pushad
pushfd
mov al, 0x20
out 0x20, al
mov edi, 2*0 + 80*2*5 ; set position to (30, 0)
lea esi, [msg_isr_32_timer]
call PM_printf
inc byte [msg_isr_32_timer]
popfd
popad
pop ds
pop es
pop fs
pop gs
iret
isr_33_keyboard:
pushad
push gs
push fs
push es
push ds
pushfd
in al, 0x60
mov al, 0x20
out 0x20, al
mov edi, 2*0 + 80*2*6 ; set position to (30, 0)
lea esi, [msg_isr_33_keyboard]
call PM_printf
inc byte [msg_isr_33_keyboard]
popfd
pop ds
pop es
pop fs
pop gs
popad
iret
;-------------------- IDT section --------------------;
idt_ignore:
dw isr_ignore
dw 0x08
db 0
db 0x8E
dw 0x0001
idt_timer:
dw isr_32_timer
dw 0x08
db 0
db 0x8E
dw 0x0001
idt_keyboard:
dw isr_33_keyboard
dw 0x08
db 0
db 0x8E
dw 0x0001
times 1024-($-$$) db 0