flat assembler
Message board for the users of flat assembler.

Index > OS Construction > A20/Pmode fun

Author
Thread Post new topic Reply to topic
Daedalus



Joined: 25 Mar 2007
Posts: 52
Daedalus 08 Mar 2008, 21:34
Hey guys,

I'm stuck with this code, and can't figure out why it keeps triplefaultrebooting. It's trying to be a bootloader.

Code:
;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,
Post 08 Mar 2008, 21:34
View user's profile Send private message MSN Messenger Reply with quote
Daedalus



Joined: 25 Mar 2007
Posts: 52
Daedalus 08 Mar 2008, 22:50
I removed the IDT section. It doesn't create an IDT know, didn't think it was necessary, so I'm cutting all the unnecessary code.
Post 08 Mar 2008, 22:50
View user's profile Send private message MSN Messenger Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4353
Location: Now
edfed 08 Mar 2008, 23:24
you can use the FBBOOT package as a good basis.
it was originally coded by dex, and i added some tricks to make it more usefull... keyboard, items, etc... free and modular.

you erase all you don't need, and verify what is needed to works, untill it bugs.
Post 08 Mar 2008, 23:24
View user's profile Send private message Visit poster's website Reply with quote
Goplat



Joined: 15 Sep 2006
Posts: 181
Goplat 09 Mar 2008, 03:35
One thing that catches my eye: Your GDT functions use ES, but you keep changing ES to point to video memory.
Post 09 Mar 2008, 03:35
View user's profile Send private message Reply with quote
Daedalus



Joined: 25 Mar 2007
Posts: 52
Daedalus 09 Mar 2008, 10:07
That ES thing caught my eye too, I'm now busy with defining the GDT inside the program itself as a bunch of dw and dbs. Hopefully that works.. At least it makes things easier to debug since it's less code.
Post 09 Mar 2008, 10:07
View user's profile Send private message MSN Messenger Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4353
Location: Now
edfed 09 Mar 2008, 10:11
in pmode, the video, and all memory, is not accessible like in real mode.

the segment for screen will not be 0b800h, but a descriptor with base = 0b8000h, you should play with segments during pm switch.
if you need to display things during the switch, prepare your segment in advance, and then, it is ok. but the switch itself shall be the shorter possible.
you can really improve your code if you read some examples like fab, fbboot or fbrowser. there are all the steps you need, but it works ...
Post 09 Mar 2008, 10:11
View user's profile Send private message Visit poster's website Reply with quote
Daedalus



Joined: 25 Mar 2007
Posts: 52
Daedalus 09 Mar 2008, 10:14
Ah ofc, when I switch into pmode I can't output to the screen no more... Forgot about that. I'll take a look into FBBOOT, thanks.
Post 09 Mar 2008, 10:14
View user's profile Send private message MSN Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.