专注于操作系统11之保护模式进阶
来源:互联网 发布:网络预警包括什么 编辑:程序博客网 时间:2024/05/20 14:23
在上一篇中,我们已经完成了从实模式到保护模式的转变,并且还在保护模式下,输出了一个字符,但这在实模式下也能做到。这没体现出保护模式的优势,现在我们要充分利用保护模式的优势,完成向内存大地址(比如5M的地址)的读写(实模式只能寻址1M,保护模式能寻址4G)。下面的代码是参照了《自己动手写操作系统》,但我在这里把它更加的简化了,只保留了我们需要关心的部分,即完成向内存大地址的读写,只需在上一篇代码中加入几行就行了。
;;nasm 2.04 ;;nasm safemodelup.asm -o safemodelup.imgorg 07c00H%macro Descriptor 3 ;定义Descriptor结构体宏dw%2 & 0FFFFh; 段界限 1(2 字节)dw%1 & 0FFFFh; 段基址 1(2 字节)db(%1 >> 16) & 0FFh; 段基址 2(1 字节)dw((%2 >> 8) & 0F00h) | (%3 & 0F0FFh); 属性 1 + 段界限 2 + 属性 2(2 字节)db(%1 >> 24) & 0FFh; 段基址 3(1 字节)%endmacro ; 共 8 字节DA_CEQU98h; 只读代码段的属性值DA_DRWEQU92h; 允许读写的数据段的属性值DA_32EQU4000h;32位段的属性值jmpLABEL_BEGIN ;现在进行第一步:建立GDT表[SECTION .gdt] ;用于放GDT表的段;GDTLABEL_GDT: Descriptor 0,0,0 ;空描述符,当一个任务没有LDT时,会把LDTR清空,这时,LDTR便指向空描述符。LABEL_CODE32: Descriptor 0,SegCode32Len-1,DA_C + DA_32 ; 代码段的描述符LABEL_VIDEO: Descriptor 0B8000h,0ffffh,DA_DRW ;显存的描述符,0b8000h是显存的首地址LABEL_TEXT: Descriptor 0500000h,0ffffh,DA_DRW ;测试的数据段,即我们要读写的数据段(内存大地址)。LABEL_DATA: Descriptor 0,0ffffh,DA_DRW+DA_32 ;存放数据的段,即我们要将这里的数据写到内存大地址。;GDT 结束GdtLenth equ $ - LABEL_GDT ;计算GDT表的长度GdtPtr dw GdtLenth - 1 ; 准备存入GDTR的信息 dd 0 ; 用于存放GDT表的物理地址,后面会计算;GDT选择子SelectorCode32 equ LABEL_CODE32 - LABEL_GDT ;代码段的选择子SelectorVideo equ LABEL_VIDEO - LABEL_GDT ;显存所在段的选择子SelectorData equ LABEL_DATA - LABEL_GDT ;数据段的选择子SelectorText equ LABEL_TEXT - LABEL_GDT ;测试数据段的选择子;[SECTION .gdt]结束[SECTION .data] ;数据段,为了简单,我们只保存一个字符LABEL_SEG_DATA:db 'A';[SECTION .data]结束[SECTION .s16][BITS 16];目标处理器模式LABEL_BEGIN:mov ax,csmov ds,axmov es,axmov ss,axmov sp,0100h;初始化数据段的描述符xor eax,eax ; 同或运算,这里是将eax清零mov ax,csshl eax,4 ;左移四位,相当于乘以16,实模式下计算物理地址add eax,LABEL_SEG_DATA ;eax中为32位段的物理地址mov word [LABEL_DATA + 2],ax ;将32位段的物理地址存入段的描述符中shr eax,16mov byte [LABEL_DATA + 4],almov byte [LABEL_DATA + 7],ah;初始化32位段的描述符xor eax,eax ; 同或运算,这里是将eax清零mov ax,csshl eax,4 ;左移四位,相当于乘以16,实模式下计算物理地址add eax,LABEL_SEG_CODE32 ;eax中为32位段的物理地址mov word [LABEL_CODE32 + 2],ax ;将32位段的物理地址存入段的描述符中shr eax,16mov byte [LABEL_CODE32 + 4],almov byte [LABEL_CODE32 + 7],ah;计算GDT表的物理地址,将GDT表的物理地址信息存入GdtPtr中xor eax,eaxmov ax,csshl eax,4add eax,LABEL_GDTmov dword [GdtPtr + 2],eax;现在进行第二步:将GDT表的信息加载到GDTR中lgdt [GdtPtr] ;装载GDTR;关中断cli;现在进行第三步:打开地址线in al,92hor al,00000010bout 92h,al;现在进行第四步:置PE为1,表示CPU处于保护模式下mov eax,cr0or eax,1mov cr0,eax;现在进入第五步:跳到保护模式的代码jmp dword SelectorCode32:0 ;这里将SelectorCode32存入CS中作为选择子;[SECTION .s16] 结束;保护模式下的代码,32位代码[SECTION .s32][BITS 32] LABEL_SEG_CODE32:mov ax,SelectorVideo ;视频选择子,用于找到显存段的描述符mov gs,ax mov ax,SelectorTextmov es,axmov ax,SelectorDatamov ds,axmov edi,(80 * 10 + 0)*2 ;屏幕的第10行,第0列mov ah,0Chmov al,[es:0]mov [gs:edi],ax ;将测试段(内存大地址)的第一个字符输出到屏幕,在虚拟机中测试时输出为空。mov al,[ds:0] ;向测试段(内存大地址)写入字符(此字符为数据段的第一个字符,这里为‘A’)mov [es:0],almov edi,(80 * 11 + 0)*2 ;屏幕的第11行,第0列mov ah,0Chmov al,[es:0]mov [gs:edi],ax ;再次将测试段(内存大地址)的第一个字符输出到屏幕,看写入是否成功jmp $SegCode32Len equ $ - LABEL_SEG_CODE32 ;计算32位代码段的长度times 510-($-$) db 0dw 0aa55H
将编译后的文件,safemodelup.img 装入虚拟机
下面是运行的结果图
- 专注于操作系统11之保护模式进阶
- 专注于操作系统7之初识保护模式
- 专注于操作系统8之保护模式基础知识a
- 专注于操作系统9之保护模式基础知识b
- 专注于操作系统10之走进保护模式
- 专注于操作系统21之分页进阶
- 专注于操作系统23之中断进阶
- 专注于操作系统29之从loader进入保护模式并分页
- 专注于操作系统12之回到实模式
- 专注于操作系统4之引导程序
- 专注于操作系统5之引导程序代码
- 专注于操作系统13之LDT
- 专注于操作系统15之特权级
- 专注于操作系统19之走进分页
- 专注于操作系统20之启动分页
- 专注于操作系统22之中断
- 专注于操作系统1之操作系统的从无到有a
- 专注于操作系统2之操作系统的从无到有b
- 第2周上机任务
- 原来PATH的菜单效果如此简单。布局+TranslateAnimation搞定 and 高仿小米launcher(ZAKER)跨屏拖动item 02-29最新更新
- SVM学习资料
- 第二周
- [Android实例] ViewPager多页面滑动切换以及动画效果
- 专注于操作系统11之保护模式进阶
- Ubuntu下arm-linux-gdb+gdbserver的编译及安装
- android在命令提示符下查看sqlite数据
- 浅谈Intel QPI的MESIF协议和Home,Source Snoop
- Servlet简介 以及servlet一些细节 servletconfig
- C程序为例内存分布详解
- 查看环境变量的方法
- 在二叉树中删除一个节点——归并删除法
- 深入理解Lustre文件系统-第11篇 Lustre一般化文件系统封装层:fsfilt