hey Guys
I have written my own boot loader in nasm but it won't switch into protected mode properly. I am running a x86 emulator called bochs and it gives the following error
CS.d_b = 16 bit
SS.d_b = 16 bit
i think this is the key problem. I would post my code but it makes the message to long so if anyone would be willing to have a look for me let me know and ill send them the code
Protected Mode
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Protected Mode
Oh Okay how stupid do i feel
Code: Select all
; ------------------------------------------------------------------------
; Phoenix OS boot loader (c)2002 Peter Liddle
; ------------------------------------------------------------------------
; This code is the boot loader for the Phoenix OS
; ------------------------------------------------------------------------
[BITS 16] ;Set code generation to 16 bit mode
[ORG 0x0000] ;Tell compiler this si offset 0, it isn;t but will be after jump
jmp BOOT
; -------------------------------------
; Data section
; ------------------------------------------------------------------------
DATA:
BootDrv db 0x80
BootMsg db 'Booting Phoenix OS', 0x0D, 0x0A, 0
PModeMsg db 'Jumping to Protected Mode', 0x0D, 0x0A, 0
PModeEnabledMsg db 'Where in Protected Mode at Last', 0x0D, 0x0A, 0
EnablA20Msg db 'Enabling A20 Line', 0x0D, 0x0A, 0
A20EnabledMsg db 'A20 Line is Now Turned On', 0x0D, 0x0A, 0
IDTptr DW 7FFh ;LIMIT 256 IDT Slots
DD 0000h ;BASE (Linear)
GDTptr DW 17FFh ;LIMIT 768 slots
DD 0800h ;BASE (Linear)
; ------------------------------------------
; Functions section
; ------------------------------------------------------------------------
.386
RESETDISK: ; Reset drive
mov ax, 0 ;
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Actually Reset
jc RESETDISK ; ERROR => reset again
ret
READ:
mov ax, 0x1000 ; ES:BX = 0x1000:0000
mov es, ax ;
mov bx, 0 ;
call RESETDISK ; First Reset Disk
mov ah, 0x2 ; Load disk data to ES:BX
mov al, 0x1 ; Load 1 sectors
mov ch, 0x0 ; Track=1
mov cl, 0x2 ; Sector=2
mov dh, 0x00 ; Head=0
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Read!
jc READ ; ERROR => Try again
ret
PRINTMSG: ; Dump ds:si to screen.
lodsb ; load byte at ds:si into al
or al,al ; test if character is 0 (end)
jz done
mov ah,0eh ; put character
mov bx,0007 ; attribute
int 0x10 ; call BIOS
jmp PRINTMSG
done:
ret
CLEARBUF:
XOR CX,CX
in al, 64h ; get input from keyboard status port
test al, 02h ; test the buffer full flag
loopnz CLEARBUF ; loop until buffer is empty
ret
; ------------------------------------------------------------------------
; ------------------------------------------
; Boot Code
; ------------------------------------------------------------------------
BOOT:
;mov [BootDrv],dl ; Save Boot Drive
;Set up Location of Data Segment
mov ax,0x7C0
mov ds,ax
cli ; Turn Off interrupts while we setup a stack and A20 and Get to P-Mode
;Set Up Stack
mov ax,0x9000 ; this seems to be the typical place for a stack
mov ss,ax
mov sp,0xFFFF ; let's use the whole segment. Why not? We can :)
mov si,BootMsg ; display our startup message
call PRINTMSG
;call READ ; Load in a sector
;Enable A20 Address Line
mov si,EnablA20Msg ; display our startup message
call PRINTMSG
;Turn on A20 Line
call CLEARBUF ; Wait till keyboard Buffer is empty
mov al, 0D1h ; keyboard: write to output port
out 64h, al ; output command to keyboard
call CLEARBUF ; Wait till keyboard Buffer is empty again
mov al, 0x0DF ; keyboard: set A20
out 0x60, al ; send it to the keyboard controller
mov cx, 0x14
call CLEARBUF ; Wait 25 sec for A20 to be enabled
nop
nop
mov si,A20EnabledMsg ; display our startup message
call PRINTMSG
;Lets Get Into P-Mode
mov si, PModeMsg
call PRINTMSG
; Set Global Descriptor Table here, this must be done PRIOR to Prot Mode
LIDT [IDTptr]
LGDT [GDTptr]
mov eax, CR0 ; load the control register in
or eax, 1 ; set bit 1: pmode bit
mov CR0, EAX ; copy it back to the control register
jmp $+2 ; and clear the prefetch queue
nop
nop
db 066h, 0EAh
dw prot, 06h
dw 08h
[BITS 32]
prot:
; Set up segments
mov ebx, 10h
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov si, PModeEnabledMsg
call PRINTMSG
MOV BX, 10h
MOV DS,BX
MOV ES,BX
MOV FS,BX
MOV GS,BX
MOV SS,BX
;jmp 0x1000:0000
times 510-($-$$) db 0
dw 0xAA55
Re:Protected Mode
1. the is no gdt table
2. I suggest you do a far jump instead of jmp $+2,
jmp code:place (code is a segment specified in the gdt)
3. int 10h does not work in pmode, especially not if you don't do sti
(and put it in the idtr)
2. I suggest you do a far jump instead of jmp $+2,
jmp code:place (code is a segment specified in the gdt)
3. int 10h does not work in pmode, especially not if you don't do sti
(and put it in the idtr)
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Protected Mode
sti-ing will not enable int10h (neither in pmode nor in realmode !) cli/sti only affect IRQs receipt by the processor, but in no way does it have an effect on INT xx command...
And even if it did, the 16bits BIOS code is unlikely to work from pmode
And even if it did, the 16bits BIOS code is unlikely to work from pmode
Re:Protected Mode
jmp dword LINEAR_CODE_SEL:PMODECODE
A couple of notes though. This style of referencing the GDT is clever (tricky, whatever), but is not very informative for the beginner IMO. It is being copied over and over on this forum, but I suspect that it is rarely understood what the selector value means or why using the offset this way works. I hope I'm wrong.
You will need to actually put some code in the PMODECODE. But don't be shocked when you can't refer to any offsets. Since you opted for ORG 0x0, your offsets are relative to the value in DS (ie. 0x07c0). This will be meaningless once you make the switch to pmode.
You won't be able to see anything on the screen unless you write (or steal) some video code. So you probably won't know where it is working or not (except perhaps by not resetting the machine).
A couple of notes though. This style of referencing the GDT is clever (tricky, whatever), but is not very informative for the beginner IMO. It is being copied over and over on this forum, but I suspect that it is rarely understood what the selector value means or why using the offset this way works. I hope I'm wrong.
You will need to actually put some code in the PMODECODE. But don't be shocked when you can't refer to any offsets. Since you opted for ORG 0x0, your offsets are relative to the value in DS (ie. 0x07c0). This will be meaningless once you make the switch to pmode.
You won't be able to see anything on the screen unless you write (or steal) some video code. So you probably won't know where it is working or not (except perhaps by not resetting the machine).