Detailed explanation of jump from the real mode to the protection mode

Source: Internet
Author: User

Detailed explanation of jump from the real mode to the protection mode

When I got the first version of "write an operating system by myself" three years ago, I was very interested, but I didn't have time to detail it.
After reading it, I saw the second version of it some time ago, and the interest was raised. It's just right after work.
In-depth research.

The first time I read this code, I didn't understand it (I admit it was a very unwise person). I only understood the following Chinese description, saying yes.
From the real mode to the protection mode.
The second time I read this code, I seem to understand it. About 20%.
Third time, fourth time, fifth time ................... n times, I understand. I admit that the ancient buddies did not lie.
People, they all say that the book has been read for hundreds of times.
N + 1 times, I found that the author does not seem to understand. It seems that the author may understand it, but his description makes others
Hard to understand.

So I think I understand this person to give a detailed explanation.

Descriptor is a macro that defines an 8-byte data structure. Then, set the three parameters % 1, % 2, and % 3 according to certain rules.
Automatically fill in the structure. This is relatively simple and there is nothing to say.

For [section. gdt], the first descriptor is a placeholder. The scientific statement is the dummy of an array.

Calculate the base address of selector for the following.

 

Can multiple segment descriptors be defined together in a non-consecutive manner?
Of course. For example:

Label_gdt: descriptor 0, 0, 0; empty Descriptor
Label_desc_code32: descriptor 0, segcode32len-1, da_c + da_32; inconsistent code segment, 32
Other_label: DW 0;
Label_desc_video: descriptor 0b8000h, 0 ffffh, da_drw; first video address

However, in this way, you need to use a complex (mental computing ?) Calculate the index of each descriptor in the gdt table, and then it is difficult to use
You can automatically calculate the index values in each selected sub-item. You need to manually fill in their values for the index locations in each selected sub-item.

What is sub-selection? This is not clear at all.

"In protection mode, the address is still expressed in the form of SEG: Offset, but the segment value is the index of the segment descriptor ",
How can this index be stored in Cs and DS? Before Page Management, how do I transmit the physical address of the base address to DS and CS?
Of course, we can do this manually (mental computing). The value 0 in the gdt table is empty, and the index of the first descriptor label_desc_code32 is 8.
Therefore, when initializing CS, you can directly upload 8 as the index part (note that the attribute part is not discussed). The second descriptor is 8 + 2 + 8, because
We have an other_label, so we can directly pass 0x12 (18) as the index value to GS,
In complex circumstances, not everyone has the ability to calculate.

The Selection Sub-statement represents a structure of the index and attribute of the corresponding descriptor in the gdt table, or a pointer that indicates
The location of the corresponding descriptor in the gdt table. There are two bytes in total, 16 bits.

If we arrange the descriptors consecutively, The 0th descriptors are empty (8 bytes wasted) as the gdt base address. Then the following
Each descriptor is a multiple of 8, 16, 24, 32, and so on for the gdt base address. Therefore
What the LABEL_DESC_CODE32-LABEL_GDT gets is an offset (the author does not say it is not an offset), and this offset value is
The offset of the descriptor to the gdt base address (label_gdt), that is, the index value in the child.

Because the offset of the continuous descriptor to the gdt base address is at least a multiple of 8, the next three digits must be 0, that is

Other bytes, larger than-> 8
00000000,00010000-> 16
Limit limit, 00011000-> 24
Bytes bytes, 00100000-> 32
So the last three digits are not needed. We only need the first 13 digits. When the calculation is performed, you can move the three zeros to the left.
In this way, three digits can be saved during the storage representation. Simply put, the first 13 digits are represented by 8 representing the opposite of the descriptor.
Gdt base address index (8, 16, 24, 32 ......), the first 13 BITs (not multiplied by 8) are the first bits (1, 2, 3, 4...) in the table ...),
The three characters saved are used to represent Ti and rpl.

 

The following gdtptr definition:

Gdtptr DW gdtlen-1; gdt Boundary

Dd 0; gdt base address

 

Gdtptr is actually a pseudo descriptor. Its structure is:

DW: 16-bit Boundary

DD: 32-bit base address

Therefore, the following dd 0 is actually the last four bytes of gdtptr.


Start to enter the code:
MoV ax, CS
MoV ds, ax
MoV es, ax
MoV SS, ax
MoV sp, 0100 H
Because the execution was just started, in the real mode, to make each segment share a base address, CS was passed to DS, es, and SS.
The initial value of sp 0x256 is, that is, the pointer to the top of the stack.

 

 

; Initialize 32-bit code segment descriptor
XOR eax, eax
MoV ax, CS
SHL eax, 4
Add eax, label_seg_code32
MoV word [label_desc_code32 + 2], ax
SHR eax, 16
MoV byte [label_desc_code32 + 4], Al
MoV byte [label_desc_code32 + 7], ah
 
Line 2, 3, and 4 calculate the first address of the field based on the value of CS in the real mode (shift left 4 is multiplied by 16), and initialize the relative address of the descriptor to the protected mode.

Segment Base Address. Then, the address is split and saved to the corresponding location of the label_desc_code32 descriptor.

XOR eax, eax
MoV ax, DS
SHL eax, 4
Add eax, label_gdt; eax <-gdt base address
MoV DWORD [gdtptr + 2], eax; [gdtptr + 2] <-gdt base address

This section serves the same purpose as label_desc_code32 initialization above. The base address of the corresponding data segment in protection mode is calculated based on the DS value in real mode.
Then pass the gdt base address to gdtptr + 2 for the following lgdt call, that is, the unknown dd location.

Gdtptr has a total of 6 bytes, the first two bytes are stored in the gdt boundary (len-1) after the four bytes is the base address of the gdt. So put this address

Location of gdtptr + 2.

 

 

 

Pmtest2.asm:

 

[Section. s16code]
Align 32
[Bits 16]
Label_seg_code16:
; Skip back to real mode:
MoV ax, selectornormal
MoV ds, ax
MoV es, ax
MoV FS, ax
MoV Gs, ax
MoV SS, ax

MoV eax, Cr0
And Al, 11111110b
MoV Cr0, eax

Label_go_back_to_real:
JMP 0: label_real_entry; the segment address is set to the correct value at the beginning of the program.

Code16len equ $-label_seg_code16

 

This code is the same as constructing the protection mode section in the real mode. We need to construct the real mode section in the protection mode to jump back to the real mode.

When switching from the protection mode to the real mode, because each segment register is equipped with a segment descriptor high-speed buffer register, its content will be taken from the protection mode to the real mode,

However, the content "format (in fact, it is the segment attribute in the real mode and cannot be manually modified in the real mode)" is the format in the protection mode, which does not match the real mode, so we need to do two things:

 

1. Load a 16-bit code selectornormal, and copy the segment descriptor of this segment to DS, es, FS, GS, and SS, and actually use these storage

To refresh the contents of these registers in high-speed buffer registers into a 16-bit real-world format ".

Because CS registers cannot be directly filled, you can only jump from the 32-bit code in protection mode to the 16-bit code. The CPU automatically refreshes the CS register's high-speed buffer register.

JMP selectorcode16: 0 serves as JMP [Cs: IP], so the selectorcode16 descriptor is loaded to the CS segment to refresh the high-speed buffer register.

 

2. Because the CS segment attribute is correct, the base address of the CS segment is saved in label_go_back_to_real + 3 in real mode,

That is, the segment address segment of the command JMP 0: label_real_entry. Therefore, JMP 0: label_real_entry can be correctly jumped to the label_real_entry of the actual mode, and the segment address in the original saved real mode is taken to label_real_entry.

 

 

This completes the refresh of the content of all the high-speed buffer registers into the real-mode "format", and then jumps into the real-mode code. Therefore, when the protection mode is switched back to the real-Mode

It will certainly use a Norma Descriptor and a JMP command with the actual CS segment address.

 

Other code is very intuitive and there is nothing special about it.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.