在保护模式下编写程序
来到保护模式(unfinished)
0.保护模式
在8086的芯片里,你可以访问或修改任意一个内存单元。因为它只有一种工作方式,那就是实模式。
8086可以一次性处理16位的数据,传送16位的数据,寻址1MB的内存,后来intel在80286上实现了16位保护模式,80286有24跟地址线,可以在保护模式下寻址16MB的内存,但是由于80286的寄存器仍然是16位的,所以段的长度不能超过64KB(16位保护模式已经很少为人知了),后来实现了32位的保护模式,机器在这种模式下具有32位的寄存器,32条地址线,最多可访问4GB的内存,但是为了兼容性,实模式还是保留了下来,可相比于最多寻址1MB的实模式,工作在保护模式下的机器才能以最高效率运行,除此之外最重要的一点,便是体现在“保护”二字之上。
1.GDT(全局描述符表)
一开始我们提到的8086实模式,在这种工作模式下我们可以不受约束地修改或访问内存,在现在看来这是非常不合理的,因为你的程序有可能会发生不可预料的结果,从而转移到了别的程序的代码段里作修改,这样就会引发各种问题。
于是便想到了在使用段之前应该先声明该段的起始地址,有多大等信息,这些信息叫做段描述符(Seg Descriptor)。我们用一块内存统一放置这些段描述符,这块内存叫做GDT,里面有多少项,说明有多少个段。为了保存这个GDT处理器内部使用一个48位的寄存器GDTR,低十六位保存"GDT边界",数值上等于 GDT的大小-1,实际上等于表内最后一字节的偏移地址,高32位表示GDT的起始地址。
关于SD,则是用一段8字节的数据结构来表示:
(高32位)
1-1.G字段:1bit,决定段界限的单位,G为1时段界限以4KB为单位,G为0时以1B为单位。
1-2.D/B字段:1bit,表示默认的操作数大小,对于代码段,其称为D,D=1时处理器执行该段时使用EIP取指令,否则使用IP;对于栈段,称为B位,B=1时使用ESP,否则使用SP。
1-3. L字段:1bit,64位代码段标志。留给64位处理器使用。
1-4.AVL字段:1bits,留给操作系统使用。
1-5.P 字段: 1bit,当描述符访问内存中的段时,如果P=0处理器则产生一个异常中断。而操作系统则处理该过程,将该段从硬盘换回内存,并将P位置1.
1-6. DPL字段:2bits,表示特权级,一共有四种0,1,2,3,零级具有最高优先级。
1-7.S字段:1bit,s=1时表示这是一个代码段或数据段,s=0表示这是系统段。
1-8 TYPE字段:
(低32位)
可以看出,虽然在64位的空间里表示32位的段基址和20位的段界限,它们分配的空间是非常断续的,于是编写这部分代码时要认真,先从SD开始,声明一个数据结构。
编写这部分代码时,必须严格根据SD的结构
首先声明一个宏Descriptior,由三个参数组成,设为P1,P2,P3
P1代表段基址(32bits) ,P2代表段界限(20位),P3代表各个字段的值。
;--------Segment Descriptior
%marco Descriptor 3 ;表明这个宏由三个参数组成
dw %2 & 0xFFFF ;取段界限的低16位
dw %1 & 0xFFFF ;取段基址的低16位
db (%1 >> 16) & 0xff ;取段基址的23~16位
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)
db (%1 >> 24) & 0FFh ;取段基址的31~24位
%endmarco
关于这条指令dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh),是因为在SD中的第8位到第23位,关于属性的比特并不是连续的,必须从参数中分开取出,再用与操作合并。
2.从实模式到保护模式
上一篇: GitHub中多个项目上传到同一个仓库
下一篇: log4net日志记录 轻松上手
推荐阅读
-
在保护模式下编写程序
-
在IIS下安装PHP扩展的方法(超简单)
-
关于Kube-Proxy在IPVS模式下的路由问题
-
NodeJs 6.9.2在Ubuntu 16.04、CentOS 7.5、Windows10下的安装配置 博客分类: LinuxNodeJS NodeJSLinuxWindows
-
在centos下搭建一个wordpress博客
-
在Java下利用log4j记录日志的方法
-
在PHP 7下安装Swoole与Yar,Yaf的方法教程
-
理清PHP在Linxu下执行时的文件权限方法
-
SQLite3 安装及在Ruby下的使用
-
ASP.net Menu控件在Google Chrome和Safari浏览器下显示错位的解决办法