80x86 Protection Mode Series Tutorial (4) Real Mode and Protection Mode Switching Example

zhaozj2021-02-08  198

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 ; pseudo descriptor

; ------------------------------------------------- ---------------------------

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 ; 32-bit code segment descriptor

Code16 DESC <0FFFFH,, ATCE,>; 16-bit code segment descriptor

DataS Desc ; Source Data Section Descriptor

DATAD DESC <3999, 8000H, 0BH, ATDW,>; Display Buffer Descriptor

Stacks desc ; Stack Section Descriptor

; ------------------------------------------------- ---------------------------

GDTLEN = $ -GDT; global descriptor table length

VGDTR PDESC ; pseudo descriptor

; ------------------------------------------------- ---------------------------

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

转载请注明原文地址:https://www.9cbs.com/read-3196.html

New Post(0)