Pregunta

I read this tutorial. In the tutorial the author writes about the A20 and different methods of enabling it. When he writes about the "fast A20 method", he says that this is done through setting the second bit in port 0x92. Here is the example he gives, of a piece of code that does this:

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

Now, suppose I want to unset that second bit and disable the A20, how would I do that?

¿Fue útil?

Solución

The instruction you are looking for is AND. If you use the AND instruction with all bits set to 1 EXCEPT the 2nd bit, you will effectively set the bit to 0.

For instance,

AL = 01011010B
BL = 11111101B

AND AL, BL

AL = 01011000B

Alternatively, if you want to flip a bit regardless of it's current value, simply do the XOR with all bits set to 0 except the one you want to flip.

AL = 01011010B
BL = 00000010B

XOR AL, BL

AL = 01011000B

Also, for future reference, if you want to force a bit to 1, use the OR instruction.

AL = 01011000B
BL = 00000010B

OR AL, BL

AL = 01011010B

As a side note, I noticed you are following the Brokenthorn Operating System Development Tutorials. I would recommend sticking with the keyboard controller method explained in the tutorials as it works on more hardware, and is in many cases safer to use. I've posted it below for you to look at.

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

To instead disable the A20 line, replace the OR instruction on the line with the comment saying WRITE with AND, and invert the bits. To toggle the bit, use XOR.

Otros consejos

There's one point not very clear in the contribution from Adrian Collado.

The example from brokenthorn has a little bug. There is more than one bit at 0x92. Setting all others to zero could result in unwanted side effects.

First you should read the byte, set that single bit and write back.

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

Resting the bit is very simmilar.

in  al,   0x92
and al,   0xfd
out 0x92, al
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top