;代码清单12-1;文件名:c12_mbr.asm;文件说明:硬盘主引导扇区代码;创建日期:2011-5-16 19:54;修改于2022-02-16 11:15;设置堆栈段和栈指针mov ax, csmov ss, axmov sp, 0x7c00;计算GDT所在的逻辑段地址mov ax, [cs: gdt_base + 0x7c00] ;低16位mov dx, [cs: gdt_base + 0x7c00 + 0x02] ;高16位mov bx, 16div bxmov ds, ax ;令DS指向该段以进行操作mov bx, dx ;段内起始偏移地址;创建0#描述符,它是空描述符,这是处理器的要求mov dword [bx+0x00],0x00mov dword [bx+0x04],0x00;创建#1描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)mov dword [bx+0x08],0x8000ffffmov dword [bx+0x0c],0x0040920b;初始化描述符表寄存器GDTRmov word [cs: gdt_size+0x7c00],15 ;描述符表的界限(总字节数减一)lgdt [cs: gdt_size+0x7c00]in al,0x92 ;南桥芯片内的端口or al,0000_0010Bout 0x92,al ;打开A20cli ;保护模式下中断机制尚未建立,应;禁止中断mov eax,cr0or eax,1mov cr0,eax ;设置PE位;以下进入保护模式... ...mov cx,00000000000_01_000B ;加载数据段选择子(0x08)mov ds,cx;以下在屏幕上显示"Protect mode OK."mov byte [0x00],'P'mov byte [0x02],'r'mov byte [0x04],'o'mov byte [0x06],'t'mov byte [0x08],'e'mov byte [0x0a],'c'mov byte [0x0c],'t'mov byte [0x0e],' 'mov byte [0x10],'m'mov byte [0x12],'o'mov byte [0x14],'d'mov byte [0x16],'e'mov byte [0x18],' 'mov byte [0x1a],'O'mov byte [0x1c],'K'mov byte [0x1e],'.'hlt ;已经禁止中断,将不会被唤醒;-------------------------------------------------------------------------------gdt_size dw 0gdt_base dd 0x00007e00 ;GDT的物理地址times 510-($-$$) db 0db 0x55,0xaa
根据上一篇我们讲到的内容继续
你会发现,控制实模式和保护模式切换的开关原是在一个叫CR0的寄存器
CR0
CR0是处理器内部的控制寄存器,之所以有个“0”后缀,是因为还有CR1,CR2,CR3…控制寄存器,到CR8
CR0是32位寄存器,包含了一系列用于控制处理操作模式和运行状态的标志位
如下
PE位
如果它的第1位为保护模式允许位,是开启保护模式的关键,如果为1,则处理器进入保护模式。
这里我们先只介绍这个
在保护模式下的中断和实模式下的中断不同,原有的中断向量表不再适用,而且必须要知道的是,BIOS中断都不能再使用。
所以你会看到37行
8086的段寄存器是16位的,共有四个:CS、DS、ES、SS
32位处理器内,在原有的基础上又增加了FS和GS
不可见部分是段的线性基址、界限、属性
段选择子
在保护模式下访问一个段时,传送到段寄存器的是段选择子
由上图我们可以看到
它由三部分构成
- 描述符索引号(Index)
- TI描述符指示器(Table Indicator)
当TI=0时,表示描述符在GDT中
当TI=1时,描述符在LDT中
LDT和GDT类似 - PRT请求特权级
我们可以看到12-1的代码清单,定义了1个段描述符,因为表内描述符的编号是从0开始的,所以它的索引号是1
在45、46行,将描述符选择子0x0008传送到段选择器DS中,代码中用的是二进制
从二进制可以看到,指定描述符号的索引值号是1,指定的是GDT,请求特权级PRT为00
GDT的线性基址在GDTR中,又因为每个描述符占8字节,因此描述符在表内的偏移地址是索引号乘以8
下图是保护模式下内存访问
保护模式下处理器取指令的过程
在进入保护模式前,处理器就已经使用CS描述符高速缓存器里的基址从代码段取指令并执行指令