Daedalus
Joined: 25 Mar 2007
Posts: 52
|
Hey guys,
I'm stuck with this code, and can't figure out why it keeps triplefaultrebooting. It's trying to be a bootloader.
;FAT12 BOOTLOADER
format binary as 'img'
use16
org 0x7c00
;############################## Start of 1st part ##############################
part1:
jmp bootcode ;Jump to bootcode
;The code below is based on the FAT16 definition.
times 3-($-$$) db 0
DB "BosByte"
times 11-($-$$) db 0
DW 512 ;Bytes per sector (do not change!)
DB 1 ;Sectors per Cluster
DW 1 ;Reserved sector count
DB 0x02 ;Num FATs (is ALWAYS 0x02)
DW 512 ;Root entry's count (Should be 512 for FAT16)
DW 2880 ;Sector count (2880 for 1.44 MB floppy)
DB 0xF0 ;Media (0xF0 is common)
DW 9 ;FatSize
DW 18 ;Sectors per Track (used by Interupt)
DW 2 ;Heads count (should be 2 for 1.44 MB floppy)
DD 0 ;Hidden sectors
DD 0 ;Used by FAT32
;Should be at offset 36 now . . .
DB 0x00 ;Drivenum (0 = floppy1)
DB 0 ;Reserved for windows NT, fuck windows!
DB 0x29 ;Indicates that the following three fields are present
DD 12345 ;VolumeID (just random shizzle)
msg1: DB "w00t-OS",0 ;VolumeName (max 11 chars)
times 54-($-$$) db " " ;Fill Volumename up to 11 chars
DB "FAT16" ;FileSysType (max 8 chars)
times 62-($-$$) db " " ;Fill FileSysType up to 8 chars
;End of FAT16 header
times 64-($-$$) db 0
enable_a20_fast:
in al, 0x92
or al, 2
out 0x92, al
.return:
ret
; gdtwriteentry Write GDT entry at es:di
; bx base low (word)
; dx base high (word)
; cx limit low (word)
; ah limit high (nibble) + gran (nibble) 0xLG l=limit g=gran
; al access (byte)
gdtWriteEntry:
mov [es:di], cx ;limit
add di, 2
mov [es:di], bx ;base low
add di, 2
mov [es:di], dl ;base middle
inc di
mov [es:di], al ;access
inc di
mov [es:di], ah ;gran
inc di
mov [es:di], dh;base high
inc di
.return:
ret
; gdt/idtwritepointer Write GDT/IDT POINTER entry at es:di
; bx base low (word)
; dx base high (word)
; cx limit (word)
gdtWritePointer:
idtWritePointer:
mov [es:di], cx ;limit
add di, 2
mov [es:di], bx ;base low
add di, 2
mov [es:di], dx ;base middle
add di, 2
.return:
ret
;putcs (SI string,BL color)
putcs:
cld
.nextchar:
lodsb ;load char @ DS:SI, SI++
or al, al ;check for 0
jz .return ;if 0
call putcc
jmp .nextchar
.return:
ret
;putcc (AL char,BL color)
putcc:
mov ah, 0x0E
mov bh, 0x00
int 0x10
.return:
ret
;puts(SI string)
puts:
mov bl, 0x07
call putcs
.return:
ret
;Now start the bootcode at offset 64:
bootcode:
;Creating stack, disabling interrupts to not be interrupted and triple fault the whole thing.
cli
mov ax, 0x9000
mov ss, ax
mov ax, 0xFFFF
mov sp, ax
sti
;Stack created, enable interrupts again and continue. We can use call and int now.
call loadpart2
jmp part2
;Loadpart2(void)
loadpart2:
mov ah, 0x02
mov al, 3 ;number of sectors to read
mov cl, 2 ;Sector number
mov dl, 0x00 ;Drive number (0=A:, 1=2nd floppy, 80h=drive 0, 81h=drive 1)
mov ch, 0x00
mov dh, 0x00
push 0x0000
pop es
mov bx, part2 ; ES:BX = pointer to buffer
int 0x13 ; int IO (ah = 0x02 means READ) sets CF on error, clears it on succes
jnc .return
mov si,.errormsg
call puts
.error:
jmp .error
.return:
ret
.errormsg:
DB "Error while loading part two!",0
;###writing#bootsignature###### End of 1st part ###this#works!#hurray#########
times 510-($-$$) db 0
dw 0xAA55
;############### Start of 2nd part ####
part2:
;************** STEP 1 - Disable interupts ********
cli
push 0xB800
pop es
mov byte [es:0], 'A'
mov byte [es:1], 0x07
;************ STEP 2 - Setup a GDT & IDT *************
;Create GDT
mov ax, 0x0000
mov es, ax
mov di, 0x1000
push 0xB800
pop es
mov byte [es:0], 'B'
mov byte [es:1], 0x07
;Making a GDT POINTER:
; bx base low (word)
; dx base high (word)
; cx limit (word)
push di
mov bx, 0x1006 ;base low (word)
mov dx, 0 ;base high (word)
mov cx, 5*8-1 ;limit (word) = count(entries) * sizeof(entry) - 1
call gdtWritePointer ;Write GDT POINTER
push 0xB800
pop es
mov byte [es:0], 'C'
mov byte [es:1], 0x07
;Making the GDT itself, first the dummy entry.
xor bx, bx ;base low
xor dx, dx ;base high
xor cx, cx
xor ax, ax
call gdtWriteEntry
push 0xB800
pop es
mov byte [es:0], 'D'
mov byte [es:1], 0x07
mov bx, 0 ;base low (word)
mov dx, 0 ;base high (word)
mov cx, 0xFfFF ;limit low (word)
mov ah, 0x0F + 16*1100b ;limit high (nibble) + gran (nibble)
mov al, 0x9A ;access (byte)
call gdtWriteEntry ;Write CODE segment (covers all memory)
mov bx, 0 ;base low (word)
mov dx, 0 ;base high (word)
mov cx, 0xFFFF ;limit low (word)
mov ah, 0x0F + 16*1100b ;limit high (nibble) + gran (nibble)
mov al, 0x92 ;access (byte)
call gdtWriteEntry ;Write DATA segment (covers all memory)
mov bx, 0x0000 ;base low (word) base = 90000
mov dx, 0x0009 ;base high (word)
mov cx, 0xFFFF ;limit low (word) limit = A0000
mov ah, 0x00 + 16*0100b ;limit high (nibble) + gran (nibble)
mov al, 0x92 ;access (byte)
call gdtWriteEntry ;Write STACK segment (0x9000:0 - 0x9000:0xFFFF)
mov bx, 0x0000 ;base low (word) base = A0000
mov dx, 0x000A ;base high (word)
mov cx, 0xFFFF ;limit low (word) limit = C0000
mov ah, 0x01 + 16*0100b ;limit high (nibble) + gran (nibble)
mov al, 0x92 ;access (byte)
call gdtWriteEntry ;Write VIDEO segment (0xA000:0 - 0xB000:0xFFFF)
;Making a IDT POINTER:
; bx base low (word)
; dx base high (word)
; cx limit (word)
push di
mov bx, di
add bx, 6 ;BX = DX + 6, put the IDT directly after the IDTpointer
mov dx, 0 ;base high (word)
mov cx, 0 ;limit (word) = count(entries) * sizeof(entry) - 1
call idtWritePointer ;Write IDT POINTER
pop di
lidt [es:di] ;Let the CPU know where the IDT (pointer) is
pop di
lgdt [es:di] ;Let the CPU know where the GDT (pointer) is
;****************************** STEP 3 - Enable the A20 ******************************
mov al, 0x0DF
out 0x64, al
;****************************** STEP 4 - Set the first bit of CR0 to 1 ******************************
xor eax, eax
mov eax, cr0
or eax, 1
mov cr0, eax
push 0xB800
pop es
mov byte [es:0], 'E'
mov byte [es:1], 0x07
;****************************** STEP 5 - Load the segment registers with correct values from the GDT ******************************
mov ax, 8*2 ; item 2 in GDT is the DATA segment . . .
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 8*3 ; item 3 in GDT is the STACK segment . . .
mov ss, ax
;****************************** STEP 6 - Load CS and EIP with correct values by doing a far jump ******************************
jmp 0x08:ProtectedMode ;Far jump to protected mode (0x08 referers to item 8 in the GDT, that's the CODE segment)
.inf:
jmp .inf
.crlf:
DB 13,10,0
.msg1:
DB "w00t-OS was succesfully loaded",10,13,10,13,"Entering pmode (32 bit) . . .",10,13,0
.a20errormsg:
db "Unable to enable A20 gate.", 0
ProtectedMode:
;****************************** STEP 7 - You are now in PMode ******************************
.end:
jmp .end
;############################## End of 2nd part ##############################
times (512+3*512)-($-$$) db 0
; \- this number is the size in segments (512 bytes) of the 2nd part
;############################## End of everyting ##############################
It reboots when I try to set the cr0 bit.
Suggestions for the rest of the code are appreciated as well.
Thanks in advance,
|