从实时模式进入保护模式之一

来源:互联网 发布:js array item 编辑:程序博客网 时间:2024/06/07 06:42

主要步骤  

 a.准备GDT

  b.用lgdt加载gdtr

  c.打开A20

  d.置cr0的PE位

  e.跳转,进入保护模式


; ==========================================; pmtest1.asm; 编译方法:nasm pmtest1.asm -o pmtest1.bin; ==========================================%include"pm.inc"; 常量, 宏, 以及一些说明org07c00hjmpLABEL_BEGIN[SECTION .gdt]; GDT;                              段基址,       段界限     , 属性LABEL_GDT:   Descriptor       0,                0, 0           ; 空描述符LABEL_DESC_CODE32: Descriptor       0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段LABEL_DESC_VIDEO:  Descriptor 0B8000h,           0ffffh, DA_DRW     ; 显存首地址; GDT 结束GdtLenequ$ - LABEL_GDT; GDT长度GdtPtrdwGdtLen - 1; GDT界限dd0; GDT基地址; GDT 选择子SelectorCode32equLABEL_DESC_CODE32- LABEL_GDT  ; 32位代码段选择子 SelectorVideoequLABEL_DESC_VIDEO- LABEL_GDT ; 显存选择子; END of [SECTION .gdt][SECTION .s16][BITS16]LABEL_BEGIN:movax, csmovds, axmoves, axmovss, axmovsp, 0100h; 初始化 32 位代码段描述符xoreax, eaxmovax, cs                                  ;指向cs段shleax, 4                                  ;左移4位,扩张为20位地址addeax, LABEL_SEG_CODE32                   ;在cs的基础上加上LABEL_SEG_CODE32的地址偏移movword [LABEL_DESC_CODE32 + 2], ax        ;将ax中的16位段地址移入描述符LABEL_DESC_CODE32对应的2~3字节shreax, 16                                 ;将eax的高16位移入低16位中movbyte [LABEL_DESC_CODE32 + 4], al        ;将al中的8位段地址移入描述符LABEL_DESC_CODE32对应的4字节中                  mov      byte [LABEL_DESC_CODE32 + 7], ah                       ;将ah中的8位段地址移入描述符LABEL_DESC_CODE32对应的7字节中; 为加载 GDTR 作准备xoreax, eaxmovax, dsshleax, 4addeax, LABEL_GDT; eax <- gdt 基地址movdword [GdtPtr + 2], eax; [GdtPtr + 2] <- gdt 基地址; 加载 GDTRlgdt[GdtPtr]                ;将GdtPtr中的GDT界限和GDT基地址加载到寄存器gdtr中; 关中断cli; 打开地址线A20inal, 92horal, 00000010bout92h, al; 准备切换到保护模式moveax, cr0oreax, 1movcr0, eax; 真正进入保护模式jmpdword SelectorCode32:0; 执行这一句会把 SelectorCode32 装入 cs,; 并跳转到 SelectorCode32:0 处,SelectorCode32中段基址指向LABEL_SEG_CODE32偏移为0; END of [SECTION .s16][SECTION .s32]; 32 位代码段. 由实模式跳入.[BITS32]LABEL_SEG_CODE32:movax, SelectorVideomovgs, ax; 视频段选择子(目的)movedi, (80 * 11 + 79) * 2; 屏幕第 11 行, 第 79 列。movah, 0Ch; 0000: 黑底    1100: 红字moval, 'Z'mov[gs:edi], ax; 到此停止jmp$SegCode32Lenequ$ - LABEL_SEG_CODE32; END of [SECTION .s32]

1. 注意程序中使用的全部是偏移地址。注意两种偏移地址

A 对于程序的起始地址来说,所有变量和标签都是相对于整个程序的偏移量
B 对于段中定义的代码,有两种偏移:
相对于程序起始地址的偏移
相对于段标签的偏移。

2.不管是实模式下的物理地址,还是保护模式下的物理地址,反正他们都是物理地址,呵呵,实模式下求的物理地址,也能在保护模式下使用,只是他们不同的是,如何寻址的方式不一样。

3.一个程序中可以包含多个不同位的段,32位或者16位,他们之间也可以互相跳转,只是32位段用的是32位寄存器,16位代码段用的是16位寄存器,如果要在16位段下使用32位寄存器,必须象高级语言中强制类型转换一样,显示的定义 dword


参考:

http://hi.baidu.com/guoxiabin/item/adb915688441f0167ddecc9c