5.从实模式进入保护模式

本文接上一篇博文,在 loader.S中干点正事儿。进入保护模式。

1.什么是保护模式?

最经典的 8086CPU 是只有实模式的。实模式下有很多的不足,所以有了保护模式。
实模式的缺点:

  1. 操作系统和用户程序处于同一特权级。
  2. 用户程序所引用的地址都是指向真实的物理地址。
  3. 用户程序可以自行修改段基址,可以访问所有内存。
  4. 访问超过 64KB 的内存区域要切换段基址。
  5. 一次只能运行一个程序。
  6. 共 20 条地址线,最大可用内存 1 MB 。

实模式是 32 位的 CPU 运行在 16 位模式下的状态。而不是CPU变为16位的了。

保护模式下,很多东西都扩展了。(因为变为32位了嘛)

  1. 寄存器扩展
    在这里插入图片描述
    但是 CS、 DS、 ES、 FS、 GS、 SS 段寄存器还是16位的。

  2. 寻址扩展
    在这里插入图片描述

  3. 指令扩展
    实模式下,它的操作数可以是 8 位、16位,
    而在保护模式下,它不仅要支持 8 位、16位,还得支持 32 位的操作数。

add al, cl ; 8位
add ax, cx ;16位
add eax, ecx ;32位

2.全局描述符表(GDT)

在实模式下,地址用 段基址:偏移地址 来表示。段基址左移 4 位加上偏移地址。只能寻址 1MB的地址空间。

为了兼容性,地址也要用 段基址:偏移地址 来表示。但是这个段基址不是用来左移 4 位。
准确来说,段寄存器中存的不是段基址,而是选择子。

保护模式下的寻址:

  1. 在内存中有一部分区域是 GDT(全局描述符表),表中每个表项是段描述符
  2. <
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: x86模式保护模式的转换需要编写一些配套的代码,以下是一些主要的步骤和对应的代码现: 1. 关闭中断:在进入保护模式之前,需要先关闭中断。可以使用汇编指令“cli”来现: ```assembly cli ``` 2. 设置全局描述符表(GDT):保护模式中使用GDT来管理内存和其他资源。需要定义一个GDT并将其加载到CPU中。可以使用以下代码进行初始化: ```assembly gdt_start: dd 0x0 dd 0x0 gdt_code: dw 0xFFFF dw 0x0 db 0x0 db 10011010b db 11001111b db 0x0 gdt_data: dw 0xFFFF dw 0x0 db 0x0 db 10010010b db 11001111b db 0x0 gdt_end: gdt_descriptor: dw gdt_end - gdt_start - 1 dd gdt_start ;加载GDT到CPU lgdt [gdt_descriptor] ``` 3. 切换到保护模式:使用汇编指令“jmp”进行转移,并设置CR0控制寄存器的PE位为1,即可切换到保护模式: ```assembly jmp gdt_code:protect_mode align 4 protect_mode: mov eax, cr0 or eax, 0x1 mov cr0, eax ``` 4. 设置段选择符:在保护模式下,需要使用新的段选择符。可以通过以下代码对段选择符进行初始化: ```assembly mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ``` 5. 启用中断:在保护模式下,可以使用汇编指令“sti”开启中断: ```assembly sti ``` 通过以上配套的代码,可以完成从x86模式保护模式的转换。这些代码包括关闭中断、设置GDT、加载GDT、切换到保护模式、设置段选择符和启用中断等关键步骤,确保计算机可以在保护模式下正常运行。 ### 回答2: x86模式保护模式的转换需要一些特定的代码来完成。下面是一个简单的例子: ```assembly ; 进入保护模式的代码 org 0x7C00 ; 设定源代码的起始地址 ; 设置初始的段寄存器 xor ax, ax ; 将 ax 寄存器初始化为 0 mov ds, ax ; 将数据段寄存器 (ds) 设置为 0 ; 切换到保护模式 cli ; 清空中断标志寄存器 (IF) mov ax, 0x1000 ; 设置代码段选择器为 0x1000 mov ds, ax ; 将数据段寄存器 (ds) 设置为 0x1000 mov ss, ax ; 将堆栈段寄存器 (ss) 设置为 0x1000 mov sp, 0xFFFF ; 设定堆栈指针 (sp) 到堆栈的顶部 sti ; 设置中断标志寄存器 (IF) ; 切换到保护模式后的代码 [其他代码] ``` 这段代码主要包含了进入保护模式的过程。首先,通过将 ax 寄存器初始化为零,并将 ds 寄存器设置为零来确保初始的段寄存器的正确设定。然后,通过cli指令清空中断标志寄存器 (IF)。接下来,通过将代码段选择器设置为 0x1000,再将 ds 和 ss 寄存器都设置为 0x1000,来设定合适的段寄存器。然后,通过设定堆栈指针 sp 为 0xFFFF 来设置堆栈的顶部。最后,通过sti指令来设置中断标志寄存器 (IF)。 当切换到保护模式后,接下来的代码将在保护模式下执行。在这段代码后可以添加一些其他的指令,用于在保护模式下完成所需的任务。 ### 回答3: x86处理器可以在模式保护模式下运行。模式是x86处理器最初的运行模式,它是用于向后兼容早期的x86处理器设计的模式保护模式是一种更高级的模式,它提供了更多的内存管理、特权级别和安全功能。 要从x86模式切换到保护模式,需要编写配套的代码。以下是一个简化的示例代码: 1. 关闭中断:使用汇编指令`CLI`(Clear Interrupt flag)关闭中断。 2. 设置GDT(全局描述符表):在保护模式下,每个段需要由描述符来定义。首先需要初始化一个GDT,其中包含代码段、数据段和其他需要的段。使用`LGDT`(Load Global Descriptor Table)指令将GDT的地址加载到处理器的GDTR(Global Descriptor Table Register)寄存器中。 3. 切换到保护模式:将CR0(Control Register 0)寄存器的第0位(PE位)设置为1,这将使处理器进入保护模式。使用`MOV`指令将带有标志位的CR0的值加载到`EAX`寄存器中,然后使用`OR`指令将`0x1`布尔值与`EAX`寄存器的值相或,并将结果放回CR0寄存器。 4. 刷新段寄存器:由于段寄存器中的段选择器已经发生了变化,因此需要执行一个`JMP`指令来重新加载CS(Code Segment)和其他段寄存器。 5. 打开中断:使用`STI`(Set Interrupt flag)指令打开中断。 这些是切换x86模式保护模式的基本步骤。当这些步骤完成后,处理器将以保护模式运行,并可以利用更多的内存、特权级别和安全功能。需要注意的是,上述代码是一个简化版本,际的代码可能更加复杂,包含错误处理和其他必要的配置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值