pmtest5a.asm

This code is used to jump from high-privilege level 0 to low-privilege level 3, which is implemented by the ret instruction. Before the ret instruction is executed, the target code cs eip ss and esp should be prepared in the stack.
This is implemented by the push instruction

;======================================
;pmtest5.asm
;编译方法:nasm pmtest5.asm -o pmtest5.bin
;======================================
%include "pm.inc";  常量,宏 以及一些说明
;org 07c00h
org 0100h
    jmp LABEL_BEGIN

[SECTION .gdt]
;GDT                 段基址  段界限   属性

LABEL_GDT:  Descriptor  0,   0,         0 ;空描述符
LABEL_DESC_NORMAL: Descriptor   0,   0ffffh,    DA_DRW ;  NORMAL描述符
LABEL_DESC_CODE32: Descriptor   0,  SegCode32Len - 1, DA_C + DA_32;  
LABEL_DESC_CODE16: Descriptor   0,  0ffffh,     DA_C;  
LABEL_DESC_DATA: Descriptor     0,  DataLen-1,  DA_DRW; Data
LABEL_DESC_STACK: Descriptor    0,  TopOfStack,     DA_DRWA+DA_32;   
LABEL_DESC_VIDEO : Descriptor   0B8000h, 0ffffh,    DA_DRW+DA_DPL3;  显存首地址
LABEL_DESC_LDT  : Descriptor    0,  LDTLen - 1, DA_LDT;  LDT
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1,   DA_C + DA_32
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3
LABEL_DESC_STACK3: Descriptor 0, TopOfStack3,       DA_DRWA+DA_32+DA_DPL3


;门 入口 门描述符只描述一个入口 代码的段还是由GDT定义

LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 0, DA_386CGate+DA_DPL0

GdtLen  equ  $-LABEL_GDT  ;GDT长度
GdtPtr  dw   GdtLen - 1  ;GDT 界限
dd 0  ; GDT基地址
;GdtPtr也是一个数据结构  前2字节是GDT界限  后4字节是GDT基地址

;GDT 选择子
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
SelectorStack   equ     LABEL_DESC_STACK - LABEL_GDT
SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT
SelectorVideo   equ LABEL_DESC_VIDEO - LABEL_GDT

SelectorCodeDest equ        LABEL_DESC_CODE_DEST - LABEL_GDT
SelectorCallGateTest equ    LABEL_CALL_GATE_TEST - LABEL_GDT
SelectorCodeRing3 equ       LABEL_DESC_CODE_RING3- LABEL_GDT + SA_RPL3
SelectorStack3    equ       LABEL_DESC_STACK3- LABEL_GDT + SA_RPL3

; END of [SECTION .gdt]



[SECTION .data1]  ;数据段
ALIGN 32
[BITS 32]
LABEL_DATA:
SPValueInRealMode   dw  0;  字符串
PMMessage:  db "In Protect Mode now.^_^", 0;  在保护模式中显示
OffsetPMMessage equ PMMessage - $$
StrTest:	db "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0;
OffsetStrTest	equ StrTest - $$
DataLen     equ $-LABEL_DATA
;end of[section.data1]


;全局堆栈段
[SECTION .gs]
ALIGN   32
[BITS 32]
LABEL_STACK:
    times 512 db 0
TopOfStack equ  $-LABEL_STACK-1

;end of [section.gs]


; 堆栈段ring3
[SECTION .s3]
ALIGN   32
[BITS 32]
LABEL_STACK3:
    times 512 db 0
TopOfStack3     equ $ - LABEL_STACK3 - 1
; END of [SECTION .s3]


;这是一个16位代码段 这个程序修改了gdt中的一些值 然后执行跳转到第三个section
[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

    ;初始化16位的代码段描述符
    xor eax, eax
    mov     ax, cs
    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

    ;初始化32位代码段描述符
    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

    ; 初始化数据段描述符  
        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  

        ; 初始化堆栈段描述符  
        xor eax, eax  
        mov ax, ds  
        shl eax, 4  
        add eax, LABEL_STACK  
        mov word [LABEL_DESC_STACK + 2], ax  
        shr eax, 16  
        mov byte [LABEL_DESC_STACK + 4], al  
        mov byte [LABEL_DESC_STACK + 7], ah  

    ;初始化LDT在GDT中的描述符
    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  

    ; 初始化 LDT 中的描述符  
        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

    ;初始化 测试调用门的代码段描述符
        xor eax, eax  
        mov ax, cs  
        shl eax, 4  
        add eax, LABEL_SEG_CODE_DEST  
        mov word [LABEL_DESC_CODE_DEST + 2], ax  
        shr eax, 16  
        mov byte [LABEL_DESC_CODE_DEST + 4], al  
        mov byte [LABEL_DESC_CODE_DEST + 7], ah

    ; 初始化堆栈段描述符(Ring3)
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_STACK3
    mov word [LABEL_DESC_STACK3 + 2], ax
    shr eax, 16
    mov byte [LABEL_DESC_STACK3 + 4], al
    mov byte [LABEL_DESC_STACK3 + 7], ah


    ; 初始化Ring3描述符
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_CODE_RING3
    mov word [LABEL_DESC_CODE_RING3 + 2], ax
    shr eax, 16
    mov byte [LABEL_DESC_CODE_RING3 + 4], al
    mov byte [LABEL_DESC_CODE_RING3 + 7], ah



    ;为加载GDTR作准备
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_GDT; eax <- gdt基地址
    mov     dword [GdtPtr + 2], eax; [GdtPtr + 2] <- gdt 基地址

    ;加载GDTR
    lgdt    [GdtPtr]

    ;关中断
    cli

    ;打开地址线A20
    in  al, 92h
    or  al, 00000010b
    out 92h, al

    ;准备切换到保护模式
    mov eax, cr0
    or  eax, 1
    mov cr0, eax

    ;真正进入保护模式
    jmp dword   SelectorCode32:0 ;  执行这句会把SelectorCode32装入CS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LABEL_REAL_ENTRY:   ;从保护模式跳回到实模式就到了这里
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax

    mov     sp, [SPValueInRealMode]   ;指针调到了堆栈中  返回到实模式

    in  al, 92h
    and al, 11111101b;  关闭A20地址线
    out 92h, al

    sti;  开中断

    mov ax, 4c00h;
    int 21h;    回到dos
;end of section .s16




[SECTION .s32]
[BITS 32]

LABEL_SEG_CODE32:
    mov ax, SelectorData
    mov ds, ax;         数据段选择子

    mov ax, SelectorVideo;  视频段选择子
    mov gs, ax

    mov ax, SelectorStack
    mov ss, ax;         堆栈段选择子

    mov esp, TopOfStack

    ;下面显示一个字符串
    mov ah, 0Ch;        0000黑底 1100红字
    xor esi, esi
    xor edi, edi
    mov esi, OffsetPMMessage;   源数据偏移
    mov edi, (80*10 + 10) * 2;  目的数据偏移  屏幕第10行第0列
    cld             ;告诉字符串向前移动

.1:
    lodsb       ;将字符串中的si指针所指向的一个字节装入al中
    test    al, al  ;判断al是否为空  为空跳转到2
    jz  .2
    mov [gs:edi], ax ;不为空显示当前字符
    add edi, 2    ;edi加二  
    jmp .1

.2: ;当第一条字符串显示完毕
    call    DispReturn      ;回车 换行


    push    SelectorStack3     ;将ss  新堆栈段push
    push    TopOfStack3        ;将esp 新堆栈指针push
    push    SelectorCodeRing3  ;将cs 新的代码段 push
    push    0                  ;将eip push  即在新的代码段的最开始执行程序
    retf   ;将堆栈中的四个数据pop到相应的寄存器中 完成跳转

    call    SelectorCallGateTest:0  ;测试调用门

    ; Load ldt
    mov ax, SelectorLDT
    lldt    ax
    jmp SelectorLDTCodeA:0   ; 跳入局部任务

;-------------------------------------------------------------------------
DispReturn:
    push    eax
    push    ebx
    mov eax, edi
    mov bl, 160
    div bl
    and eax, 0FFh

    inc eax
    mov bl, 160
    mul bl
    mov edi, eax
    pop ebx 
    pop eax

    ret
;disreturn 结束-------------------------------------------

SegCode32Len    equ $-LABEL_SEG_CODE32
;end of section .s32


[SECTION .sdest]; 调用门目标段
[BITS 32]
LABEL_SEG_CODE_DEST:
    ;jmp    $
    mov ax, SelectorVideo
    mov gs, ax  
    mov edi, (80*11+0)*2
    mov ah, 0Ch
    mov al, 'G'
    mov [gs:edi], ax
    retf

SegCodeDestLen equ  $-LABEL_SEG_CODE_DEST

;16位的代码段 由32位代码段跳入  跳出后到实模式
[SECTION .s16code]
ALIGN 32
[BITS 16]
LABEL_SEG_CODE16:

    ;跳回实模式
    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;    段地址会在程序开始处被设置为正确的值

Code16Len equ $ - LABEL_SEG_CODE16

;end of section .s16code

;LDT
[SECTION .ldt]
ALIGN   32
LABEL_LDT:
;               段基址 段界限     属性
LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1,   DA_C + DA_32

LDTLen  equ $ - LABEL_LDT

;ldt 选择子
SelectorLDTCodeA    equ LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL
; end of section .ldt

;codeA  (ldt  32位代码段)
[SECTION .la]
ALIGN   32
[BITS   32]
LABEL_CODE_A:
    mov ax, SelectorVideo
    mov gs, ax

    mov edi, (80 * 12 + 0) * 2 ;  
    mov ah, 0Ch
    mov al, 'Z'
    mov [gs:edi], ax

    jmp SelectorCode16:0
CodeALen    equ $ - LABEL_CODE_A
;end of section .la


; CodeRing3
[SECTION .ring3]
ALIGN   32
[BITS 32]
LABEL_CODE_RING3:
    mov ax, SelectorVideo
    mov gs, ax

    mov edi, (80 * 14 + 0) * 2
    mov ah, 0Ch
    mov al, '3'
    mov [gs:edi], ax

    jmp $
SegCodeRing3Len equ $ - LABEL_CODE_RING3
; END of [SECTION .ring3]

Guess you like

Origin blog.csdn.net/u012323667/article/details/79376036