OS boot 的时候为什么要 enable A20?

请问OS boot的时候 enable A20的意义是? 我知道enable A20后,real mode下,可以访问到第21位地址。那么如果我在跳转到protect mode前,不访问第21位,可以不打开A20么?跳转后的代码会因没打开 A20,而被影响么? ========================================= 以下是 boot.S 的代码,我把enable A20那一段注释了,目前来看OS运行正常。(目前这个OS刚实现到分页机制, mit 6.828 lab2) #include <inc/mmu.h> # Start the CPU: sw…
关注者
63
被浏览
2525

2 个回答

不访问当然可以不开——说的就是那些legacy software

但是你一个bootloader干嘛不开呢?跟内存过不去?

--

先谈A20的背景


还记得8088/8086有多少根地址线不?20根.


那16位寄存器怎么表示20位的寻址空间呢?Intel用了分段的方法——segment:offset. 实际的地址是segment << 4 + offset.


举例说明,1000:FF03 表示的地址是 0x1000 << 4 + 0xFF03 即 0x1FF03


那这种方法,填满F表示的地址是多少呢?FFFF:FFFF = 0xFFFF << 4 + 0xFFFF = 0x10FFEF.

你注意看 0x10FFEF 的二进制表示——它逆天地有一个第20位!在8088/8086上面,那个第20位被直接忽略掉了——因为就是没有这根线嘛,所以最终得到的地址是除掉这个第20位的,即0xFFEF.


但是在80286中,Intel把地址线扩展成24根了,FFFF:FFFF真的就是0x10FFEF了,你让那些legacy software怎么活?!本来人家想读0xFFEF的,怎么成了0x10FFEF?不是人家不想好好工作,是你硬件设计的不让人家好好工作嘛。


于是,“聪明的IBM工程师” 就想,你不是喜欢被truncate么,不是想把第20位拿掉么,那我默认就给你关掉这一位不就好啦,啥时候想用啥时候开开。


乃们看出来了没?A20 是 80286 时代照顾8088软件的产物。通常所说的32位保护模式是 80386 才出现的,所以,A20跟保护模式毛关系都没有!开不开都一样进,影响的只是第20位而已



--
不开的话,保护模式下第21位会不会总是被清0,或者21-32位总是为0

第20位总是0(从0开始数数好么),21-31位不变

但是Real Mode Addressing只有24位,所以其实是21-23位不变,高八位管不到了


--

测试A20是否默认开启:
gist.github.com/sakamot

测试结果:

Bochs 2.6.7 Win Prebuilt: 默认开 (但是bochs有个编译选项可以选择是否有A20这个东西,不清楚我用的预编译版是不是选了)

VMWare Workstation 11.0.0 build-2305329: 默认关

QEMU 1.1.2 (Debian 1.1.2+dfsg-6a+deb7u6): 默认开

Hyper-V bundled with Win 8.1 Update, Gen 1: 默认开

本子没法关UEFI,不试了


附代码供各位没法上gh的老爷看


; NASM
[bits 16]
 
org 0x7c00
 
    mov ax, cs
    mov ds, ax
    mov es, ax
 
    call check_a20
    test ax, ax
    mov ax, A20On
    jnz Print           ; Enabled
    mov ax, A20Off
 
Print:
    mov bp, ax
    mov cx, 16
    mov ax, 0x1301
    mov bx, 0x000c
    mov dl, 0
    int 0x10
    
    cli                 ; Shutdown
    hlt
 
 
 
check_a20:
    push ds
    push es
    push di
    push si
 
    cli
 
    xor ax, ax ; ax = 0
    mov es, ax
 
    not ax ; ax = 0xFFFF
    mov ds, ax
 
    mov di, 0x0500
    mov si, 0x0510
 
    mov al, byte [es:di]
    push ax
 
    mov al, byte [ds:si]
    push ax
 
    mov byte [es:di], 0x00
    mov byte [ds:si], 0xFF
 
    cmp byte [es:di], 0xFF
 
    pop ax
    mov byte [ds:si], al
 
    pop ax
    mov byte [es:di], al
 
    mov ax, 0
    je check_a20__exit
 
    mov ax, 1
 
check_a20__exit:
    pop si
    pop di
    pop es
    pop ds
 
    ret
 
A20On:
    db "A20 is On        "
A20Off:
    db "A20 is Off       "
 
times 510-($-$$) db 0
 
db 0x55
db 0xaa
不开A20是不行的,下表是打开和不打开A20时访问地址的情况:

代码中的物理地址 实际的物理地址(开A20 实际的物理地址(关A20
0x00080000          0x00080000             0x00080000
0x00100000          0x00100000             0x00000000
0x00180000          0x00180000             0x00080000
0x00200000          0x00200000             0x00200000
0x00280000          0x00280000             0x00280000
0x00300000          0x00200000             0x00200000
0x00380000          0x00280000             0x00280000



所以,不打开A20的话,相当于A20那一位永远都是0,相当于物理内存里有一半的空间你无法使用,并且如果你使用地址时,必须务必小心,否则会访问到另一部分物理地址上,这对于代码来说是难以接受的。

所以原则上,A20一定要开。

当然,如果不开A20是否一定就会有问题呢?答案是,不一定。因为A20实际上老的BIOS里的一种设置,新的BIOS基本上都是A20默认打开,所以代码里即使不处理A20也不一定会有问题。

如果要测试,可以拿bochs或者vmware之类的进行测试。

有些回答把第20位和第20位以及更高的部分(高12位)弄混,注意了,Intel的手册上明确写是第20位,不是高12位

A20M# pin — On an IA-32 processor, the A20M# pin is typically provided for compatibility with the Intel 286 processor. Asserting this pin causes bit 20 of the physical address to be masked (forced to zero) for all external bus memory accesses. Processors supporting Intel Hyper-Threading Technology provide one A20M# pin, which affects the operation of both logical processors within the physical processor. The functionality of A20M# is used primarily by older operating systems and not
used by modern operating systems. On newer Intel 64 processors, A20M# may
be absent.

同时也提到了,在一些新的处理器上A20问题已经没有了。

内容摘自:
Intel® 64 and IA-32 Architectures Software Developer's Manual
Volume 3A: System Programming Guide, Part 1
8.7.13.4 External Signal Compatibility