Gate A20与保护模式

news/2024/4/16 3:59:28

 Gate A20与保护模式

 

 

大家都知道,8088/8086只有20位地址线,按理它的寻址空间是2^20,应该是1024KB,但PC机的寻址结构是segment:offset,segment和offset都是16位的寄存器,最大值是0ffffh,换算成物理地址的计算方法是把segment左移4位,再加上offset,所以segment:offset所能表达的寻址空间最大应为0ffff0h + 0ffffh = 10ffefh(前面的0ffffh是segment=0ffffh并向左移动4位的结果,后面的0ffffh是可能的最大offset),这个计算出的10ffefh是多大呢?大约是1088KB,就是说,segment:offset的地址表达能力,超过了20位地址线的物理寻址能力,你说这是不是有点麻烦。在早先,由于所有的机器都没有那么大的内存,加上地址线只有20位,所以当你用segment:offset的方式企图寻址100000h这个地址时,由于没有实际的第21位地址线,你实际寻址的内存是00000h的位置,如果你企图寻址100001h这个地址时,你实际得到的内容是地址00001h上的内容,所以这个事对实际使用几乎没有任何影响,但是后来就不行了,出现了80286,地址线达到了24位,使segment:offset寻址100000h--10ffefh这将近64K的存储器成为可能,为了保持向下兼容,于是出现了A20 Gate,这是后话,我们后面再细说。

    我们可能经常听到一些只有在PC机上才有的一些关于存储器的专有名词,包括:常规内存(Conventional Memory)、上位内存区(Upper Memory Area)、高端内存区(High Memory Area)和扩展内存(Extended Memory),我尽量把这几个东东说明白,这需要下面这张著名的图。

 

    这张图很清楚地说明了问题,大家都知道,DOS下的“常规内存”只有640K,这640K就是从0--A0000H这段地址空间;所谓“上位内存区”,指的就是20位地址线所能寻址到的1M地址空间的上面384K空间,就是从A0001H--100000H这段地址空间,也就是我们说的用于ROM和系统设备的地址区域,这384K空间和常规内存的640K空间加起来就是20位地址线所能寻址的完整空间1024KB;由于80286和80386的出现使PC机的地址线从20位变成24位又变成32位,寻址能力极大地增加,1M以上的内存寻址空间,我们统称为“扩展内存”;这里面绝大部分内存区域只能在保护模式下才能寻址到,但有一部分既可以在保护模式下,也可以在实模式下寻址,这就是我们前面提到过的地址100000h--10ffefh之间的这块内存,为了表明其特殊性,我们把这块有趣的内存区叫做“高端内存”。

    前面我们提过由于IBM的愚蠢设计给PC机的内存结构埋下了麻烦的伏笔,现在我们来说说这个麻烦。我们都见过PC机上的内存条,但是由于上位内存区的存在,这个内存条上的地址居然不能连续,就是说,这个内存条上要有0--A0000H的地址空间,还要有100000h--最大内存容量的地址空间,中间的384K地址空间必须留出来给ROM用,在现如今一个芯片就好几兆的情况下,你说这个内存条应该怎么做,当然我相信一定是可以做出来的,但肯定很麻烦,如果当初IBM把这个“上位内存区”放在地址低端,就是0--6000h这一部分,岂不是这个麻烦就没有了?!

    但是,实际的内存条上地址都是连续的,并没有人把这段地址空间留出来给ROM使用,原因很简单,采用技术手段把这段地址空间空出来,比浪费这384K内存的成本还要高,所以在这个地址区域就出现了很奇怪的现象,ROM和RAM的地址重叠。 实际上,往往ROM并不能完全覆盖整个384K区域,这样就会有一些地址没有被ROM占用,那么这部分地址上的RAM仍然是可以使用的。实际上,和ROM重叠的这384K RAM一般也不会被浪费,说到这里,不得不说所谓的ROM Shadowing了,RAM和ROM的性能是有很大差异的,RAM的存取速度要远远大于ROM,而且RAM可以32位存取,ROM通常只能16位,所以目前的PC机对这块RAM和ROM重叠的区域的处理采用一种ROM Shadowing的技术方式,当机器加电后,先让ROM有效,RAM无效,然后读出ROM内容,再让ROM无效,RAM有效,把读出的ROM内容放到相同地址的RAM中,并把相应位置的RAM设定为只读,这样就把ROM搬到了RAM中,地址完全一样,只是性能比使用ROM要高些,这块RAM就好像ROM的Shadow一样。

    回到我们的主题A20 Gate,出现80286以后,为了保持和8086的兼容,PC机在设计上在第21条地址线(也就是A20)上做了一个开关,当这个开关打开时,这条地址线和其它地址线一样可以使用,当这个开关关闭时,第21条地址线(A20)恒为0,这个开关就叫做A20 Gate,很显然,在实模式下要访问高端内存区,这个开关必须打开,在保护模式下,由于使用32位地址线,如果A20恒等于0,那么系统只能访问奇数兆的内存,即只能访问0--1M、2-3M、4-5M......,这显然是不行的,所以在保护模式下,这个开关也必须打开。

    下面我们来看一下PC机是怎么实现A20 Gate的。

     早期的PC机,控制键盘有一个单独的单片机8042,现如今这个芯片已经给集成到了其它大片子中,但其功能和使用方法还是一样,当PC机刚刚出现A20 Gate的时候,估计实在找不到控制它的地方了,同时为这点小事也不值得增加芯片,于是工程师使用这个8042键盘控制器来控制A20 Gate,但A20 Gate真的和键盘一点关系也没有,我们先从软件的角度简单介绍一下8042这个芯片。

    8042有4个寄存器

1个8-bit长的Input buffer;Write-Only;

1个8-bit长的Output buffer; Read-Only;

1个8-bit长的Status Register;Read-Only;

1个8-bit长的Control Register;Read/Write。


    有两个端口地址:60h和64h。

读60h端口,读output buffer
写60h端口,写input buffer
读64h端口,读Status Register
    对Control Register的操作相对要复杂一些,首先要向64h端口写一个命令(20h为读命令,60h为写命令),然后根据命令从60h端口读出Control Register的数据或者向60h端口写入Control Register的数据(64h端口还可以接受许多其它的命令)。

    先来看看Status Register的定义,我们后面要用bit 0和bit 1:

    bit    meaning
    -----------------------------------------------------------------------
     0     output register (60h) 中有数据
     1     input register (60h/64h) 有数据
     2     系统标志(上电复位后被置为0)
     3     data in input register is command (1) or data (0)
     4     1=keyboard enabled, 0=keyboard disabled (via switch)
     5     1=transmit timeout (data transmit not complete)
     6     1=receive timeout (data transmit not complete)
     7     1=even parity rec'd, 0=odd parity rec'd (should be odd)


    除了这些资源外,8042还有3个内部端口:Input Port、Outport Port和Test Port,这三个端口的操作都是通过向64h发送命令,然后在60h进行读写的方式完成,其中本文要操作的A20 Gate被定义在Output Port的bit 1上,所以我们有必要对Outport Port的操作及端口定义做一个说明。

读Output Port
向64h发送0d0h命令,然后从60h读取Output Port的内容
写Output Port
向64h发送0d1h命令,然后向60h写入Output Port的数据
    另外我们还应该介绍两个命令:

禁止键盘操作命令
向64h发送0adh
打开键盘操作命令
向64h发送0aeh
    有了这些命令和知识,我们可以考虑操作A20 Gate了,有关8042芯片更详细的资料,请参考该芯片的Data Sheet。

     如何打开和关闭A20 Gate。

    理论上讲,我们只要操作8042芯片的输出端口(64h)的bit 1,就可以控制A20 Gate,但实际上,当你准备向8042的输入缓冲区里写数据时,可能里面还有其它数据没有处理,所以,我们要首先禁止键盘操作,同时等待数据缓冲区中没有数据以后,才能真正地去操作8042打开或者关闭A20 Gate。打开A20 Gate的具体步骤大致如下:

    1.关闭中断;
    2.等待8042 Input buffer为空;
    3.发送禁止键盘操作命令;
    4.等待8042 Input buffer为空;
    5.发送读取8042 Output Port命令;
    6.等待8042 Output buffer有数据;
    7.读取8042 Output buffer,并保存得到的字节;
    8.等待8042 Input buffer为空;
    9.发送Write 8042 Output Port命令到8042 Input buffer;
    10.等待8042 Input buffer为空;
    11.将从8042 Output Port得到的字节的第2位置1(或清0),然后写入8042 Input buffer;
    12.等待,直到8042 Input buffer为空为止;
    13.发送允许键盘操作命令到8042 Input buffer;
    14. 打开中断。

    下面是完成打开A20 Gate的代码:

    A20Enable:
                cli                     ;1.关闭中断
                call WaitInbufEmpty    ;2.等待8042 Input buffer为空;
                mov al, 0adh
                mov dx, 64h
                out dx, al              ;3.发送禁止键盘操作命令
                call WaitInbufEmpty    ;4.等待8042 Input buffer为空;
                mov al, 0d0h
                mov dx, 64h
                out dx, al              ;5.发送读取8042 Output Port命令;
                call WaitOutbufFull     ;6.等待8042 Output buffer有数据;
                mov dx, 60h
                in al, dx               ;7.读取8042 Output buffer
                push ax                 ;保存读取的数据
                call WaitInbufEmpty     ;8.等待8042 Input buffer为空;
                mov al, 0d1h
                mov dx, 64h
                out dx, al              ;9.发送写 8042 Output Port命令
                call WaitInbufEmpty     ;10.等待8042 Input buffer为空
                pop ax
                or al, 02h              ;11.将从8042 Output Port得到的字节的bit 1置1
                mov dx, 60h
                out dx, al              ;写入Output Port
                call WaitInbufEmpty    ;12.等待8042 Input buffer为空
                mov al, 0aeh
                mov dx, 64h
                out dx, al              ;13.发送允许键盘操作命令
                sti                     ;开中断
                ret

    WaitInbufEmpty:
                mov dx, 64h
                in al, dx               ;读取Status Register
                test al, 02h
                jnz WaitInbufEmpty
                ret

WaitOutbufFull:
                mov dx, 64h
                in al, dx
                test al, 01             ;读取Status Register
                jz WaitOutbufFull
                ret

    后来,由于感觉使用8042控制A20运行太慢了(确实,那么长的代码,中间还要若干次的wait),所以后来又出现了所谓的Fast A20,实际上,现在的大多数机器都是Fast A20,Fast A20使用92h端口控制A20,同时BIOS里提供了一个软中断来控制A20:

    入口:ah=24h
          al=0    关闭A20
             1    打开A20
             2    读取A20状态
          int 15h

    返回:如果BIOS支持此功能,CF=0,否则CF=1
          CF=0时,AX返回当前A20状态,1=打开,0=关闭

    像8042中的Output Port中的定义一样,92h端口的bit 1控制着A20,为1时打开,为0时关闭,从92h中读一个byte可以看a20的当前状态,所以对92h的操作如下:

读A20状态
mov dx, 92h
in al, dx
如果al的bit 1为1表示a20打开,否则为0
打开A20
mov dx, 92h
mov al, 02
out dx, al
关闭A20
mov dx, 92h
mov al, 0
out dx, al
    特别要注意的是,大家从这篇文章的文字中可能也能感觉到,A20 Gate的设计本身就让人感觉很别扭,不是那么流畅,所以和A20有关的事情就难免也会有相同的感觉,很奇怪的是,上面介绍的三种方法并不是在每台机器上都适用,所以如果你要做一个商业软件其中要操作A20,那一定要三种方式联合使用才比较稳妥,否则会有意想不到的结果,LINUX公开的启动代码中就是这么做的

    在DOS下有时我们会在config.sys中写上一句:dos=high,这句就会把驻留的DOS放到高端内存区域去,怎么放的呢?关键点就是打开A20,然后把DOS从常规内存搬到100000h起始的区域去,并把在常规内存中占用的内存释放掉,当然说起来容易,实际做的时候还有很多细节要处理。

    说到DOS=HIGH,就不得不提醒大家另一件事,如果在config.sys中有dos=high这一句,那么恐怕92h的方法和BIOS的方法都会不完全灵验(至于操作8042的方法灵不灵我没有试),这是DOS做了手脚,因为DOS被放到了高端内存中,为了保证DOS能正常运行,它不允许你把A20给关掉,遇到这种情况不要惊慌,不是我写得不对,确实是DOS太狡猾了。

    还有最后一点要特别注意,92h的bit 0是给机器发复位信号的(8042 Output Port的bit 0也是),所以在向92h写数据时,千万不要让bit 0为1,否则机器会重新启动,如果你的应用程序需要重新启动机器,这也是方法之一,比jmp 0ffffh:0来的还要干脆。

 

 

 

原文作者的连接应该是这个:http://hengch.blog.163.com/blog/static/107800672009013104623747/

 


http://www.ppmy.cn/news/861323.html

相关文章

A20地址线

A20地址线并不是打开保护模式的关键,只是在保护模式下,不打开A20地址线,你将无法访问到所有的内存(具体参考下面的第5点) 用于80286

如何通过设备管理系统实现设备全生命周期管理

设备是生产力的核心,对企业的运营和效益起着至关重要的作用。然而,随着设备数量和复杂性的增加,如何有效管理设备的全生命周期成为了一个挑战。 在这个时代,设备管理系统成为了一种重要的工具,帮助企业实现设备全生命周…

什么是 A20

Unix 的 boot loader 里,在最开始部分有段代码是用来打开 A20 的。什么是 A20 呢?为什么不让它默认为打开,而是每次系统启动时都要打开它呢?原来这个是计算机的历史遗留问题。在 8088 的时候,计算机只有 20 条地址线&a…

A20 配置

TN92屏的显示配置: screen0_output_type1; screen0_output_mode5; lcd_x800; lcd_y480; lcd_swap0; lcd_dclk_freq33; lcd_hbp46; lcd_ht1055; lcd_vbp23; lcd_vt1050; lcd_lvds_ch1; lcd_lvds_mode0; lcd_lvds_bitwidth0; lcd_lvds_io_cross0; lcd_if0; N101BCG-L…

全志A20裸机开发教程----环境搭建

全志A20裸机开发教程 前言 最近在学习嵌入式开发,跟着网上下载的视频做,结果发现最初的一步就卡住了。网上的视频用的都是三星的芯片,什么6410、210,而我图省钱买了个全志的开发板,乍一看资料还挺多,但对…

A20启动代码流程分析

2019独角兽企业重金招聘Python工程师标准>>> A20启动代码流程分析:1:全志的启动包括boot0,boot1,u-boot,boot0与boot1源码在lichee/boot/目录下, 机器上电执行boot0,boot0就会引导boot1,boot1再引导u-boo…

A20地址线科普【转载】

1981 年8 月,IBM 公司最初推出的个人计算机IBM PC 使用的CPU 是Intel 8088。在该微机中地址线只有20 根(A0 – A19)。在当时内存RAM 只有几百KB 或不到1MB 时,20 根地址线已足够用来寻址这些内存。其所能寻址的最高地址是0xffff:0xffff,也即0…

OAuth 2.0:开放授权的安全认证协议

OAuth 2.0是一种开放标准的安全认证协议,旨在为应用程序提供授权和访问受保护资源的框架。它广泛应用于Web和移动应用程序中,为用户提供了安全且便捷的身份验证和授权机制。本文将介绍OAuth 2.0的基本概念、授权流程和常见应用场景,帮助读者深…

贯穿AI生命周期各阶段的道德问题:数据标注部分

随着AI在市场上得到更广泛的采用并被作为各种用例中的工具实现,更多的挑战也应势而生。AI项目遇到了一个长期的关键问题,即合乎道德的AI以及数据中的偏见处理。在AI发展初期,这个问题并不明显。 数据偏见是指数据集中某个元素的代表权重过大或…

巡风安装

目录 参考资料 下载mongodb 设置mongo环境变量 文档中启动数据库mongo 127.0.0.1:65521/xunfeng 调试run.py: 成功后开启流程 参考资料 巡风是用python的web框架flask写的 https://xycsec.cn/?p151 https://www.cnblogs.com/bayueman/articles/6604507.htm…

风压和功率计算公式轴流式_轴流风机的安置及风压的计算

轴流风机 常用于各类风冷热泵机组、 风冷单元式空调机、 多联式空调机等。 根据表冷器 的设计参数, 通常可选用低静压的自由式轴流风扇或静压相对较高的轴流风机。 就具体应用 而言, 多数风冷式大中型中央空调强制热交换所使用的是静压相对较高的单级轴流风机, 而 风冷式户用…

小型NAS搭建实例②——ubuntu server 的一些设置,包含NFS挂载,CIFS挂载,常用工具安装

ubuntu server 的一些设置 ubuntu server 的一些设置登录开启ssh 的root 登录切换root设置root密码安装vim编辑器修改ssh服务的配置文件重启ssh查询ip安装查询ip工具 net-tools安装ping命令工具登录ssh更新系统和软件 挂载共享存储挂载NFS共享存储truenas开启NFS共享在池里新建…

保姆级服务器安装宝塔面板教程

1、购买服务器 此处要记住自己的服务器系统型号。 2、远程连接服务器 通过服务器公网IP进行连接。 3、使用安装脚本安装宝塔 进入宝塔面板官网:https://www.bt.cn/ 复制对应服务器系统的安装脚本! 在终端工具中粘贴、回车开始进行下载&#xff01…

项目2.CentOS7虚拟机挂载本地光盘以及配置本地yum源

课程:Linux系统管理与服务配置 班级:2019物联网技术应用五年制1班 1.进入虚拟机设置->硬件选项-> CD/DVD选项中。 连接选项:勾选使用ISO映像文件,点击浏览按钮选择要挂载的ISO文件地址;设备状态选项&#xff…

双馈风机(DFIG)单机无穷大simulink仿真

双馈风机(DFIG)单机无穷大simulink仿真系统,属于基础程序,可以用来研究双馈风机故障时的短路电流,或者crowbar电路的运行,以及双馈风机的电压穿越,也可在上添加模块进行后续仿真。 提供相关电压…

Router OS 安装+配置软路由

准备工具:VMRouter os 镜像(https://download.csdn.net/download/cair2/10628759) 下面主要讲解一下Ros安装:默认账户admin,密码为空。 配置Ros, 1.查看网卡并且命名为wan 和 lan 2.为…

用OpenWrt软路由做旁路由-VMWARE版

1.环境准备 OpenWrt镜像 在vmware中安装的镜像源下载地址:openwrt-releases安装包下载_开源镜像站-阿里云本例使用的是22.03.2版本,下载地址https://mirrors.aliyun.com/openwrt/releases/22.03.2/targets/x86/64/openwrt-22.03.2-x86-64-generic-ext4…

第4章 OpenWrt-路由器虚拟机的安装

第4章 OpenWrt-路由器虚拟机的安装 本章内容介绍了如何在Windows 系统利用VMWare安装路由器虚拟机,相信很多同学在VMWare中安装过Ubuntu或者Windows. 4.1 为什么安装虚拟机 方便没有路由器硬件的同学进行代码测试路由器虚拟机提供了一种调试代码的环境&#xff0…

Digsilent双馈风机变风速详解

1. 打开Demo中的风机例子:DFIG-Model for Stability。 2. 要变风速需要在Composite Model中添加相应模块,为此要先打开风机的Composite Model。 里面可以看到该工程的所有复合模型。这个工程中只用到一个,因此仅有:A…

软路由系统怎么安装

软路由是一种基于软件的路由器系统,它可以通过安装在普通计算机或嵌入式设备上的软件来实现路由器的功能。软路由系统的安装相对来说比较简单,下面我们来介绍一下软路由系统的安装方法。 R86S-NVME-BLACK 软路由 第一步:选择合适的软路由系…
最新文章