Page 1 of 1

PMODE ERROR

Posted: Sun Dec 05, 2004 12:00 am
by Ty
I'm having great difficulty getting into protected mode. Every time my loader sets the lsb of cr0 to 1, my computer reboots. I'v searched the net, but came up with nothing. Sorry if this is a dumb question. (Maybe I sould just read all the IA32 manuals...) Here is my code:

Code: Select all


enable_A20:

mov ax, 0x2401		; bios enable a20 line
int 0x15
jnc enter_pmode		; if no error, go to pmode

mov si, A20_error	                ; Otherwise, error msg
call print

enter_pmode:

cli			; dissable interrupts
lgdt [gdtr]		                ; load gtdr
mov eax, cr0		; edit cr0
or al, 0x01		                ; lsb sets pmode
mov cr0, eax		; and set pmode bit

init:			; initialize selectors

mov ax, 0x10		; second descriptor
mov ds, ax

gdt:			; 64 bit segment descriptors

dw	0x0		; null descriptor
dw	0x0
dw	0x0
dw	0x0

dw	0xffff		; code descriptor
dw	0x0000
dw	0x9a00
dw	0x00cf

dw	0xffff		; data descriptor
dw	0x0000
dw	0x9200
dw	0x00cf

gdt_end:		                ; used for calculation of limit

gdtr:			; base and limit of gdt

dw	gdt_end-gdt-1	; gdt limit
dd 	gdt		; gdt base address


Thanks,

Ty

Re: PMODE ERROR

Posted: Sun Dec 05, 2004 12:00 am
by Ty
I just entered [BITS 32] after setting the cr0 bit to 1, and it doesn't reboot, the floppy drive just keeps running. Is this just a fluke coincidence, or am I doing something wrong. Also, I noticed that, when setting the limit address when creating the segment descriptors to the "full 4GB," you do a

Code: Select all

dw 0xFFFF
Yet, I thought that it should be 32 bit, ie. "0xFFFFFFFF"..not 16 bit, ie. "0xFFFF"


I very confused.

Re: PMODE ERROR

Posted: Sun Dec 05, 2004 12:00 am
by Ty
I narrowed the error down to removing these lines:

Code: Select all

mov ax, 0x10
mov ds, ax
I doesn't reboot if I remove these lines, just hangs like it's supposed to.

Re: PMODE ERROR

Posted: Mon Dec 06, 2004 12:00 am
by gaf
Hello,
make sure that the address in 'gdtr' is physical and not linear. Since your kernel's offset is probably not zero you have to calculate it at run-time:

Code: Select all

mov bx, cs
shl ebx, 16
lea eax, [ebx+gdt]
mov [gdtr+2], eax
The same problem might occure when you execute the jump to pmode. While it is possible to calculate the pmode entrypoint's address at run-time too, it's quite ugly and makes thing harder than necessary.
Could you please post the offset of your kernel (ORG) and the address your bootloader loads the kernel to ?
Yet, I thought that it should be 32 bit, ie. "0xFFFFFFFF"..not 16 bit, ie. "0xFFFF"
Actually it's 0xFFFFF - The last F is hidden in the attributes as 0xCF. This is the size of your segment in 4k pages (0xFFFFF * 0xFFF = 0xFFFFFFFF).

regards,
gaf

Re: PMODE ERROR

Posted: Mon Dec 06, 2004 12:00 am
by Ty
gaf wrote: While it is possible to calculate the pmode entrypoint's address at run-time too, it's quite ugly and makes thing harder than necessary.
Are you talking about this:

Code: Select all

gdtr:			; base and limit of gdt

dw	gdt_end-gdt-1	; gdt limit
dd 	gdt		; gdt base address
Could I just then use something like this for the gdt limit:

Code: Select all

limit:
dw (3*4)-1                                  ;(3 descripters*4 words)-1
gaf wrote: Could you please post the offset of your kernel (ORG) and the address your bootloader loads the kernel to ?
I don't have a kernel yet! Sorry. I have only been able to get into pmode. What seems to be happening is that when I remove the lines after setting the cr0 bit, ie:

Code: Select all

mov ax, 0x10
mov ds, ax
My os doesn't reboot. It just hangs at my "jmp $"
Yet, when I add that line back in, It reboots.

Thanks.

Ty

Re: PMODE ERROR

Posted: Tue Dec 07, 2004 12:00 am
by gaf
I don't have a kernel yet! Sorry. I have only been able to get into pmode. What seems to be happening is that when I remove the lines after setting the cr0 bit, ie:

mov ax, 0x10
mov ds, ax

My os doesn't reboot. It just hangs at my "jmp $"
Yet, when I add that line back in, It reboots.
So it's a bootsector ?
In that case your code should be loaded to 0x7c00 by the BIOS.

First make sure that your bootsector is linked correctly:

Code: Select all

(first line in your file)
org 0x7C00
bits 16

enable_A20:
...
Also remember that there has to be a magic number at the end of your bootsector.

Code: Select all

(last line of code/data)

times 510-($-$$) db 0
dw 0xAA55
The first line will fill the remaining sector (except the very last 2 bytes) with zeroes. These 2 bytes will then be used for the signature in the second line.
$ = current address (orgin + offset, for example 0x7c00+enable_A20)
$$ = origin of the file (org directive, 0x7c00)
Are you talking about this:
...
Could I just then use something like this for the gdt limit:
limit:
dw (3*4)-1 ;(3 descripters*4 words)-1
No - I was actually talking about the 'gdt base address'. The limit is a relative value, so even if your offset is wrong there shouldn't be any problems.

The labels in NASM consist of (code origin)+(offset in the code). The origin is set using the org-directive:

Code: Select all

org 0x7c00

label1:
; label1 = origin + offset1 -> 0x7c00 + 0
<lots of code1>

label2:
; label2 = origin + offset2 -> 0x7c00 + sizeof(lots of code1)
<lots of code2>

label3:
; label3 = origin + offset3 -> 0x7c00 + sizeof(lots of code1+2)
<lots of code3>

data1 dd label3-label1
; data1 = (origin + offset3) - (origin + offset1) = offset3 - offset1
Anyway, since you have a bootsector rather than a kernel the 'gdt base address' isn't a problem either (just leave it as is).
The reason your code wouldn't work in a kernel is that it must be executed within the first 64k of memory and most/all kernels are loaded beyond the 1MB mark. If it is executed at a higher address, the (real-mode) code-segment can't be zero and you have to colculate the physical address at run-time as I've showed you.
Yet, when I add that line back in, It reboots.
Outcommenting this line won't really help because you aren't in pmode before you've reloaded all segment registers. And don't forget to set up the stack:

Code: Select all

mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax

mov esp, 0x200000 ; 2MB
Now everything is ready to jump to pmode...

Code: Select all

jmp dword 0x08:pmode

bits 32
pmode:
jmp $
regards,
gaf

Re: PMODE ERROR

Posted: Tue Dec 07, 2004 12:00 am
by Ty
Thanks gaf! It works now. That's awesome...

Ty