; ==========================================
; Pmtest3.asm
; Compilation method: Nasm Pmtest3.asm-o pmtest3.com
; ==========================================
%include "Pm.inc"; constants, macros, and some instructions
Org 0100h
JMP Label_begin
[section. GDT]
; GDT
; Segment base, segment bounds, properties
Label_gdt:descriptor 0, 0, 0; NULL descriptor
Label_desc_normal:descriptor 0, 0FFFFH, DA_DRW; Normal Descriptor
Label_desc_code32:descriptor 0, Segcode32len-1, Da_c + da_32; Non-Uniform code snippet, 32
Label_desc_code16:descriptor 0, 0FFFFH, Da_c; Non-Uniform code snippet, 16
Label_desc_data:descriptor 0, DataLen-1, DA_DRW+DA_DPL1; Data
Label_desc_ldt1:descriptor 0, Ldtlen1-1, Da_ldt; LDT1
Label_desc_ldt2:descriptor 0, ldtlen2-1, Da_ldt; LDT1
Label_desc_video:descriptor 0b8000h, 0FFFFH, DA_DRW; Memory first Address
; GDT End
Gdtlen equ $-LABEL_GDT; GDT length
Gdtptr DW GdtLen-1; GDT boundaries
DD 0; GDT Base Address
; GDT Select Child
Selectornormal equ LABEL_DESC_NORMAL-LABEL_GDT
SELECTORCODE32 equ LABEL_DESC_CODE32-LABEL_GDT
SELECTORCODE16 equ LABEL_DESC_CODE16-LABEL_GDT
Selectordata equ LABEL_DESC_DATA-LABEL_GDT
SelectorLDT1 equ LABEL_DESC_LDT1-LABEL_GDT
SelectorLDT2 equ LABEL_DESC_LDT2-LABEL_GDT
Selectorvideo equ LABEL_DESC_VIDEO-LABEL_GDT
; END of [section. GDT]
[section. Data1]; Data segment
ALIGN 32
[BITS 32]
Label_data:
Spvalueinrealmode DW 0
; String
Pmmessage:db "in Protect Mode now. ^-^ ", 0; Show this string after entering protected mode
Offsetpmmessage equ Pmmessage-$$
Datalen equ $-Label_data
; END of [section. Data1]
[section. S16]
[BITS 16]
Label_begin:
MOV ax, CS
MOV ds, ax
MOV es, ax
mov ss, ax
mov sp, 0100h
mov [label_go_back_to_real+3], ax
mov [Spvalueinrealmode], SP
; Initializing a 16-bit code snippet descriptor
MOV ax, CS
movzx eax, Ax
SHL EAX, 4
add eax, Label_seg_code16
mov Word [Label_desc_code16 + 2], ax
shr eax, 16
mov byte [Label_desc_code16 + 4], AL
mov byte [Label_desc_code16 + 7], ah
; Initializing a 32-bit code snippet 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
; Initialize Data segment Descriptor
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_data
mov Word [Label_desc_data + 2], ax
shr eax, 16
mov byte [Label_desc_data + 4], AL
mov byte [label_desc_data + 7], ah
; Initialize LDT1 descriptor in GDT
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, LABEL_LDT1
mov Word [label_desc_ldt1 + 2], ax
shr eax, 16
mov byte [Label_desc_ldt1 + 4], AL
mov byte [label_desc_ldt1 + 7], ah
; Initialize LDT2 descriptor in GDT
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, LABEL_LDT2
mov Word [label_desc_ldt2 + 2], ax
shr eax, 16
mov byte [Label_desc_ldt2 + 4], AL
mov byte [label_desc_ldt2 + 7], ah
; Initialize descriptor A in LDT1
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_code_a
mov Word [Label_ldt1_desc_codea + 2], ax
shr eax, 16
mov byte [Label_ldt1_desc_codea + 4], AL
mov byte [Label_ldt1_desc_codea + 7], ah
; Initialize descriptor B in LDT2
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_code_b
mov Word [Label_ldt2_desc_codeb + 2], ax
shr eax, 16
mov byte [Label_ldt2_desc_codeb + 4], AL
mov byte [label_ldt2_desc_codeb + 7], ah
; Initialize descriptor C in LDT2
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_code_c
mov Word [Label_ldt2_desc_codec + 2], ax
shr eax, 16
mov byte [Label_ldt2_desc_codec + 4], AL
mov byte [Label_ldt2_desc_codec + 7], ah
; Preparing to load GDTR
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
; 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
mov eax, CR0
or EAX, 1
mov cr0, eax
; Real access to Protected mode
JMP DWORD selectorcode32:0; Executing this sentence will load the SelectorCode32 into CS and jump to code32selector:0 Secretariat
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Label_real_entry:; Jump back from Protected mode to real mode.
MOV ax, CS
MOV ds, ax
MOV es, ax
mov ss, ax
mov sp, [Spvalueinrealmode]
In Al, 92h;
and Al, 11111101b; Close A20 Address Line
Out 92h, AL;
STI; Open Interrupt
mov ax, 4c00h;
int 21h; Back to DOS
; END of [section. S16]
[section. S32]; 32-bit code snippet. Jumped in by real mode.
[BITS 32]
LABEL_SEG_CODE32:
mov ax, selectordata
mov ds, ax; Data Segment Selection Sub
mov ax, selectorvideo
mov gs, AX; Video Segment Selector
; A string is shown below
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
XOR esi, ESI
XOR EDI, EDI
mov esi, offsetpmmessage; Source Data Offset
mov edi, (80 * 10 + 0) * 2; Destination data offset. screen 10th, column No. 0.
Cld
.1:
Lodsb
Test Al, AL
JZ. 2
mov [Gs:edi], ax
Add EDI, 2
JMP. 1
.2:; Display complete
; Load LDT
mov ax, SelectorLDT1
Lldt Ax
JMP selectorldt1codea:0; Jump into a local task
Segcode32len equ $-label_seg_code32
; END of [section. S32]
; 16-bit code snippet. Jump from a 32-bit code snippet and jump back to real mode
[section. S16code]
ALIGN 32
[BITS 16]
LABEL_SEG_CODE16:
; To jump 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
; END of [section. S16code]
; LDT1
[section. Ldt1]
ALIGN 32
LABEL_LDT1:
Label_ldt1_desc_codea:descriptor 0, CodeALen-1, Da_c + da_32; Code, 32-bit
LDTLEN1 equ $-LABEL_LDT1
Selectorldt1codea equ Label_ldt1_desc_codea-label_ldt1 + sa_til
; END of [section. Ldt1]
; LDT2
[section. LDT2]
ALIGN 32
LABEL_LDT2:
Label_ldt2_desc_codeb:descriptor 0, CodeBLen-1, Da_c + da_32; Code, 32-bit
Label_ldt2_desc_codec:descriptor 0, CodeCLen-1, Da_c + da_32; Code, 32-bit
LDTLen2 equ $-LABEL_LDT2
Selectorldt2codeb equ LABEL_LDT2_DESC_CODEB-LABEL_LDT2 + sa_til
Selectorldt2codec equ LABEL_LDT2_DESC_CODEC-LABEL_LDT2 + sa_til
; END of [section. LDT2]
; Codea (LDT, 32-bit code snippet)
[Section. La]
ALIGN 32
[BITS 32]
Label_code_a:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
mov edi, (80 * 12 + 0) * 2; screen 10th, column No. 0.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' A '
mov [Gs:edi], ax
MOV ax,selectorldt2
Lldt Ax
JMP selectorldt2codeb:0; To jump to a different LDT, load the target LDT first
Codealen equ $-label_code_a
; END of [section. La]
; Codeb (LDT, 32-bit code snippet)
[section. lb]
ALIGN 32
[BITS 32]
Label_code_b:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
mov edi, (80 * 12 + 4) * 2; Screen 10th, column 4th.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' B '
mov [Gs:edi], ax
JMP selectorldt2codec:0; Different sections of the same LDT can jump directly.
Codeblen equ $-Label_code_b
; END of [section. lb]
; CodeC (LDT, 32-bit code snippet)
[section. LC]
ALIGN 32
[BITS 32]
Label_code_c:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
mov edi, (80 * 12 + 8) * 2; Screen 10th, column 8th.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' C '
mov [Gs:edi], ax
; Ready to jump back to real mode via 16-bit code segment
JMP selectorcode16:0
Codeclen equ $-Label_code_c
; END of [section. LC]