操作系统实验三:实模式与保护模式间自由跳转
2010-01-24 02:54
288 查看
此次实验,是在 操作系统实验二:从实模式跳转到保护模式 基础上的进一步实验。实验实现的内容很简单,一开始进入实模式,然后跳转到保护模式,然后再跳转回实模式,然后再跳转到保护模式,如此不断循环。
从实模式调转到保护模式步骤:
1.准备好GDT
2.使用lgdt指令加载gdtr
3.打开地址线A20
4.设置cr0的PE位为1
5.使用cli指令关闭中断
6.根据GDT选择子跳转到32位代码段,此时进入保护模式
从保护模式转到实模式调步骤:
1.跳转到16位代码段
2.加载适合的GDT选择子到有关段寄存器
3.设置cr0的PE位为0
4.跳转到16位代码段,此时进入实模式
5.关闭地址线A20
6.使用sti指令打开中断
实验流程简要说明:
(pm16.c部分)
1.清屏
2.跳到第9步
3.加载适合的描述符选择子到有关段寄存器
4.设置cr0的PE位为0
5.一个跳转,真正回到实模式
6.关闭 A20 地址线
7.开中断
8.调用延时函数
9.显示字符串This is real model!
10.设置下一次显示字符串的位置
11.加载 GDTR
12.关中断
13.打开地址线A20
14.置cr0的PE位为1
15.跳转到32位代码段,进入保护模式
(pm32.c部分)
16.调用延时函数
17.显示字符串I am now in protect model^_^
18.保存最后的光标位置
19.跳转到(pm16.c)第3步
实验代码如下:
code:run.c(请参考 操作系统实验二:从实模式跳转到保护模式 中的run.c代码)
code:pm.h
code:pm16.c
code:pm32.c
想要实验以上代码的朋友请注意:
1.到杨晓兵大大的博客上下载安装yc09,安装只需一分钟左右。
2.将操作系统实验二:从实模式跳转到保护模式 中的run.c代码,以及此次试验中的pm.h、pm16.c、pm32.c代码拷贝到某个实验用的文件夹内。
3.在YC09/example文件夹内找到bochs.exe、BIOS-bochs-latest、VGABIOS-elpin-2.40、x11-pc-us.map四个文件拷贝到试验用的文件夹内。
4.使用yc09编译运行run.c
从实模式调转到保护模式步骤:
1.准备好GDT
2.使用lgdt指令加载gdtr
3.打开地址线A20
4.设置cr0的PE位为1
5.使用cli指令关闭中断
6.根据GDT选择子跳转到32位代码段,此时进入保护模式
从保护模式转到实模式调步骤:
1.跳转到16位代码段
2.加载适合的GDT选择子到有关段寄存器
3.设置cr0的PE位为0
4.跳转到16位代码段,此时进入实模式
5.关闭地址线A20
6.使用sti指令打开中断
实验流程简要说明:
(pm16.c部分)
1.清屏
2.跳到第9步
3.加载适合的描述符选择子到有关段寄存器
4.设置cr0的PE位为0
5.一个跳转,真正回到实模式
6.关闭 A20 地址线
7.开中断
8.调用延时函数
9.显示字符串This is real model!
10.设置下一次显示字符串的位置
11.加载 GDTR
12.关中断
13.打开地址线A20
14.置cr0的PE位为1
15.跳转到32位代码段,进入保护模式
(pm32.c部分)
16.调用延时函数
17.显示字符串I am now in protect model^_^
18.保存最后的光标位置
19.跳转到(pm16.c)第3步
实验代码如下:
code:run.c(请参考 操作系统实验二:从实模式跳转到保护模式 中的run.c代码)
code:pm.h
]//文件:pm.h //功能:pm16.c与pm32.c的公共头文件 //运行:run.exe自动会编译pm16.c与pm32.c然后生成img并调用Bochs运行此程序 //提示:请先用yc09编译run.c文件,生成run.exe程序 // 之后修改pm16.c与pm32.c中代码,可直接运行run.exe查看效果 //作者:miao //时间:2010-1-24 //定义GDT属性 #define DA_32 0x4000 //32位段 #define DA_DRW 0x92 //存在的可读写数据段属性值 #define DA_CR 0x9A //存在的可执行可读代码段属性值 //GDT 选择子,根据pm16.c中的GDT界限设置偏移量值 #define SelectorNormal 8*1 //返回实模式需要用到的选择子 #define SelectorSode32 8*2 //指向32位段处 #define SelectorVideo 8*3 //指向显存首地址 #define SelectorSode16 8*4 //指向16位代码段 #define SelectorData32 8*5 //指向32位段处 typedef unsigned int t_32; //4字节 typedef unsigned short t_16; //2字节 typedef unsigned char t_8; //1字节 typedef int t_bool;//4字节 typedef unsigned int t_port;//4字节 //存储段描述符/系统段描述符 struct DESCRIPTOR //共 8 个字节 { t_16 limit_low; //Limit 2字节 t_16 base_low; //Base 2字节 t_8 base_mid; //Base 1字节 t_8 attr1; //P(1) DPL(2) DT(1) TYPE(4) 1字节 t_8 limit_high_attr2; //G(1) D(1) 0(1) ***L(1) LimitHigh(4) 1字节 t_8 base_high; //Base 1字节 }; #define Descriptor(bas,len,attr) { (len) & 0xffff, / (bas) & 0xffff, / ((bas)>>16)&0xff, / (attr) & 0xff, / (((attr)>>8) &0xf0) + (((len)>>16) & 0x0f), / ((bas) >> 24) & 0xff } /
code:pm16.c
]//文件:pm16.c //功能:设置GDT,在GDT中初始化32位代码段,然后切换到保护模式,跳转到32位代码段 // 当从32位代码段保护模式跳转回来后,切换到实模式,显示字符串,再切换到保护模式 //说明:16位部分引导程序放在镜像引导扇区的前半部分,0~255字节中,程序大小不能超过这个限制 //运行:run.exe自动会编译pm16.c与pm32.c然后生成img并调用Bochs运行此程序 //提示:请先用yc09编译run.c文件,生成run.exe程序 // 之后修改pm16.c与pm32.c中代码,可直接运行run.exe查看效果 // 若在_BackToRealModel标签前添加或删除代码,会导致保护模式无法正确跳转回来, // 此时需要反汇编pm16.c的代码,查找到_BackToRealModel所在地址,修改pm32.c中的跳转值 //作者:miao //时间:2010-1-24 #define YCBIT 16 //告诉编译器,以16位格式编译程序 #define YCORG 0x7c00 //告诉编译器,在7c00处加载程序 #include "pm.h" //GDT界限 DESCRIPTOR label_gdt[] = { // 段基址 段界限 属性 Descriptor(0, 0, 0), Descriptor(0, 0xfffff, DA_DRW), //Normal 描述符,返回实模式前要加载的 Descriptor(0x7d00, 0xfffff, DA_CR | DA_32), //32位代码段(pm32.c),可执行可读 Descriptor(0xb8000, 0xffff, DA_DRW), //显存地址段,可读可写 Descriptor(0x7c00, 0xfffff, DA_CR), //16位代码段(pm16.c),可执行可读 Descriptor(0x7d00, 0xfffff, DA_DRW | DA_32), //令32位代码段(pm32.c)的变量可以读写 }; #pragma pack(1) struct GDT_PTR { unsigned short size; void *addr; }; #pragma pack() GDT_PTR GdtPtr = { sizeof(label_gdt), (char*)label_gdt}; //段界限,基地址 #define MsgLngth 24 //串长度 char Msg[MsgLngth] = "This is real model! "; char row = 0; //行数 char line = 0; //列数 asm void Delay(); //延时函数 asm void main() { mov ax, cs mov ds, ax mov es, ax //清屏 mov ah, 06h //屏幕初始化或上卷 mov aL, 00h //AH = 6, AL = 0h mov bx, 1110h //蓝色底色 mov cx, 0 //左上角: (0, 0) mov dl, 4fh //最后一列 mov dh, 1fh //最后一行(右下角) int 10h //显示中断 jmp _Start16 //跳过下面从保护模式切换到实模式的代码 //保护模式代码执行完后直接跳转到此处 _BackToRealModel: mov ax, SelectorNormal //加载适合的描述符选择子到有关段寄存器 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax //准备切换到实模式,清除cr0的PE位 mov eax, cr0 and al, 11111110b mov cr0, eax jmp 0:_RealEntry //这一跳,段地址被设置成正确的值,真正回到实模式 _RealEntry: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, YCORG //关闭 A20 地址线 in al, 92h and al, 11111101b out 92h, al sti //开中断 call Delay //调用延时函数 _Start16: mov ax, &Msg mov bp, ax //es:bp=串地址 mov ah, 13h //AH:13显示字符串 mov al, 1h //AH = 13, AL = 01h mov bx, 0014h //页号为0(BH = 0) 蓝底红字(BL = 14h) mov cx, MsgLngth //CX = 串长度 mov dl, line //起始列 mov dh, row //起始行 int 10h //显示中断 add line, MsgLngth //下一次显示字符串是当前列的后MsgLngth - 3列 cmp line, 0x50 - MsgLngth //判断列数是否过大 jng _LineNotEnd mov line, 0 //列数过大,列数归零 add row, 1 //行数加一 cmp row, 24 jge _DeadLoop //行数超过24行,跳转到一个死循环 _LineNotEnd: lgdt GdtPtr //加载 GDTR cli //关中断 //打开地址线A20 in al, 92h or al, 00000010b out 92h, al //准备切换到保护模式,置cr0的PE位为1 mov eax, cr0 or eax, 1 mov cr0, eax //真正进入保护模式 jmp dword SelectorSode32:0x0 //死循环 _DeadLoop: jmp _DeadLoop } //延时函数 asm void Delay() { mov ax, 0x0 _Loop1: inc ax mov cx, 0xFFFF _Loop2: loop _Loop2 cmp ax, 0xFF jne _Loop1 ret }
code:pm32.c
]//文件:pm16.c //功能:保护模式下32位代码段,功能为显示一个字符串,然后跳转到16位代码段(pm16)切换到实模式 //说明:32位部分引导程序放在镜像引导扇区的后半部分,256~509字节中,程序大小不能超过这个限制 //运行:run.exe自动会编译pm16.c与pm32.c然后生成img并调用Bochs运行此程序 //提示:请先用yc09编译run.c文件,生成run.exe程序 // 之后修改pm16.c与pm32.c中代码,可直接运行run.exe查看效果 //作者:miao //时间:2010-1-24 #define YCBIT 32 //告诉编译器,以32位格式编译程序 #define YCORG 0x0 //必须定义一个值 #include "pm.h" char Msg1[] = "I am now in protect model^_^"; int printPlace = ((80 * 1 + 0) * 2); //目的数据偏移。屏幕第1行, 第0列。 //延时函数 asm void Delay() { mov ecx, 0xFFFFFF _Loop2: loop _Loop2 ret } //32 位代码段. 由实模式跳入(可执行可读) asm void main() { mov eax, SelectorVideo mov gs, ax //视频段选择子(目的) mov eax, SelectorData32 //令32位代码段的变量(printPlace)可以读写 mov ds, ax call Delay //调用延时函数 //下面显示一个字符串(显示已经到达保护模式信息) mov ah, 14h //蓝底红字(AL = 14h) mov esi, &Msg1 //源数据偏移 mov edi, printPlace //根据保存的光标位置,继续显示字符 //循环逐个将字符串输出 _DispStr: mov al, cs:[esi]//因为可读,才能用cs指向当前段的Msg1字符串 inc esi cmp al, '/0' //判断是否字符串结束 jz _stop mov gs:[edi], ax add edi, 2 jmp _DispStr _stop: //显示完毕 add edi, 2 mov printPlace, edi //保存最后的光标位置 //通过反汇编,知道pm16.c的_BackToRealModel在内存的0x7c18处 jmp dword SelectorSode16:0x7c18 - 0x7c00 }
想要实验以上代码的朋友请注意:
1.到杨晓兵大大的博客上下载安装yc09,安装只需一分钟左右。
2.将操作系统实验二:从实模式跳转到保护模式 中的run.c代码,以及此次试验中的pm.h、pm16.c、pm32.c代码拷贝到某个实验用的文件夹内。
3.在YC09/example文件夹内找到bochs.exe、BIOS-bochs-latest、VGABIOS-elpin-2.40、x11-pc-us.map四个文件拷贝到试验用的文件夹内。
4.使用yc09编译运行run.c
相关文章推荐
- 实模式向保护模式跳转
- 实模式跳转到保护模式
- 实模式跳转到保护模式,在保护模式打印一个字符串。
- 系统从实模式跳转到保护模式的基本步骤
- JongXie OS系统成功从实模式跳转到保护模式下运行
- 2013-02-23 -一个简单的实模式跳转到保护模式程序(无loader功能)
- 实模式跳转到保护模式时用到的概念
- 一个操作系统的实现:关于保护模式和实模式的跳转和段描述符高速缓冲寄存器
- 从实模式到保护模式跳转的详解
- babyos (五)—— 跳转到保护模式并显示一个LOGO
- 跳转到保护模式并显示一个LOGO
- 一个操作系统的实现:关于保护模式和实模式的跳转和段描述符高速缓冲寄存器
- 保护模式实模式跳转之迷-调试
- 保护模式下的跳转
- 实模式跳转保护模式,代码全注释
- 实模式跳转保护模式,代码全注释
- 操作系统实验二:从实模式跳转到保护模式
- 一个操作系统的实现:关于保护模式和实模式的跳转和段描述符高速缓冲寄存器
- 从实模式跳转到保护模式再跳回实模式的程序
- x386保护模式下的特权级互相跳转小结