IV. Real mode and protection mode switching example
This article describes two instances that implement real-mode and protection mode switches. Through them, they explain how to achieve switching of real mode and protection mode, and also illustrate 80386 and their programming in protection mode.
<1> Example of performing real mode and protection mode switching (instance one)
The logical function of examples is that 256 bytes starting from the memory address 110000 in the form of a hexadecimal number. This example specifies the purpose of the memory area only to explain the necessity of switching to the protection mode, because in real mode, it is not accessible to the specified memory area, and can only be accessed to the specified area in the protection mode.
The specific implementation step of this example is: (1) Preparation for switching to the protection method; (2) switching to a protection method; (3) Transferring the contents of the specified memory area to buffer in conventional memory; (4) switching Financial mode; (5) Display buffer content.
1. Contains files
386 Protection Mode Assembly Language Program The included file is shown below, which is used in later programs.
; Name: 386scd.inc
; Function: definition of symbol constant, etc.
; ------------------------------------------------- ---------------------------
; Ifndef __386scd_inc
; __ 386scd_inc equ 1
; ------------------------------------------------- ---------------------------
.386P
; ------------------------------------------------- ---------------------------
Open the A20 address line
; ------------------------------------------------- ---------------------------
Enablea20 macro
Push AX
IN Al, 92H
OR Al, 00000010B
OUT 92H, Al
POP AX
ENDM
; ------------------------------------------------- ---------------------------
Close the A20 address line
; ------------------------------------------------- ---------------------------
Disablea20 macro
Push AX
IN Al, 92H
And Al, 11111101B
OUT 92H, Al
POP AX
ENDM
; ------------------------------------------------- ---------------------------
; 16-bit offset, direct transfer command macro definition (used in 16-bit code segments)
; ------------------------------------------------- ---------------------------
Jump16 Macro Selector, Offset
DB 0EAH; opcode
DW Offset; 16-bit offset
DW selector; segment value or segment selector
ENDM
; ------------------------------------------------- ---------------------------
; 32-bit offset, direct transfer command macro definition (used in 32-bit code segments)
; ------------------------------------------------- --------------------------- Comment
Jump32 Macro Selector, Offset
DB 0EAH; opcode
DD Offset
DW selector; segment value or segment selector
ENDM
; -------------------------------------------------
Jump32 Macro Selector, Offset
DB 0EAH; opcode
DW offset
DW 0
DW selector; segment value or segment selector
ENDM
; ------------------------------------------------- ---------------------------
; 16-bit offset segment call macro definition (used in 16-bit code segments)
; ------------------------------------------------- ---------------------------
Call16 Macro Selector, Offset
DB 9AH; opcode
DW Offset; 16-bit offset
DW selector; segment value or segment selector
ENDM
; ------------------------------------------------- ---------------------------
; 32-bit offset interval call command macro definition (used in 32-bit code segments)
; ------------------------------------------------- ---------------------------
Comment
Call32 Macro Selector, Offset
DB 9AH; opcode
DD Offset
DW selector; segment value or segment selector
ENDM
; -------------------------------------------------
Call32 Macro Selector, Offset
DB 9AH; opcode
DW offset
DW 0
DW selector; segment value or segment selector
ENDM
; ------------------------------------------------- ---------------------------
; Save Descriptor Structure Type Definition
; ------------------------------------------------- ---------------------------
DESC STRUC
Limitl DW 0; Duan Direction (Bit0-15)
Basel DW 0; Segment base site (Bit0-15)
Basem DB 0; Segment Bi Site (Bit16-23)
Attributes db 0; segment attribute
Limith DB 0; Segment Bounder (Bit16-19) (with high 4 digits of segmentation)
Baseh db 0; section base site (bit24-31)
DESC ENDS
; ------------------------------------------------- ---------------------------; Door Descriptor Structure Type Definition
; ------------------------------------------------- ---------------------------
Gate struch
OFFSETL DW 0; 32-bit offset low 16 bits
Selector dw 0; selector
DCOUNT DB 0; double word count
GTYPE DB 0; Type
OFFSEth DW 0; 32-bit offset high 16-bit
Gate Ends
; ------------------------------------------------- ---------------------------
; Pseudo Descriptor Structure Type Definition (for loading global or interrupt descriptor table registers)
; ------------------------------------------------- ---------------------------
PDESC STRUC
Limit DW 0; 16-bit boundary
Base DD 0; 32 base address
PDESC ENDS
; ------------------------------------------------- ---------------------------
; Task State Segment Structure Type Definition
; ------------------------------------------------- ---------------------------
TSS STRUC
Trlink dw 0; link field
DW 0; not used, set to 0
Tresp0 DD 0; 0-level stack pointer
TRSS0 DW 0; 0-level stack segment register
DW 0; not used, set to 0
Tresp1 DD 0; Level 1 Stack Pointer
TRSS1 DW 0; Level 1 stack segment register
DW 0; not used, set to 0
TRESP2 DD 0; Level 2 Stack Pointer
TRSS2 DW 0; Level 2 stack segment register
DW 0; not used, set to 0
TRCR3 DD 0; CR3
Treip DD 0; EIP
Treflag DD 0; EFLAGS
Treax DD 0; EAX
TRECX DD 0; ECX
TREDX DD 0; EDX
Trebx DD 0; EBX
TRESP DD 0; ESP
Trebp DD 0; EBP
Tresi DD 0; ESI
TREDI DD 0; EDI
TRES DW 0; ES
DW 0; not used, set to 0
TRCS DW 0; CSDW 0; not used, set to 0
TRSS DW 0; SS
DW 0; not used, set to 0
TRDS DW 0; DS
DW 0; not used, set to 0
TRFS DW 0; FS
DW 0; not used, set to 0
TRGS DW 0; GS
DW 0; not used, set to 0
TRLDTR DW 0; LDTR
DW 0; not used, set to 0
TRTRIP DW 0; debug trap flag (only 0)
TriOMAP DW $ 2; pointing to the block of I / O license bit
TSS Ends
; ------------------------------------------------- ---------------------------
Demon section descriptor type value description
; ------------------------------------------------- ---------------------------
ATDR EQU 90H; existing read-only data segment type value
ATDW EQU 92H; existing readable write data segment attribute value
ATDWA EQU 93H; the existing access readable write data segment type value
ATCE EQU 98H; only execute code segment attribute values
Atcer EQU 9ah; existing executable readable code segment attribute value
Atcco EQU 9ch; only performs a consistent code segment attribute value
Atcor EQU 9EH; existing executable readable uniform code segment attribute value
; ------------------------------------------------- ---------------------------
; System segment descriptor type value description
; ------------------------------------------------- ---------------------------
ATLDT EQU 82H; Partial Descriptive Table Segment Type Value
Attaskgate EQU 85H; Task Door Type Value
AT386TSS EQU 89H; 386 task status segment type value available
AT386CGATE EQU 8CH; 386 Call Door Type Value
AT386IGATE EQU 8EH; 386 Interrupt door type value
AT386TGATE EQU 8FH; 386 trap door type value
; ------------------------------------------------- ---------------------------
DPL value description
; ------------------------------------------------- ---------------------------
DPL0 EQU 00H; DPL = 0
DPL1 EQU 20H; DPL = 1
DPL2 EQU 40H; DPL = 2
DPL3 EQU 60H; DPL = 3
; ------------------------------------------------- ---------------------------; RPL value description
; ------------------------------------------------- ---------------------------
RPL0 EQU 00H; RPL = 0
RPL1 EQU 01H; RPL = 1
RPL2 EQU 02H; RPL = 2
RPL3 EQU 03H; RPL = 3
; ------------------------------------------------- ---------------------------
IOPL value description
; ------------------------------------------------- ---------------------------
IOPL0 EQU 0000h; IOPL = 0
IOPL1 EQU 1000H; IOPL = 1
IOPL2 EQU 2000H; IOPL = 2
IOPL3 EQU 3000H; IOPL = 3
; ------------------------------------------------- ---------------------------
Other constant value description
; ------------------------------------------------- ---------------------------
D32 EQU 40H; 32-bit code segment flag
GL EQU 80H; Segment Boundary Limit in 4K
TIL EQU 04H; Ti = 1 (partial descriptor table sign)
VMFL EQU 00020000H; VMF = 1
VMFLW EQU 0002H
IFL EQU 00000200H; if = 1
RFL EQU 00010000H; RF = 1 (restart flag, 1 means ignore debug faults)
RFLW EQU 0001H
NTL EQU 00004000H; NT = 1
; ------------------------------------------------- ---------------------------
Constant description
; ------------------------------------------------- ---------------------------
PL EQU 1; page exists attribute bits
RWR EQU 0; R / W attribute bit value, read / execution
RWW EQU 2; R / W attribute bit value, read / write / execution
USS EQU 0; U / S attribute bit value, system level
USU EQU 4; U / S attribute bit value, user-level
; ------------------------------------------------- ---------------------------
; ENDIF
2. Execologics
The source program of examples is as follows:
Name: asm1.asm
; Function: Demonstration and protection mode switch (switch to 16-bit code segment)
; ------------------------------------------------- ---------------------------
INCLUDE 386SCD.Ic
; ------------------------------------------------- ---------------------------
Character display macro definition
; ------------------------------------------------- ---------------------------
Echoch macro ascii
MOV AH, 2
MOV DL, ASCII
Int 21h
ENDM
; ------------------------------------------------- ---------------------------
DSEG segment use6; 16-bit data segment
; ------------------------------------------------- ---------------------------
GDT Label Byte; Global Description Table
Dummy DESC <>; empty descriptor
Code Desc <0FFFH,, ATCE,,>; Code Segment Descriptor
DataS Desc <0fffh, 0, 11h, ATDW,>; Source Data Section Descriptor
DATAD DESC <0FFFFH,, ATDW,>; Target Data Section Descriptor
; ------------------------------------------------- ---------------------------
GDTLEN = $ -GDT; global descriptor table length
VGDTR PDESC
; ------------------------------------------------- ---------------------------
Code_sel = Code-GDT; code segment selector
DataS_sel = DataS-GDT; Source Data Section Select Sub
DATAD_SEL = DATAD-GDT; target data segment selector
; ------------------------------------------------- ---------------------------
BUFLEN = 256; buffer byte length
Buffer DB buflen dup (0); buffer
; ------------------------------------------------- ---------------------------
DSEG ENDS; Data Segment Definition End
; ------------------------------------------------- -------------------------- CSEG segment use6; 16-bit code segment
Assume CS: CSEG, DS: DSEG
; ------------------------------------------------- ---------------------------
START Proc
MOV AX, DSEG
MOV DS, AX
; Prepare a counterfeit name to load to GDTR
MOV BX, 16
Mul bx
Add Ax, Offset GDT; calculated and set the base address
ADC DX, 0; the boundary is already defined when setting up
Mov Word Ptr vgdtr.base, AX
Mov Word Ptr Vgdtr.Base 2, DX
Set the code segment descriptor
MOV AX, CS
Mul bx
Mov Word Ptr Code.Basel, AX; code segment begins offset to 0
MOV BYTE PTR Code.basem, DL; code segment boundary is already set when defined
Mov Byte Ptr Code.baseh, DH
Set the target data segment descriptor
MOV AX, DS
MUL BX; calculate and set target data segment baseholder
Add Ax, Offset Buffer
ADC DX, 0
Mov Word PTR DATAD.BASEL, AX
MOV BYTE PTR DATAD.BASEM, DL
MOV BYTE PTR DATAD.BASEH, DH
Load GDTR
LGDT QWORD PTR VGDTR
CLI;
Enablea20; Open address line A20
; Switch to protection
MOV Eax, Cr0
OR EAX, 1
MOV CR0, EAX
; Qing Directive Prefetch Queue, and truly enters protection
Jump16 code_sel,
Virtual:; Now start running in the protection mode
MOV AX, DATAS_SEL
MOV DS, AX; load source data segment descriptor
Mov AX, DATAD_SEL
MOV ES, AX; load target data segment descriptor
CLD
XOR Si, Si
XOR DI, DI; Settings Pointer Attribution
MOV CX, BUFLEN / 4; set 4 bytes of buffer length
REPZ MOVSD; transfer
; Switch back
MOV Eax, Cr0
And Al, 11111110B
MOV CR0, EAX
; Qing Directive Prefetch Queue, Enter Real Way
JUMP16
REAL:; now back to the real way
Disablea20
STI
MOV AX, DSEG
MOV DS, AX
MOV Si, Offset Buffer
CLD
MOV BP, BUFLEN / 16
NextLine: MOV CX, 16
Nextch: lodsb
Push AX
SHR Al, 1
Call toasciiechoch alone
POP AX
Call toascii
Echoch al
Echoch ''
Loop nextch
Echoch 0DH
Echoch 0ah
Dec BP
Jnz nextline
MOV AX, 4C00H
Int 21h
START ENDP
; ------------------------------------------------- ---------------------------
Toascii Proc
And Al, 0FH
Add Al, 90h
DAA
ADC Al, 40h
DAA
RET
Toascii ENDP
; ------------------------------------------------- ---------------------------
CSEG ENDS; code segment definition ends
; ------------------------------------------------- ---------------------------
End Start
3. About the annotation of the example step
In the beginning of the source program, the file "386scd.inc" is first included, and some of the structural, macros and constants for protection mode program designs are defined in this included file. Each implementation step is made below.
(1) Preparation for switching to protection
Before switching from the real mode to the protection mode, it must be prepared. The content of the preparation work is determined. The minimum preparation work is to establish a suitable global descriptor table and use GDTR to point to the GDT. Since it is at least loaded to the CS when switching to the protection method, at least the descriptor of the code segment is at least the CS segment.
From this example source program, the global descriptor table GDT has only four descriptors: the first is an empty descriptor; the second is the code segment descriptor; the third and fourth are the source data segment and the target, respectively. Data segment descriptor. The segment boundary in each descriptor in this example is set when defined, and the limit of the boundary in the VGDTR in the descriptor VGDTR is set to 0FFFH in addition to the actual length of the GDT. In addition, segment properties in the descriptor are also preset according to the type described, and the definition of each attribute is described in the included file 386scd.inc. From the attribute value, these three segments are 16-bit segments.
Since the GDT is referenced after switching to the protection mode, GDTR must be loaded before switching to the protection mode. Use the following instructions to load GDTR in the example:
LGDT QWORD PTR VGDTR
The function of the instruction is to put the counterfeit character VGDTR in the memory into the global descriptor table register GDTR. The structure of the pseudo descriptor VGDTR is shown in front of the structural type PDESC, the low word is the boundary of the global descriptor table segment in the byte bit unit, and the high double word is a linear base address of the descriptor table segment (this instance is not enabled. The paging mechanism, so the linear address is equivalent to the physical address). This example does not involve local descriptors and interrupt descriptors, which will be described in detail.
(2) Switch to the protection mode by real mode
After being ready, switch to the protection mode from real mode is not difficult. In principle, simply use the PE position 1 in the control register CR0. This example uses the following three instructions to set the PE bit:
MOV Eax, Cr0
OR EAX, 1
MOV CR0, EAX
The actual situation is more complicated than this. After performing the three instructions above, the processor is transferred to the protection mode, but the contents of the CS are also the segment values of the code segments in the real mode, rather than the selection of code segments in the protection mode, so before the instruction is taken, the code segment is obtained. The selector is loaded into the CS. To this end, these three instructions are scheduled to arrange a paragraph transfer command as shown below: Jump16 Code_sel,
This section transfer instruction
Prefetched in real mode and is performed in the protection mode. Using this paragraph transfer instruction to load the selection of the code segment in the protection mode into the CS while also refreshing the instruction prefetch queue. From then on, I really entered the protection mode.
(3) Switch by the protection mode to the real mode
On 80386, the process switches from the protection mode to the real mode is similar to the protected mode to the protection mode. In principle, simply clear the PE bit in the control register CR0. In fact, a section of the transfer instruction is also arranged, one side of the instruction prefetch queue, and the other hand sends a segment value of the code segment in the real mode.
This paragraph transfer instruction is prefiltrated in the protection mode and is executed in real mode.
(4) Data transfer in protection mode
First, load the source data segment and the selector of the target data segment into the DS and ES registers, which have been set in real mode, which means that the selection of sub-load registers means including base sites. Segment information is loaded into the segment descriptor cache register. Then set the initial value of the pointer registers Si and Di, and set the initial value of the counter CX. Depending on the preset segment attribute, in the protection mode, the code segment is only 16-bit segments, and the string operation instruction only uses registers such as Si, DI, and CX. Finally, the transfer is implemented using a string operation instruction.
(5) Show content in the buffer
Since the buffer is in conventional memory, it is easy to understand according to the requirements according to the requirements in the real mode, and it will not be more to say.
4. Memory image
The GDT did not treat GDT in the source program, but after entering the protection method, it is a separate segment. From the base address and segment boundary limit assigned to the code segment and the source data segment descriptor, the code segment and the data segment are partially covered. Although this is not conducive to the safety of code and data, it is feasible if necessary. The memory image of this instance is shown below.
5. Special explanation
As an example of the first real mode and the protection mode switching, the instance is a large amount of simplified processing.
Typically, preparations for switching to the protection mode by real mode should also include establishing an interrupt descriptor table. However, this example does not have an interrupt descriptor table. To this end, the entire process is required to carry out the interruption of the process; the requirements do not use soft interrupt instructions; assuming does not have any exceptions. Otherwise it will cause the system to crash.
This example does not use a local descriptor table, so the local descriptor table register LDTR is not set after entering the protection mode. To this end, the segment selector used in the protection mode specifies the descriptor in the GDT.
In this example, the stack segment in the protection mode is not defined. There is no stack segment descriptor in the GDT, and SS is not set in the protection mode, so there is no instruction to the stack operation in the protection mode.
The privilege-level RPL of each descriptor grade DPL and each of the selected sub-RPLs is 0, and the current privileged CPL at the time of protection is also 0.
This example does not use the paging management mechanism, that is, the PG bit in CR0 is 0, and the linear address is the physical address of the memory cell.
6. Open and close the address line A20
The 21st address line (A20) of the PC and its compatible machine is special, and a "door" is generally arranged in the computer system to control whether the address line is valid. In order to access the address of the address of 1 m or more, the "door" of the control address line A20 should be opened first. This setting is related to only the lowest end 1M byte storage space in the real mode, and whether it works in real mode or protection mode if it works, even when the address line A20 is turned off, it can also enter the protection mode.
How to open and close the address line A20 is related to the specific settings of the computer system. Two macros are defined in the included file 386scd.inc described herein, open the macro Enablea 20 of the address line A20 and the macro disablea20 of the closing address line A20, which is feasible on a general PC compatible machine. <2> Demos 32-bit code segments and 16-bit code segment switching instance (Example 2)
The logical function of the example II is the content of 16 bytes starting from the memory address 100000h in two forms of hexadecimal and ASCII characters.
From the functional view, this example is similar to the example one, but there is a change in implementation methods, it can more reflect the case of switching the model and protection mode. The specific implementation step is: (1) Preparation for switching to protection; (2) switching to a 32-bit code segment of the protection mode; (3) convert the content of the specified memory area in byte, converted into a corresponding ten The six-incoming ASCII code is filld in the display buffer implementation display; (4) change to a 16-bit code segment in the protection mode; (5) Fill in the specified memory area as an ASCII code The display is displayed in the buffer; (6) Switch to the real mode.
Example binary program
Example II The source program is as follows:
Name: asm2.asm
; Function: Demonstration and protection mode switch (switch to 32-bit code segment)
; ------------------------------------------------- ---------------------------
INCLUDE 386SCD.Ic
; ------------------------------------------------- ---------------------------
DSEG segment use6; 16-bit data segment
; ------------------------------------------------- ---------------------------
GDT Label Byte; Global Description Table
Dummy DESC <>; empty descriptor
Normal DESC <0FFFH,, ATDW,>; Specification Segment Descriptor
CODE32 DESC
Code16 DESC <0FFFFH,, ATCE,>; 16-bit code segment descriptor
DataS Desc
DATAD DESC <3999, 8000H, 0BH, ATDW,>; Display Buffer Descriptor
Stacks desc
; ------------------------------------------------- ---------------------------
GDTLEN = $ -GDT; global descriptor table length
VGDTR PDESC
; ------------------------------------------------- ---------------------------
SAVESP DW?; Used to save SP registers SAVESS DW?; For saving SS registers
; ------------------------------------------------- ---------------------------
NORMAL_SEL = NORMAL-GDT; Specification Segment Descriptor Select Sub
Code32_sel = Code32-GDT; 32-bit code segment selector
Code16_sel = Code16-GDT; 16-bit code segment selector
DataS_sel = DataS-GDT; Source Data Section Select Sub
DATAD_SEL = DATAD-GDT; target data segment selector
Stacks_sel = stacks-gdt; Stack Segment Descriptor Select Sub
; ------------------------------------------------- ---------------------------
Datalen = 16
; ------------------------------------------------- ---------------------------
DSEG ENDS; Data Segment Definition End
; ------------------------------------------------- ---------------------------
Stackseg Segment Para Stack USE16
Stacklen = 256
DB Stacklen DUP (0)
Stackseg Ends
; ------------------------------------------------- ---------------------------
CSEG1 segment use6 'real'; 16-bit code segment
Assume CS: CSEG1, DS: DSEG
; ------------------------------------------------- ---------------------------
START Proc
MOV AX, DSEG
MOV DS, AX
; Prepare a counterfeit name to load to GDTR
MOV BX, 16
Mul bx
Add Ax, Offset GDT; calculated and set the base address
ADC DX, 0; the boundary is already defined when setting up
Mov Word Ptr vgdtr.base, AX
Mov Word Ptr Vgdtr.Base 2, DX
Set 32-bit code segment descriptor
MOV AX, CSEG2
Mul bx
Mov Word Ptr Code32.Basel, AX
MOV BYTE PTR Code32.basem, DL
Mov Byte Ptr Code32.Baseh, DH
Set 16-bit code segment descriptor
MOV AX, CSEG3
Mul bx
Mov Word Ptr Code16.Basel, AX; code segment begins offset to 0mov Byte Ptr Code16.baSem, DL; code segment boundary is already set when defined
Mov Byte Ptr Code16.Baseh, DH
Set the stack segment descriptor
MOV AX, SS
Mov Word PTR Savess, AX
MOV Word Ptr Savesp, SP
Mov AX, Stackseg
Mul bx
Mov Word Ptr Stacks.Basel, AX
Mov Byte Ptr Stacks.basem, DL
Mov Byte Ptr Stacks.baseh, DH
Load GDTR
LGDT QWORD PTR VGDTR
CLI;
Enablea20; Open address line A20
; Switch to protection
MOV Eax, Cr0
OR Al, 1
MOV CR0, EAX
; Qing Directive Prefetch Queue, and truly enters protection
Jump16 code32_sel,
Now now back to the real way
MOV AX, DSEG
MOV DS, AX
MOV SP, Savesp
Mov SS, SAVESS
Disablea20
STI
MOV AX, 4C00H
Int 21h
START ENDP
; ------------------------------------------------- ---------------------------
CSEG1 ENDS; code segment definition end
; ------------------------------------------------- ---------------------------
CSEG2 segment use32 'pm32'
Assume CS: CSEG2
; ------------------------------------------------- ---------------------------
SPM32 Proc
MOV AX, Stacks_sel
Mov SS, AX
MOV ESP, Stacklen
MOV AX, DATAS_SEL
MOV DS, AX
Mov AX, DATAD_SEL
Mov ES, AX
XOR ESI, ESI
XOR EDI, EDI
Mov ECX, Datalen
CLD
Next: lodsb
Push AX
Call toascii
Mov Ah, 7
SHL EAX, 16
POP AX
SHR Al, 4
Call toascii
Mov Ah, 7
Stosd
MOV Al, 20h
Stosw
Loop next
Jump32 code16_sel,
SPM32 ENDP
; ------------------------------------------------- ---------------------------
Toascii Proc
And Al, 00001111B
Add Al, 30H
CMP Al, 39h
Jbe isdig
Add Al, 7ISDIG: RET
Toascii ENDP
; ------------------------------------------------- ---------------------------
C32len = $
; ------------------------------------------------- ---------------------------
CSEG2 ENDS
; ------------------------------------------------- ---------------------------
CSEG3 Segment USE16 'PM16'
Assume CS: CSEG3
; ------------------------------------------------- ---------------------------
SPM16 Proc
XOR Si, Si
MOV DI, DATALEN * 3 * 2
Mov Ah, 7
MOV CX, Datalen
Again: Lodsb
Stosw
Loop again
Mov Ax, Normal_Sel
MOV DS, AX
Mov ES, AX
Mov SS, AX
MOV Eax, Cr0
And Al, 11111110B
MOV CR0, EAX
JMP Far PTR Toreal
SPM16 ENDP
; ------------------------------------------------- ---------------------------
CSEG3 ENDS
; ------------------------------------------------- ---------------------------
End Start
2. Notes on implementing steps
(1) Prepare for switching to protection mode
Building a global descriptor table, the global descriptor table here contains two 16-bit data segments descriptors, a descriptor of a 16-bit code segment and a 16-bit stack segment descriptor. In addition, there is a 32-bit code segment descriptor in the GDT, describing a 32-bit code segment, and the D bit in the properties field of the descriptor is 1.
(2) Switch to the protection mode by real mode
The method of switching to the protection mode 32-bit code segment is the same as the method of switching to a 16-bit code segment. The method of switching the real mode by the protection mode 16-bit code segment is similar to the example.
In the protection mode, switch instructions from 32-bit code segments to 16-bit code segments by transfer instructions in the following direct segmentation:
Jump32 code16_sel,
From the definition of this macro, the transfer instruction contains 48-bit pointer, which is 16 bits of 16-bit code segment, and the lower 32 bits are the inlet offset of the 16-bit code segment.
This instruction is prefetched and executed in a 32-bit manner. Since executed in 32-bit mode, use 48-bit pointers.
(3) Display the contents of the specified memory area
In this example, the method of direct writing display buffer is used. Assuming that the starting physical address of the display buffer is 0B8000H, 3 text display mode, displayed on the first line of the screen.
3. Special explanation
This example uses instructions involving the stack operation in the protection mode, thus establishing a 16-bit protection mode stack segment.
This example still has a large amount of simplification. Such as: No IDT and LDT, etc., each privileged level is 0. There is also no page management mechanism.
As can be seen from the GDT of this example, the boundaries of the two data segments are set according to the actual size. As can be seen from the source program code segment, the selection of the descriptor Normal pointing to the Data Section that does not use without use is loaded into the DS and ES before switching to the real mode. This is why? Real mode The following descriptor cushioning register's content segment register segment base address segment limit (fixed) segment attribute (fixed) existing privilege level Acquisition granular expansion Direction Readability can be used to perform stack size consistent with the current privilege CS CS * 160000FFFFHY0YBUYYY-NSS current SS * 160000FFFFHY0YBUYYNW-DS current DS * 160000FFFFHY0YBUYYN - ES current ES * 160000FFFFHY0YBUYYN - FS current FS * 160000FFFFHY0YBUYYN - GS current GS * 160000FFFFHY0YBUYYN--
In the following article, each segment register is equipped with a segment descriptor cache register. These high-speed buffer registers still play a role in real-mode, but they differ from the protection mode. As shown in the table below, "Y" means "YES"; "N" means "NO"; "B" means byte; "U" means the upward expansion, "W" means the stack of words in words. Segment base address is still 32 bits, its value is the corresponding segment register value (segment value) multiplied by 16, and is refreshed when the segment value is loaded into the segment register. Since it is a 16-bit value multiplying 16, the base site is actually only 20 digits in the real mode. The 32-bit boundaries of each segment are fixed to 0FFFH, and many bits of segment properties are fixed. The so-called fixed means that these attribute values cannot be set in real mode, and can only continue along the value of the protection mode. Therefore, before preparing to end the protection mode is returned to the real mode, the sub-register is to be selected by loading a suitable descriptor, so that the corresponding segment descriptor high-speed buffer register contains appropriate segment limit and attributes. The descriptor NORMAL in the GDT of this example is such a descriptor that loads the corresponding selection sub-Normal_Sel to DS and ES before returning the real mode. Since the content in the SS segment descriptor is in line with the needs of the real mode, although the SS has also changed, it is not necessary to reload SS (this instance is reloaded in this instance, which in addition to slightly increase the run time, there is nothing wrong) . The contents of the 16-bit code segment descriptor are also in line with the needs of the real mode, so when returning to real mode through the 16-bit code segment, the contents of the CS segment descriptor also meet the requirements of the real mode. It should be noted that the real mode cannot be returned from the 32-bit code segment, because the attributes in the CS high-speed buffer register cannot be implemented from the 32-bit code segment (real mode cannot change the segment attribute). By the way, the descriptor in Example No. Example is in line with real mode requirements. Segment Descriptor High Speed Buffer Register Contains Suitable Segment Direction
4. Description of 32-bit code segment programming
In the 32-bit code segment, the default operating size is 32 bits, and the default storage unit address size is 32 bits. Since the pointer register used by the string operation instructions is ESI and EDI, the counter used by the LOOP instruction is ECX, in the code segment CSEG2, in order to use the serial operation instruction, the ESI and EDI registers are assigned to the initial value. Please compare the relevant fragments in CSEG3 in CSEG3, which is a 16-bit code segment.
Reference information book name Society Society "80386 and its programming" Tsinghua University Press, Zhou Mingde, editor "80x86 assembly language program design tutorial" Tsinghua University Publishing Social Yang Qiwen Editor