pmtest4.asm

;======================================
;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_TEST: Descriptor    0500000h, 0ffffh,   DA_DRW;  
LABEL_DESC_VIDEO : Descriptor   0B8000h, 0ffffh,    DA_DRW;  显存首地址
LABEL_DESC_LDT  : Descriptor    0,  LDTLen - 1, DA_LDT;  LDT
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1,   DA_C + DA_32
;门 入口 门描述符只描述一个入口 代码的段还是由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
;SelectorTest   equ     LABEL_DESC_TEST - 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
; 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]




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


    ;为加载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      ;回车 换行

;   call    Selector:0  ;测试调用门
    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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值