我read this tutorial。在本教程中,作者写了关于A20和启用它的不同方法。当他写下“快速A20方法”时,他说这是通过设置端口0x92中的第二位来完成的。以下是他给出的一段代码的例子:
mov al, 2 ; set bit 2 (enable a20)
out 0x92, al
现在,假设我要取消设置第二位并禁用A20,我该怎么做?
答案 0 :(得分:1)
您要查找的说明是AND
。如果使用AND
指令将所有位设置为1除了第2位,则将有效地将该位设置为0。
例如,
AL = 01011010B
BL = 11111101B
AND AL, BL
AL = 01011000B
或者,如果你想要翻转一下,无论它的当前值如何,只需将XOR
的所有位设置为0,除了你要翻转的位。
AL = 01011010B
BL = 00000010B
XOR AL, BL
AL = 01011000B
另外,为了将来参考,如果要强制为1,请使用OR
指令。
AL = 01011000B
BL = 00000010B
OR AL, BL
AL = 01011010B
作为旁注,我注意到您正在关注Brokenthorn操作系统开发教程。我建议坚持使用教程中解释的键盘控制器方法,因为它适用于更多硬件,并且在许多情况下使用起来更安全。我已将它发布在下面供您查看。
EnableA20:
PUSH AX
CLI
CALL .WaitA
MOV AL, 0xAD ; CMD: Disable PS/2 Port 1
OUT 0x64, AL
CALL .WaitA
MOV AL, 0xD0 ; CMD: Read Controller Output Port
OUT 0x64, AL
CALL .WaitB
IN AL, 0x60 ; READ: Controller Output Port
PUSH AX
CALL .WaitA
MOV AL, 0xD1 ; CMD: Write Controller Output Port
OUT 0x64, AL
CALL .WaitA
POP AX
OR AL, 0x02 ; WRITE: Controller Output Port
OUT 0x60, AL
CALL .WaitA
MOV AL, 0xAE ; CMD: Enable PS/2 Port 1
OUT 0x64, AL
CALL .WaitA
STI
POP AX
RET
.WaitA:
IN AL, 0x64
TEST AL, 0x02 ; Check Input Buffer Status
JNZ .WaitA
RET
.WaitB:
In AL, 0x64
TEST AL, 0x02 ; Check Output Buffer Status
JZ .WaitB
RET
要禁用A20行,请将行上的OR指令替换为WRITE
与AND
的注释,并反转这些位。要切换位,请使用XOR
。
答案 1 :(得分:0)
Adrian Collado的贡献中有一点不太清楚。
来自爆破区的例子有一点小错误。 0x92处有多个位。将所有其他设置为零可能会导致不必要的副作用。
首先,您应该读取该字节,设置该位并写回。
in al, 0x92
or al, 2
out 0x92, al
休息一下非常简单。
in al, 0x92
and al, 0xfd
out 0x92, al