`

(第三章 4)A20地址线

阅读更多

     A20地址线困惑我了很久,这篇文章终于揭开了这个谜团。详细阐述之前,我先来总结一把—— 8086/8088和80286地址转换方式一样,寻址范围不一样
    8086/8088和80286中“逻辑地址-->线性地址”的转换方式是一样的:segment:offset-->segment<<4+offset,而且segment和offset均只有16bit. 只不过因为8086/8088是20位地址总线,而80286是24位地址总线,故地址范围有点不一样:
        (1)8086/8088寻址范围是0~1M(在8086/8088中1M以上的extend memory地址回回绕到1M内的模值);
    (2)80286寻址范围是0~1M~10FFEFh -->注:虽然80286有24根地址线,但实际上只用了21根,浪费了3根,这是由于寻址方式的牵制。

 

1 先看看 real mode 的寻址方法

8086/8088 的地址线有 20 条:A0 ~ A19,意味着 processor 可以将 20 位地址放上这 20 条地址线上,它的寻址能力是 1M (00000 ~ FFFFF),它的寻址方法是:segment:offset ,这是一种被称为 logic address (逻辑地址)表示法,它需要转化为 processor 的 linear address(线性地址)表示:

segment:offset ---------> segment << 4 + offset

如:F000:FFFF = F0000 + FFFF = FFFFF ,这是 8086/8088 所能访问的最高地址。这种表示方法是 Intel 为了在 16 位 real mode 下能够访问 20 位地址空间 所想设计出来的计算方式。

因此,8086/8088 的寻址范围是可以表示为:从 0000:0000 ~ 0000:FFFF 开始到 F000:0000 ~ F000:FFFF

2 访问 extended memory——1M及其以上地址

在后续的 80286 上,Intel 实现了 24 位的 Address bus,那么在 real mode 下 80286 能够访问到的最高地址是 10FFEF,这个地址值是由下面的方法而来:

FFFF:FFFF = FFFF0 + FFFF = 10FFEFh

这已经是 logic address 所能表达的极限范围了。100000h 以上的内存被称为 extend memory,从 100000h ~ 10FFEFh 这片内存区域在 DOS 下被称为 High Memory(高端内存)。高端内存是 80286 在 real mode 所能访问到的区域,而 8086/8088 所不能访问到的。

3 wraparound 现象——只有A0~A19上的信号有效

当在 8086/8088 下执行 FFFF:FFFF 这个内存寻址时,会产生什么结果呢?

       
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0
0
0
1
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
1

结果很明显:由于 8086/8088 只有 20 条 address bus,地址 10FFEF 的高 4 位会被抛弃,实际上送上 address bus 的只有 0FFEFh 值,所以访问 FFFF:FFFF 地址结果只能访问到 1M 以内的地址。这就是 wraparound 现象:访问 1M 以上地址都会回绕到 1M 内的模值。

那么,当 80286 下访问 FFFF:FFFF 地址时,又会产生什么果呢? 由于 80286 具有 24 条 address bus,对于 FFFF:FFFF 地址的访问,会正确得到访问。

SO,访问 FFFF:FFFF 内存,使得 8086/8088 下产生 wraparound 现象,变相访问 0FFEF 地址内存。而在 80286 下得到正确的的 10FFEF 地址,不存在 wraparound 现象。因此:wraparound 现象在 8086/8088 才会产生。这样产生的问题是:访问高端内存时,80286 在 real mode 下和 8086/8088 的行为不一致!

4 引入 A20 Gate

为了使用 80286 和 8086/8088 在 real mode 下的行为一致,即:在 80286 下也产生 wraparound 现象 。IBM 想出了古怪方法:当 80286 运行在 real mode 时,将 A20 地址线(第 21 条 address bus)置为 0 ,这样使得 80286 在 real mode 下第 21 条 address line 无效,从而人为造成了 wraparound 现象。

具体实现方法是:

设立一个 AND Gate (与门电路),AND gateIN 输入端中一端接 A20 line 上,另一端接在 keyboard control 8042 上,而 AND gate 的 OUT 输出端接在 A20 line 上。只有两个 IN 端都为 1 时,OUT 端才为 1

A20 Gate

A20 line 一直处于 1 状态(High 电平),而 8042 内的 A20 gate 一直处于 0(Low 电平),因此:必须使 Keyboard controller 8042 内的 A20 Gate 处于 high 时,A20 line 输出才有效。 A20 gate 也被称为 A20 MASK#。

SO,Keyboard Controller 8042 增加了一组命令去控制 A20 Gate 的开/关,给 8042 发送命令 0xDF 置 A20 gate 有效,给 8042 送命令 0xDD 置 A20 gate 无效。

现在的 system 中,南桥芯片的 A20 MASK# 缺省都是 MASK 状态,即:A20 gate 缺省都是开的。

5 打开 A20 gate

在 OS 的 boot 阶段一般都要做打开 A20 gate 操作,虽然现在 A20 gate 缺省为开的。

打开 A20 gate 的方法最原始的是给 keyboard controller 8042 发送 A20 gate enable 命令字,就是上面所说的 0xDF 命令。

下面是我在 mouseOS 操作系统项目中 keyboard 驱动里的一小段代码(编译器是 nasm):

;-----------------------------------
; macro: WAIT_STATUS_FOR_WRITE
;-----------------------------------
%macro WAIT_STATUS_FOR_WRITE 0
%%wait_status_for_write_loop:
        IO_DELAY
        in al, I8402_STATUS_PORT
        bt rax, 1
        jc %%wait_status_for_write_loop
%endmacro


;-------------------------------------------------------
; macro: WRITE_BYTE_TO_I8402
; description:
;               send byte to keyboard contrroler (I8402)
;-------------------------------------------------------
%macro WRITE_BYTE_TO_I8402 1
        WAIT_STATUS_FOR_WRITE
        mov al, %1
        out I8402_COMMAND_PORT, al
%endmacro

 


;-----------------------------------------
; keyboard_enable_a20()
;-----------------------------------------
__keyboard_enable_a20:
        WRITE_BYTE_TO_I8402 I8402_ENABLE_A20_CMD       ; send 0xDF to I8402
        ret

这个代码实现很简单,向 0x64(I8402 write 端口)发送 0xDF 命令,这是控制 keyboard controller I8402 A20 gate 的其中一种方法。

另一种方法是:通过写 I8402 的 output 端口,直接置 I8402 的 pin 21 (对应于 A20 gate line),同样来自 mouseOS 中的代码(nasm 编译器)

;-----------------------------------
; macro: WAIT_STATUS_FOR_WRITE
;-----------------------------------
%macro WAIT_STATUS_FOR_WRITE 0
%%wait_status_for_write_loop:
        IO_DELAY
        in al, I8402_STATUS_PORT
        bt rax, 1
        jc %%wait_status_for_write_loop
%endmacro

;-----------------------------------
; macro: WAIT_STATUS_FOR_READ
;-----------------------------------
%macro WAIT_STATUS_FOR_READ 0
%%wait_status_for_read_loop:
        IO_DELAY
        in al, I8402_STATUS_PORT
        bt rax, 0
        jnc %%wait_status_for_read_loop
%endmacro


;-------------------------------------------------------
; macro: WRITE_BYTE_TO_I8402
; description:
;               send byte to keyboard contrroler (I8402)
;-------------------------------------------------------
%macro WRITE_BYTE_TO_I8402 1
        WAIT_STATUS_FOR_WRITE
        mov al, %1
        out I8402_COMMAND_PORT, al
%endmacro


;------------------------------------------------------
; macro: WRITE_BYTE_TO_I8408
; description:
;               send byte to keyboard encoder (I8408)
;------------------------------------------------------
%macro WRITE_BYTE_TO_I8408 1
        WAIT_STATUS_FOR_WRITE
        mov al, %1
        out I8408_COMMAND_PORT, al
%endmacro

;------------------------------------------------------
; macro: READ_BYTE_FROM_I8408
; description:
;               read byte from keyboard encoder (I8408)
;------------------------------------------------------
%macro READ_BYTE_FROM_I8408 0
        WAIT_STATUS_FOR_READ
        in I8408_DATA_PORT
%endmacro

 

;-----------------------------------------
; __enable_a20() with 0xD0/0xD1
;-----------------------------------------
__enable_a20:
; 1: send read_output_port command to 8402 (0x64)
        WRITE_BYTE_TO_I8402 I8402_READ_OUTPUT_CMD

; 2: read byte from 8408 (0x60)
        READ_BYTE_FROM_I8408
        mov ah, al

; 3: send write_output_port command to 8402 (0x64)
        WRITE_BYTE_TO_I8402 I8402_WRITE_OUTPUT_CMD

; 4: set A20 gate line
        mov al, ah
        or al, 2

; 5: send to data port (0x60)
        WRITE_BYTE_TO_I8408 al
        ret

在 __enable_a20() 代码中,首先向 8402 发送 read output port 命令,然后从 0x60(8408 的数据端口)读出 output port 里的数据,将其它的 bit1 置为 1。再向 8402 发出 write output port 命令,将该数据写向 0x60(8408 的 data port)。

上面的方法都是基于 keyboard controller 来实现的,这是比较正统的实现方法。一个新的 fast A20 gate 方法,但是这种方法不是通用的方法。在一些系统可能得不到正确的结果

;----------------------------------------
; macro: A20_ENABLE
; descriptor:
;            Fast A20 gate enable
;----------------------------------------
%macro A20_ENABLE 0
        in al, SYSTEM_CONTROL_PORT          ; port - 0x92
        or al, 0x02
        out SYSTEM_CONTROL_PORT, al       
%endmacro

6 打开 A20 gate 的必要性

打开 A20 gate 是为了在 80286/286+ 以后的 processor 上使用 protected mode 来访问完全的 24/24+ 位地址空间,如:在 32 位 protected mode 下,在不打开 A20 gate 的情况下,Bit20 为 0,导致 Bit20 留下一个空位。

1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

 

转载自:http://www.mouseos.com/arch/002.html


所有权限 mik 所有,转载请注明出处!

 

分享到:
评论

相关推荐

    第7章 高级汇编语言程序设计.doc

    相反,从保护模式回到实模式,需要清除CR0的第0位,关闭A20地址线,并恢复DS寄存器以指向正确的数据段。 在汇编语言中,这些操作通常通过宏定义来实现,例如`JUMPFAR`用于段间跳转,`ENABLE_A20`和`DISABLE_A20`宏...

    汇编语言程序设计及上机指导 第7章 高级汇编语言程序设计.ppt

    - 在实模式到保护模式切换中,启用A20地址线至关重要,因为它允许访问超过1MB的内存空间。 6. **CR0寄存器**: - CR0是控制寄存器,其中的第0位(PG位)设置为1会启动分页机制,这是从实模式进入保护模式的关键...

    x86 x64体系探索及编程part4

    134 8.6 实模式下的执行环境 135 8.7 实模式下的IVT 135 8.8 突破64K 段限 136 8.9 A20 地址线 137 第 9 章 SMM系统管理模式探索 138 9.1 进入SMM 138 9.2 SMM 的运行环境 141 9.2.1 SMRAM 区域 141 9.2.2 SMM 执行...

    中考数学复习课件试题 第三章 函数精选.doc

    平面直角坐标系被分成四个象限,从右上到左下分别是第一象限(I)、第二象限(II)、第三象限(III)和第四象限(IV)。点A(a+1, b-2)位于第二象限意味着 a+1且 b-2&gt;0,因此 a且 b&gt;2。 【函数的定义域】 函数的定义...

    第一章从开机加电到Main函数执行前 《linux内核设计的艺术》的笔记内容

    4. 打开A20线,这是为了启用32位地址线,使得CPU能够访问超过1MB的内存空间。 最后,当所有这些工作完成后,系统已经准备好执行32位代码,这通常是从加载并执行Head.s开始,这是一个汇编语言写的初始化程序,为运行...

    x86 x64体系探索及编程part3

    134 8.6 实模式下的执行环境 135 8.7 实模式下的IVT 135 8.8 突破64K 段限 136 8.9 A20 地址线 137 第 9 章 SMM系统管理模式探索 138 9.1 进入SMM 138 9.2 SMM 的运行环境 141 9.2.1 SMRAM 区域 141 9.2.2 SMM 执行...

    ePUBw.COM+-+Linux+内核设计的艺术(第2版).新设计团队.机械工业出版社.2013-5-11

    3. 第三章讲述了进程1的创建和执行,包括进程0如何创建进程1,设置进程1的分页管理,共享文件,以及首次进程调度的机制。 4. 第四章进一步扩展到进程2的创建,包括打开设备文件,创建进程2,加载shell程序,以及...

    x86 x64体系探索及编程 part2

    134 8.6 实模式下的执行环境 135 8.7 实模式下的IVT 135 8.8 突破64K 段限 136 8.9 A20 地址线 137 第 9 章 SMM系统管理模式探索 138 9.1 进入SMM 138 9.2 SMM 的运行环境 141 9.2.1 SMRAM 区域 141 9.2.2 SMM 执行...

    x86 x64体系探索及编程part1

    134 8.6 实模式下的执行环境 135 8.7 实模式下的IVT 135 8.8 突破64K 段限 136 8.9 A20 地址线 137 第 9 章 SMM系统管理模式探索 138 9.1 进入SMM 138 9.2 SMM 的运行环境 141 9.2.1 SMRAM 区域 141 9.2.2 SMM 执行...

    第二章招标设备清单及参数要求.doc

    招标文件中的"第二章招标设备清单及参数要求.doc"详尽列出了一个演播室建设项目的设备需求,包括各种高清摄录设备、灯光、音响、控制设备以及辅助配件。以下是对这些设备及其参数的详细解析: 1. 高清摄录一体机:3...

    Linux初始值设置

    7. **A20地址线的开启**:开启A20地址线,使得处理器能够访问超过1MB的内存空间。 8. **设置进入32位保护模式运行**:最后,系统会从实模式转换到32位保护模式,以利用更多的内存和更高级的内存管理机制。 在完成...

    微机单元测试题与复习大纲(PPT上复制的,方便打印).doc

    【第三章测验知识点】 1. 定义变量的伪指令:db 用于定义字节变量,dw 用于定义字变量。 2. 标号属性:段、偏移和距离,距离属性包括 far 和 near。 3. 获取变量 TABLE 的段属性指令 mov bx, seg table,类型属性...

    2022高中数学全程复习第六章第二节等差数列.pptx

    2. 前n项和Sn可表示为Sn=n^2/2*d+n/2*(2*a1-d),它是n的二次函数,其图像为抛物线的一部分。 等差数列的性质和公式在解题时非常关键,例如在题组一中: 1. 错误。只有当这个常数为零时,数列才可能是等差数列。 2. ...

    四川省成都市高中数学第1章计数原理1.3.4二项式系数性质习题课限时练新人教A版选修2_32018072719

    题目中第4项与第8项的系数相等,意味着 `C(n, 3) = C(n, 7)`,从而可以解出 `n` 的值,进一步确定系数最大的项。通常情况下,当 `n` 是奇数时,中间项的系数最大,是`C(n, n/2)`。 3. 展开式 `(x + 2)(2x + 3)^10` ...

    哈工大操作系统实验linux实验一启动系统.docx

    setup.s的功能更加复杂,包括读取机器状态、移动system模块、设置IDTR和GDTR以开启A20线,重新配置中断控制器,并最终通过设置CR0寄存器进入32位保护模式。一旦这些步骤完成,控制权将交给system模块的头部head.s...

    clk11c.pdf linux 0.11内核学习手册

    - **setup.s**:这部分代码主要完成硬件初始化的任务,比如设置中断向量表、打开A20线等操作,是连接引导扇区和内核主体之间的桥梁。 - **head.s**:包含了内核的启动代码,负责初始化段寄存器、设置堆栈等基础任务...

Global site tag (gtag.js) - Google Analytics