>> 欢迎您,客人客人客人客人: 登录 | 注册 | 忘记密码 | 在线 | 搜索 | 帮助
教学论坛
Projects [返回]
Project:从实模式进入保护模式
标记论坛所有内容为已读
>> Projects欢迎您的到来 <<
◆您是本帖第 7936793679367936 个阅读者◆
* 贴子主
* 贴子主题* 贴子主题* 贴子主题: Project:从实模式进入保护模式
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
创建实际的引导程序
选择了分段的内存模型后需要设置段,这通过创建和加载GDT完成。至少要有两个段:一个
代码段和一个数据段。为简单起见将它们重叠。
1.开始
首先引导程序告诉编译器使用16位的指令,内存基地址为0x7C00:
[BITS 16]
[ORG 0x7C00]
其次,关闭实模式下的中断
必须确保本引导程序是唯一正在执行的程序。只有中断能够影响程序的正常执行,因此在
ORG命令后的适当位置必须关闭中断:
cli ; Disable interrupts, we want to be alone
2007/03/27 03:42pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
2. 填写GDT
第一个段通常设置为0,使其成为空段(null segment)。这个段被Intel保留,不可被访
问。如果加载该空段,则将产生通用保护异常(General Protection Exception)。通过写
64位0来填充空段。
gdt: ; Address for the GDT
gdt_null: ; Null Segment
dd 0
dd 0
2007/03/27 03:43pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
消息 查看 搜索 好友 邮件 复制 引用 回复
此主题相关图片如下:
3. 填写代码段的Descriptor
gdt_code: ; Code segment, read/execute, nonconforming
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第1页共6页 2011/12/251:20
注册日期: 2006/10/08 根据Descriptor的结构(如图所示)
开始的16位设置段偏移(Limit, 15-0)。保护模式下段偏移可以达到4GB(总共0ffffH的偏
移量):
dw 0FFFFh; 16 bits segment offset = 0xffff = 4G in protected mode, Limit(15-0)
接下来设置基地址为0(内存起始地址,Base 15-0):
dw 0 ; 16 bits base address = 0, Base (15-0)
2007/03/27 03:46pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
此主题相关图片如下:
接下来的16位,首先是8位基地址,仍然为0;然后是8位Access rights,根据每一位的含
义:(如图所示)
A是访问标志,有CPU在第一次访问时设置,置0;R/W置为1使段可读;ED/C表示顺从性,如
果设置位1,则表示低优先级的代码段可以跳转到或调用该段。此处置为0,不需要此功
能;E置为1,表示描述符描述的是代码段;S表示该段是代码段或数据段,置为1;DPL表示
优先级,由于是引导程序,所以要把优先级设为00;最后,P设置为1。综上,该16位用代码
表示即为:
db 0 ; 8 bit base address = 0, Base(23-16)
db 10011010b ; Access rights: A=0; R=1; C=0; E=1; S=1; DPL=00; P=1
最后16位。首先4位偏移量,设置为0Fh;AV为表示Available,AV=1表示segment is
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第2页共6页 2011/12/251:20
available,此处忽略该位,设为0;Intel保留了一位必须设为0;D表示大小位,置为1,它
告诉CPU使用32位代码而不是16位代码;G表示粒度,如果G=0,则Limit所表示的段偏移是
00000H-FFFFFH,如果G=1,则Limit表示的段偏移是00000XXXH-FFFFFXXXH,即Limit所表示
的段偏移实际上是它的值再乘以4K。此处设置G=1。于是得到前8位:11001111。后8位是基
地址,仍然是0,代码如下:
db 11001111b ; G=1; D=1; AV=0; Limit=1111=0xfh
db 0 ; 8 bit base address = 0, Base (31-24)
至此完成了代码段的段描述符设置,该描述放置在GDT中。
2007/03/27 03:49pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
4. 填写数据段的Descriptor
前32位与代码段一样:
gdt_data: ; Data segment, read/write, expand down
dw 0FFFFh
dw 0
接下来16位,前8位为0。后8位与代码段有所不同,由于是数据段,需要可写,所以Type的
组合为001(E=0、ED=0、W=1);S=1;DPL=00;P=1。
db 0
db 10010010b ; Access rights: A=0; W=1; ED=0; E=0; S=1; DPL=00; P=1
最后16位与代码段一样:
db 11001111b ; G=1; D=1; AV=0; Limit=1111=0xfh
db 0 ; 8 bit base address = 0, Base (31-24)
现在,形成了一个空段、一个代码段和一个数据段。它们都放置在GDT中。接下来需要让CPU
找到这个GDT,从而可以利用其中已经创建好的Descriptor来访问内存。
2007/03/27 03:50pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
此主题相关图片如下:
5.加载GDT
利用LGDT指令把一个地址放入GDT描述符(即GDTR),它告诉CPU到哪里去找GDT以及GDT的大
小。GDTR长48位,其中0-15位表示GDT的大小(Lmit),16-47位表示GDT的地址(Base
address)
为了知道GDT的大小,需要在编译时就将其计算出来,NASM中必须在数据段之后增加一行:
gdt_end: ; Used to calculate the size of the GDT
然后得到GDT的地址:
gdt_desc: ; The GDT descriptor, that is, the GDTR
dw gdt_end – gdt – 1 ; Limit (size)
dd gdt ; Address of the GDT
由于GDTR的地址是DS:gdt_desc,而DS的是不知道——通过AX来设置:
xor ax, ax
mov ds, as ;DS stores the address of GDT, set DS-register to 0 - used by lgdt
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第3页共6页 2011/12/251:20
执行LGDT指令:
lgdt[gdt_desc]
现在GDT应该如图所示。
2007/03/27 03:53pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
6. 进入保护模式
通过设置cr0寄存器中的第0位来进入保护模式。首先把cr0(16位)种的内容转移到EAX中,
然后把EAX与1进行或操作来设置第0位,最后把EAX再转移到cr0中即可。
moveax, cr0; Copy the contents of CR0 into EAX
or eax, 1; Set bit 0 of cr0
movcr0, eax; Copy the contents of EAX into CR0
2007/03/27 03:54pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
此主题相关图片如下:
7. 清空指令缓冲队列
需要清空指令缓冲队列。该队列包含了一些16位模式中剩余的指令,但现在是在32位模式
下,不再需要16位模式下的指令。通过一个远跳转指令来清空该队列,即跳转到代码段中的
某一偏移位置。按照先前的定义,代码段是空段后的第一个段,只需*8(multiple by 8)
即可到达代码段。
另外,进入32位模式后,需要告诉编译器需要编译32位的指令,为此,需要在远跳转指令后
加上[BITS 32]。
jmp 08h:clear_pipe ; Jump to code segment, offset is “clear_pipe”
[BITS 32] ; We now need 32-bit instructions
clear_pipe:
mov ax, 10h ; Save data segment identifyer
mov ds, ax ; Move a valid data segment into the data segment register
mov ss, ax ; Move a valid data segment into the stack segment register
mov esp, 090000h ; Move the stack pointer to 090000h
jmp 08h:clear_pipe指令将使程序从代码段中的“clear_pipe”处继续执行。然后需要把正
确的值写入6个寄存器中:CS、DS、ES、SS、FS和GS。寄存器其实指向了GDT中的
Descriptor。Selector的内容位于DS等各个寄存器中,而GDTR(GDT描述符)的地址是
DS:gdt_desc。附图说明了使用DS寄存器从GDT中选择一个descriptor的情况。
- CS指向代码段,这在跳转时已经设置了,是08h,即gdt_code
- DS指向数据段,是存放变量的地方。数据段在GDT中位于代码段下面(其实是代码段的别
名段),即空段后面的第二个段,只需*16(multiple by 16)即可到达数据段,DS的值应
该是10h
- SS指向堆栈段,也是存放变量的地方,同样是10h
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第4页共6页 2011/12/251:20
DS的值不能直接设置,通过AX来设置:
mov ax, 10h
mov ds, ax
mov ss, ax
完成段设置后,要设置偏移量。偏移量保存在ESP中。偏移量应该远离内存的前1MB,此处将
堆栈设置在090000h。
mov esp, 090000h ; Move the stack pointer to 090000h
2007/03/27 03:57pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
8. 确认跳转到正确的代码段
在保护模式中不能使用BIOS中断。为了确定引导程序跳转到了正确的代码段,需要在屏幕上
显示字符,以显示“hello”为例。
显存位于0xA000-0xBFFFF之间,通常帧缓冲位于0xB8000处(彩色文本模式,应用于CGA,EGA
和VGA)。每个字符需要2个字节:第一个字节是该字符的ASCII码;第二个字节是颜色属
性。字符显示的方式为:用亮青色作为前景色,蓝色作为背景色,并且不使用闪烁显示。第
0-3位设置前景色,4-6位设置背景色,第7位设置是否闪烁。0Bh代表亮青色,01h代表蓝
色,0代表不闪烁.
mov byte [ds:0B8000h], 'H' ; Move the ASCII-code of 'H' into first video memory
mov byte [ds:0B8001h], 1Bh ; Assign a color code
mov byte [ds:0B8002h], 'e' ; Move the ASCII-code of 'e' into first video memory
mov byte [ds:0B8003h], 1Bh ; Assign a color code
mov byte [ds:0B8004h], 'l' ; Move the ASCII-code of 'l' into first video memory
mov byte [ds:0B8005h], 1Bh ; Assign a color code
mov byte [ds:0B8006h], 'l' ; Move the ASCII-code of 'l' into first video memory
mov byte [ds:0B8007h], 1Bh ; Assign a color code
mov byte [ds:0B8008h], 'o' ; Move the ASCII-code of 'o' into first video memory
mov byte [ds:0B8009h], 1Bh ; Assign a color code
2007/03/27 03:58pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
9. 收尾工作
系统已经进入了保护模式,此处暂时把系统挂起。
hang:
jmp hang
最后加上一行:
times 510-($-$$) db 0 ; Fill up the file with zeros
dw 0AA55h ; Boot sector identifyer
2007/03/27 03:59pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
消息 查看 搜索 好友 邮件 复制 引用 回复
相关附件: (共 2365 字节)
完整的参考代码。
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第5页共6页 2011/12/251:20
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08 2007/03/27 04:01pm IP: 已设置保密
0620080395 0620080395 0620080395 0620080395
信息:
威望: 0
来自: 保密
总发贴数: 279279279279 篇
注册日期: 2006/10/08
消息 查看 搜索 好友 邮件 复制 引用 回复
此主题相关图片如下:
现在看看结果吧^o^
2007/03/27 04:34pm IP: 已设置保密
本主题共有 本主题共有 本主题共有 本主题共有 2222 页 页 页 页 9 7 [ 1 2222 ] 8 :
快速回复主题:快速回复主题:快速回复主题:快速回复主题: Project:从实模式进入保护模式
输入用户名和密码:输入用户名和密码:输入用户名和密码:输入用户名和密码: 用户名用户名用户名用户名: 客人 没有注册? 密码:密码:密码:密码: 忘记密码?
上传附件或图片上传附件或图片上传附件或图片上传附件或图片 (最大容量 900900900900KB) ----------
选项选项选项选项
使用 LB5000 标签?
显示您的签名?
有回复时使用邮件通知您?
发 表 回 复 清 除 内 容 [使用 Ctrl+Enter 直接提交贴子]
顶端 加到"个人收藏夹"
主题管理主题管理主题管理主题管理: 总固顶 | 取消总固顶 | 固顶 | 取消固顶 | 精华 | 取消精华 |
提升 | 锁定 | 解锁 | 删除 | 删除回复 | 移动 |
© 中文版权所有: CGI 编程者之家 版本: LB5000MX 1.85
程序版权所有: CGI 编程者之家 程序编制: 山鹰(糊)、 花无缺
本论坛言论纯属发表者个人意见,与 教学论坛 教学论坛 教学论坛 教学论坛 立场无关
Projects-Project:从实模式进入保护模式 http://mp.tongji.edu.cn/cgi-bin/topic.cgi?forum=6&topic...
第6页共6页 2011/12/251:20