pmtest5.asm

0特権レベルから3特権レベルジャンプpmtest5a.asmてなされたものであり、RETは、次いで、プッシュCS EIP SSによってコードセグメント特権レベルLABEL_DESC_CODE_RING3 3にジャンプし、ESP 3を印刷します

特権レベル3からゲートを呼び出すこのとき、ゲートのDPLが3であり、特権レベル3にアクセスできることを確認する必要があります。このとき、ゲートのコードセグメントのLABEL_CALL_GATE_TESTにジャンプします。

このゲートはSelectorCodeDestセレクターを指しているため、プログラム
はコードセグメントLABEL_DESC_CODE_DESTにジャンプします。これは特権レベル0のコードセグメントです。したがって、プログラムは低特権レベルから高特権レベルへのジャンプを実現します。このコードセグメントの最後にあるretfは、コードを返すことができます。特権レベル3、
印刷G

このretfの前にldtにロードされたコードを追加し、ローカルタスクを呼び出して、実際のモードに戻します。

;======================================
;pmtest4.asm
;编译方法:nasm pmtest4.asm -o pmtest4.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
LABEL_DESC_TSS: Descriptor 0, TSSLen-1, DA_386TSS

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

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

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 + SA_RPL3
SelectorCodeRing3 equ       LABEL_DESC_CODE_RING3- LABEL_GDT + SA_RPL3
SelectorStack3    equ       LABEL_DESC_STACK3- LABEL_GDT + SA_RPL3
SelectorTSS equ         LABEL_DESC_TSS - LABEL_GDT



; 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]


;TSS
[SECTION .tss]
ALIGN 32
[BITS 32]
LABEL_TSS:
    DD  0       ;BACK
    DD  TopOfStack  ;0级堆栈
    DD  SelectorStack   ;
    DD  0       ;1级堆栈
    DD  0       ;
    DD  0       ;2级堆栈
    DD  0       ;
    DD  0       ;CR3
    DD  0       ;EIP
    DD  0       ;EFLAGS
    DD  0       ;EAX
    DD  0       ;ECX
    DD  0       ;EDX
    DD  0       ;EBX
    DD  0       ;ESP
    DD  0       ;EBP
    DD  0       ;ESI
    DD  0       ;EDI
    DD  0       ;ES
    DD  0       ;CS
    DD  0       ;SS     
    DD  0       ;DS
    DD  0       ;FS
    DD  0       ;GS
    DD  0       ;LDT
    DW  0       ;调试陷阱标志
    DW  $-LABEL_TSS + 2  ;IO位图基址
    DB  0ffh        ;IO位图结束标示
TSSLen  equ $-LABEL_TSS




;这是一个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


    ; 初始化TSS描述符  
        xor eax, eax  
        mov ax, ds  
        shl eax, 4  
        add eax, LABEL_TSS  
        mov word [LABEL_DESC_TSS + 2], ax  
        shr eax, 16  
    mov byte [LABEL_DESC_TSS + 4], al  
    mov byte [LABEL_DESC_TSS + 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      ;回车 换行

    mov ax, SelectorTSS
    ltr ax

    push    SelectorStack3
    push    TopOfStack3
    push    SelectorCodeRing3
    push    0
    retf

;因为跳转到特权级三  相当于任务已经切换 所以下面四行的代码执行不到了
;调用门  需要放到ring3  的代码底部   当打印出3  之后  开始调用门
;因为此时CPL是3  为了能访问到调用门  需要将调用门的 DPL  RPL也设置为3
    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

    ;load LDT  new  add
    mov ax, SelectorLDT
    lldt    ax
    jmp SelectorLDTCodeA:0

    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

    call    SelectorCallGateTest:0       ;从3特权级进入门   门中是ldt  Z

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

おすすめ

転載: blog.csdn.net/u012323667/article/details/79384486