Writing a Simple Operating System — from Scratch

(Jeff_L) #1

CHAPTER 4. ENTERING 32-BIT PROTECTED MODE 38


CPU to flush the pipeline (i.e. complete all of instructions currently in different stages
of the pipeline).
To issue a far jump, as opposed to a near (i.e. standard) jump, we additionally
provide the target segment, as follows:


jmp <segment >:<address offset >

For this jump, we need to think carefully about where we wish to land. Suppose we set up
a label in our code such asstartprotectedmodethat marks the beginning of our 32-bit
code. As we have just discussed, anearjump, such asjmp startprotectedmodemay
not be sufficient to flush the pipeline, and, besides we are now in some strange limbo,
since our current code segment (i.e. cs) will not be valid in protected mode. So, we
must update ourcsregister to the offset of the code segment descriptor of our GDT.
Since the segment descriptiors are each 8 bytes long, and since our code descriptor was
the second descriptor in our GDT (the null descriptor was the first), its offset will be
0x8, and so this value is what we must now set our code segment register to. Note that,
by the very definition of a far jump, it will automatically cause the CPU to update our
csregister to the target segment. Making handy use of labels, we got our assembler to
calculate these segment descriptor offsets and store them as the constantsCODESEGand
DATASEG, so now we arrive at out jump instruction:


jmp CODE_SEG:start_protected_mode

[bits 32]

start_protected_mode:
... ; By now we are assuredly in 32-bit protected mode.
...

Note that, in fact, we don’t need to jump very far at all in terms of the physical distance
between the where we jumped from and where we landed, but the importance was in
how we jump.
Note also that we need to use the[bits 32]directive to tell our assembler that,
from that point onwards, it should encode in 32-bit mode instructions. Note, though,
that this does not mean we cannot use 32-bit instructions in 16-bit real mode, just that
the assembler must encode those instructions slightly differently than in 32-bit protected
mode [?]. Indeed, when switching to protected mode, we made use of the 32-bit register
eaxto set the control bit.
Now we are in 32-bit protected mode. A good thing to do once we have entered
32-bit mode proper is to update all of the other segment registers so they now point to
our 32-bit data segment (rather than the now-invalid real mode segments) and update
the position of the stack.
We can combine the whole process into a re-usable routine, as in Figure XXX.


[bits 16]
; Switch to protected mode
switch_to_pm:
cli ; We must switch of interrupts until we have
; set -up the protected mode interrupt vector
; otherwise interrupts will run riot.
Free download pdf