Discussion:
Entering Protected Mode
(too old to reply)
Rick C. Hodgin
2019-06-19 15:25:20 UTC
Permalink
In my custom OS kernel, I use this code to enter protected mode:

cli ; Clear interrupts
mov eax,cr0
or al,1
mov cr0,eax
;; Ok, we're in protected mode, still 16-bit code segment though
jmp $+2 ; Clear the cache
lidt fword ptr IDT_ptr ; Load IDT
lgdt fword ptr GDT_ptr ; Load GDT
xor ax,ax
lldt ax ; Load LDT with NULL
mov ax,_sTSS ; Load TR
ltr ax
; Data segment registers
mov ax,_sDATA
mov ds,ax
mov es,ax
; Extra segment registers
mov ax,_sVGA
mov fs,ax
mov ax,_sMONO
mov gs,ax
; Stack
mov ax,_sSTACK
mov ss,ax
mov esp,_sSTACK_limit - 4
sti

After this I push the new target address on the stack and issue
a RETF to go there.

On the line above after the ";; Ok, we're in protected mode..."
I issue a JMP $+2. I remember when writing this code that it was
a requirement to clear the cache.

-----
My question today is ... why does that need to be done? Is it
only because the pre-decoded instructions are operating in the
legacy sense of the prior real-mode decoding engine? And now
they need to be re-decoded using the protected-mode decoding
scheme?

And if so, would it be possible to put enough NOP instructions
after the MOV CR0,EAX instruction where it enters protected mode
to cause the CPU to never need a JMP instruction to clear the
cache because the NOPs would simply flood-fill it and it would
automatically decode future cache line reads using the new mode?

I don't see any practical use for this knowledge, but I'm more
curious than anything.
--
Rick C. Hodgin
wolfgang kern
2019-07-01 04:30:08 UTC
Permalink
Post by Rick C. Hodgin
cli ; Clear interrupts
mov eax,cr0
or al,1
mov cr0,eax
;; Ok, we're in protected mode, still 16-bit code segment though
Not at all!
it will remain in true real mode until change of CS [JMPF/RETF/IRET]
Post by Rick C. Hodgin
jmp $+2 ; Clear the cache
^redundant^
Post by Rick C. Hodgin
lidt fword ptr IDT_ptr ; Load IDT
lgdt fword ptr GDT_ptr ; Load GDT
f..kword? I use 16:32 loads for both above
and I have LGDT run once during boot and LIDT in front of the CR0 change
to allow other mode switches use the same code.
Post by Rick C. Hodgin
xor ax,ax
lldt ax ; Load LDT with NULL
I don't care LDT because never used
Post by Rick C. Hodgin
mov ax,_sTSS ; Load TR
ltr ax
; Data segment registers
mov ax,_sDATA
mov ds,ax
mov es,ax
; Extra segment registers
mov ax,_sVGA
mov fs,ax
mov ax,_sMONO
mov gs,ax
; Stack
mov ax,_sSTACK
mov ss,ax
mov esp,_sSTACK_limit - 4
sti
my setting: ds=es=fs=gs=4GB FLAT, ss=64K
Post by Rick C. Hodgin
After this I push the new target address on the stack and issue
a RETF to go there.
I do a JMP far imm 16:32 right after MOV CRo,eax.
__
wolfgang
Rick C. Hodgin
2019-07-01 12:11:01 UTC
Permalink
Post by Rick C. Hodgin
lidt fword ptr IDT_ptr ; Load IDT
lgdt fword ptr GDT_ptr ; Load GDT
[fword?]?
FAR WORD (a 16:32 pointer):

Search for "fword ptr":
http://bytepointer.com/masm/ml51_readme.htm
--
Rick C. Hodgin
r***@nospicedham.gmail.com
2019-07-03 07:07:32 UTC
Permalink
Hi,
Post by Rick C. Hodgin
On the line above after the ";; Ok, we're in protected mode..."
I issue a JMP $+2. I remember when writing this code that it was
a requirement to clear the cache.
I know nothing of pmode. I've never coded anything in it directly.
Post by Rick C. Hodgin
My question today is ... why does that need to be done?
I don't see any practical use for this knowledge, but I'm more
curious than anything.
FreeDOS HIMEMX 3.32 had a bug where it wouldn't work on some old
386 laptops that two people still sometimes used (at the time).
IIRC, the unofficial fix (3.33, albeit without official maintainer)
was to add "jmp $+2". But it wasn't needed in newer cpus, apparently.

Is that what you meant?
Rick C. Hodgin
2019-07-03 12:12:46 UTC
Permalink
Post by r***@nospicedham.gmail.com
Hi,
Post by Rick C. Hodgin
On the line above after the ";; Ok, we're in protected mode..."
I issue a JMP $+2. I remember when writing this code that it was
a requirement to clear the cache.
I know nothing of pmode. I've never coded anything in it directly.
Post by Rick C. Hodgin
My question today is ... why does that need to be done?
I don't see any practical use for this knowledge, but I'm more
curious than anything.
FreeDOS HIMEMX 3.32 had a bug where it wouldn't work on some old
386 laptops that two people still sometimes used (at the time).
IIRC, the unofficial fix (3.33, albeit without official maintainer)
was to add "jmp $+2". But it wasn't needed in newer cpus, apparently.
Is that what you meant?
Possibly. My kernel was initially written in the mid-90s, and I would
have had books and resources from the late 80s I drew from to design it.

It's very likely I assembled code samples from those various sources
and added bits here and there until I got it to work, as creating my
kernel was a trial-and-error format making baby steps as I went. I
would get to a certain point and put a particular character in the
upper-left of the screen to know it made it there. Later I created
my real-mode debugger and could single-step through even the initial
boot sector code, which was awesome.

Until then I did a lot of this:

mov ax,0b800h
mov es,ax
mov word ptr es:[di],0072eh ; Display a dot
@@:
hlt
jmp @B

That kind of thing. :-)
--
Rick C. Hodgin
wolfgang kern
2019-07-04 07:10:57 UTC
Permalink
On 03.07.2019 14:12, Rick C. Hodgin wrote:

...
    mov     ax,0b800h
    mov     es,ax
    mov     word ptr es:[di],0072eh   ; Display a dot
    hlt
That kind of thing. :-)
this tell that it's still in realmode with text-mode 03.

for PM32 check:
;assume DS flat 4G

C7 05 00 80 0B 00 50 70 mov word [0x000b8000],0x7050 ;"P"
__
wolfgang
Rick C. Hodgin
2019-07-05 16:56:23 UTC
Permalink
Post by wolfgang kern
...
     mov     ax,0b800h
     mov     es,ax
     mov     word ptr es:[di],0072eh   ; Display a dot
     hlt
That kind of thing. :-)
this tell that it's still in realmode with text-mode 03.
;assume DS flat 4G
C7 05 00 80 0B 00 50 70   mov word [0x000b8000],0x7050 ;"P"
In pmode I would do this:

mov ax,_sVGA
mov es,ax
mov word ptr es:[0],0072eh ; Display a dot
@@:
hlt
jmp @B

I would use positions at X,Y from 0,0 (upper-left) across the
line horizontally to indicate what I went through. In some
places I would use a "-" in others a "+" to indicate which
part of the code went through, etc.

My startup upper-left bar would look like this:

....-...+....

And so on. It was an easy to way indicate it was working
without yet having keyboard and mouse functions, or even
decent video functions.

Later on I had full handlers and wrote code more or less
like we see in DOS.
--
Rick C. Hodgin
Loading...