"0" written in front
0.1) The purpose of this code:The purpose of this text is to explain the function of the local descriptor, its definition, initialization and jump, etc.
0.2)The personal summary at the end of the article is dry, the preceding code is for reference only, and source code from Orange's implemention of a OS.
0.3)Since the code in this article and the "Steps of the real mode and protected mode switching" source code has a similarity of 90%, see http://blog.csdn.net/pacosonswjtu/article/details/48009165, therefore, I only have a simple annotated description of the code involving the local descriptor Ldt;
0.4)Multi-attention and (real mode + protected mode) mode switching process step (http://blog.csdn.net/pacosonswjtu/article/details/48009165) to do the comparison;
; ==========================================; pmtest2.asm; 编译方法:nasm pmtest2.asm -o pmtest2.com; ==========================================%include "pm.inc" ; 常量, 宏, 以及一些说明 org 0100h jmp LABEL_BEGIN
; Global Descriptor Descriptor Definition
[section. GDT]
; GDT; 段基址, 段界限 , 属性......LABEL_DESC_LDT: Descriptor 0, LDTLen - 1, DA_LDT ; LDT......<font size=5 color=green>;GDT 选择子定义</font>......SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT ; Mine【SelectorLDT 是重头戏哦】......
; END of [section. GDT]
Data segment definition + global stack segment definition
......
16-bit code snippet, the CPU is running in real mode, why the value in GDT can be modified only under 16-bit code snippet
[section. S16]; Mine "Getting ready to jump to protected mode for the actual mode"
[BITS 16]LABEL_BEGIN: ......
; Initializes the descriptor of the LDT in the GDT; Mine "Label_desc_ldt as a GDT table item"
xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_LDT mov word [LABEL_DESC_LDT + 2], ax shr eax, 16 mov byte [LABEL_DESC_LDT + 4], al mov byte [LABEL_DESC_LDT + 7], ah
; Initializes a descriptor in the LDT; Mine "Initializes the specific multi-tasking code snippet that the base site of the LDT points to"
xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_CODE_A mov word [LABEL_LDT_DESC_CODEA + 2], ax shr eax, 16 mov byte [LABEL_LDT_DESC_CODEA + 4], al mov byte [LABEL_LDT_DESC_CODEA + 7], ah
; Prepare to load GDTR, populate the data structure of the GDT base site
xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_GDT ; eax <- gdt 基地址 mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址
; Load GDTR
lgdt [GdtPtr]
; Off interrupt
cli
; Open Address line A20
in al, 92h or al, 00000010b out 92h, al
; Ready to switch to protected mode, PE position 1
mov eax, cr0 or eax, 1 mov cr0, eax
; Real access to Protected mode
jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0 处
; Jumping back from protected mode to real mode is here (note: Jump from protected mode to real mode, that is, under this identifier, this identifier is at the end of the 16-bit code snippet that exists at the initialization descriptor)
LABEL_REAL_ENTRY: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, [SPValueInRealMode]
; Close A20 Address Line
in al, 92h ; and al, 11111101b out 92h, al ; / sti ; 开中断 mov ax, 4c00h ; `. int 21h ; / 回到 DOS
; END of [section. S16]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 32-bit code snippet, which is protected mode. Jump in from Real mode
[section. S32]
[BITS 32]LABEL_SEG_CODE32:......
; A string is shown below (the code here is omitted)
; Mine "Here the LDT Selection Sub-index is the base address value of the descriptor descriptor recorded in the LDT, that is, the execution code of the specific task"
; Load LDT</font> mov ax, SelectorLDT ; lldt ax ; Mine【lldt 负责 加载ldtr, 它的操作数是一个选择子,这个选择子对应的就是用来描述LDT的那个描述符LABEL_DESC_LDT】
; Jump into a local task
jmp SelectorLDTCodeA:0 SegCode32Len equ $ - LABEL_SEG_CODE32
; END of [section. S32]
; 16-bit code snippet. Jumped from a 32-bit code snippet, this paragraph jumps back to real mode
[section. S16code]
ALIGN 32[BITS 16]LABEL_SEG_CODE16:
; To jump back to Real mode:
mov ax, SelectorNormal ; Mine【 选择子 SelectorNormal 是对描述符 LABEL_DESC_NORMAL 的索引 】 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov eax, cr0 and al, 11111110b ; Mine【cr0的最后一位PE位置为0,进入实模式】 mov cr0, eaxLABEL_GO_BACK_TO_REAL: jmp 0:LABEL_REAL_ENTRY ; 段地址会在程序开始处被设置成正确的值Code16Len equ $ - LABEL_SEG_CODE16
; END of [section. S16code]
; Definition of the LDT
[section. Ldt]
ALIGN 32LABEL_LDT:; 段基址 段界限 属性LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1, DA_C + DA_32 ; Code, 32 位LDTLen equ $ - LABEL_LDT
; Definition of the LDT selector
SelectorLDTCodeA equ LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL
; END of [section. Ldt]
; Codea (LDT, 32-bit code snippet), select sub Selectorldtcodea by index to jump in
[Section. La]
ALIGN 32[BITS 32]LABEL_CODE_A: mov ax, SelectorVideo mov gs, ax ; 视频段选择子(目的) mov edi, (80 * 12 + 0) * 2 ; 屏幕第 10 行, 第 0 列。 mov ah, 0Ch ; 0000: 黑底 1100: 红字 mov al, ‘L‘ mov [gs:edi], ax
; Ready to jump back to real mode via 16-bit code segment
jmp SelectorCode16:0CodeALen equ $ - LABEL_CODE_A
; END of [section. La]
Summary: Function of the local descriptor descriptor + definition + initialization + Jump correlation: (Dry goods)
(Attention: We parse the contents of the memory according to the steps of the program execution process)
(1)Org 0100, tells the compiler program to run, to load to the offset address 0100; jmp Label_begin jumps into 16-bit code Snippets (real mode) for each data segment, code snippet, stack segment initialization, Finally, it jumps into the base address of the task code stored by a descriptor in the local descriptor table to run;
(2) GDT initialization {definition segment descriptor (including LDT descriptor Label_desc_ldt) + Define GDTR data structure + define GDT selector (including selection sub Selectorldt for LDT descriptor Label_desc_ldt)}:
- 2.1) Define the Global Descriptor Table GDT, which defines the required segment descriptors, data segments, and code snippet descriptor data structures as follows:
- 2.2) Define the data structure of the GDTR Global descriptor and assign values, the GDTR data structure is as follows:
- 2.3) Define the GDT selector: How many descriptors are there, and how many selectors are used to record the offset address that describes typeface for the GDT base address, because the base addresses and bounds of the GDT are stored in the Global descriptor Register GDTR, We can find the GDT base address by GDTR, and then find the corresponding offset address by selecting the sub, so as to find the base address + boundary (offset) + attribute of the corresponding segment descriptor, and the value describing the's baseline address also records the base addresses of each code snippet or data segment. So that we can index to the specific code snippet and data segment by selecting the child;
(3) Definition of data segment + Stack segment
(4) Definition of 16-bit code snippet (real mode):
- 4.1) set the code to run the environment, that is, to assign values to the relevant registers;
- 4.2) initializes the 16-bit code snippet Descriptor + 32-bit code snippet descriptor + Stack segment descriptor + data segment descriptor, which focuses on initializing the LDT descriptor in the GDT and initializing the descriptor in the LDT (defined at the end of the code);
- 4.3) Initializes the contents of the Global Descriptor Descriptor GDTR, because its base address is not initialized and then loads the contents of the GDTR in memory through LGDT [Gdtptr], focusing on preserving the base site of the GDT;
- 4.4) off interrupt, that is, set the CPU does not respond to any other external interrupts, because the CPU now the time slice only belongs to the currently loaded program;
- 4.5) open Address line A20; As for why to open, hehe, see: http://blog.csdn.net/pacosonswjtu/article/details/48005813
4.6) CR0 the PE position of the 1;PE bit ==1, indicating that the CPU is running in protected mode, (this is ready to switch to the protection mode phase), the CR0 data structure is as follows:
4.7) jump to Protected mode: JMP DWORD selectorcode32:0, where the code refers to a selector, (3) The last part, which explains why you can index to 32-bit code segments by selecting a child label_seg_code32 ; (This is the actual mode to jump into protected mode)
(5) Definition of 32-bit code snippet (in the form of a real-mode jump, Protected mode)
- 5.1) will assign the corresponding selection to the corresponding register, that is, set the operating environment of the task code, you have to mention that the code also changed the SS and ESP, the 32-bit code snippet all the stack operation will be in the new stack segment;
- 5.2) Do the task, we are here to print a string of strings;
- 5.3) task done after, through MOV ax, Selectorldt; Lldt ax; Loads the selection of the LDT to the local descriptor LDTR register, and jumps to the local task to execute;
(6) The definition of the LDT (LDT Descriptor definition + LDT Selection sub-definition + required to complete the task code), the definition of the content of the same as GDT;
- 6.1) The LDT descriptor definition, which only defines a descriptor here;
- 6.2) define the corresponding selectors;
- 6.3) defines the code snippet that executes the task, in which, when the task executes, it is ready to jump back into real mode via a 16-bit code segment (jump to 16-bit code snippet, then jump to real mode);
- add: jump to 16-bit code snippet because jumping back from protected mode to real mode only jumps back from the 16-bit code snippet ;
(7) Back to the real mode of the 16-bit code snippet (we simply call it a transition of the 16-bit code snippet, and the module (4) to make a difference)
- 7.1) loads a descriptor selector, which says that the properties in the CS cache register to be implemented from the 32-bit code snippet are in compliance with the real-mode requirements, (specifically, I do not understand here)
- 7.2) the CR0 PE position 0;pe bit ==0, indicating that the CPU is running in real mode, (this is ready to switch to the real mode stage), see 5.6 attached picture;
- 7.3) really jump to Real mode: LABEL_GO_BACK_TO_REAL:JMP 0:label_real_entry; The 0 here is purely a pretence, and I understand that it is just a placeholder, because when the 16-bit code snippet is initialized, its value is set to the CS (segment base) value before the jump, that is, MOV [label_go_back_to_real+3], Ax;
"8" jumps back to the definition of 16-bit code snippet (real mode)
- 8.1) The code is defined at the end of the (5) code area, because they are all operating environments in real mode;
- 8.2) Initialize the value of the register, set the operating environment;
- 8.3) Reset the value of the stack pointer sp, this value as early as the 16-bit code segment initialization, has its value temporarily in the variable, here just restore it to the original value, that is, MOV [spvalueinrealmode], SP;
- 8.4) close A20 Address line, why close, see: http://blog.csdn.net/pacosonswjtu/article/details/48005813
- 8.5) open interrupt;
- 8.6) generates an interrupt signal and returns to Dos;
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Local Descriptor Descriptor function of the LDT + definition + initialization + jump correlation