如何取消一点

时间:2014-02-02 21:33:42

标签: osdev

read this tutorial。在本教程中,作者写了关于A20和启用它的不同方法。当他写下“快速A20方法”时,他说这是通过设置端口0x92中的第二位来完成的。以下是他给出的一段代码的例子:

mov al, 2   ; set bit 2 (enable a20)
out 0x92, al

现在,假设我要取消设置第二位并禁用A20,我该怎么做?

2 个答案:

答案 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指令替换为WRITEAND的注释,并反转这些位。要切换位,请使用XOR

答案 1 :(得分:0)

Adrian Collado的贡献中有一点不太清楚。

来自爆破区的例子有一点小错误。 0x92处有多个位。将所有其他设置为零可能会导致不必要的副作用。

首先,您应该读取该字节,设置该位并写回。

in  al,   0x92
or  al,   2
out 0x92, al

休息一下非常简单。

in  al,   0x92
and al,   0xfd
out 0x92, al