Code: Select all
mov ax, 0AAAAh ; Just a pattern to better see what it will be overwritten with.
mov dx, 01F0h ; ATA primary controller's Command Block ports start here.
in ax, dx ; I read a 16-bit value, now AX seems to be FFFF.
mov bx, ax ; I make a copy of that result in BX for later comparison.
mov ax, 0AAAAh ; I restore my pattern.
in al, dx ; Now I read just an 8-bit value into AL. After that, AX seems to be 0AAFFh, as expected.
xchg al, ah ; I swap the halves of AX before reading another byte into AL. Now AX is 0FFAAh.
inc dx ; I move on to the next ATA register, 01F1h.
in al, dx ; I read one byte from 01f1h into AL, and... AX is 0FF00h !!! WTF??? o_O
; A while ago, 01F0h contained 0FFFFh, which I guess was 01f0h=0FFh and 01f1h=0FFh.
; But now it says that 01F0h=FFh, but 01F1h=00h ?? What is going on here?
; Ok, let's double check by reading a word beginning at 01F1h:
mov ax, 0CCCCh ; Scratch pattern.
in ax,dx ; Now it turns out that 01F1h contains 0000h. So I guess 01F1h=00h and 01F2=00h ? Let's see:
mov ax, 0AAAAh ; Scratch pattern.
inc dx ; DX is now 01F2h, and this port is supposed to contain 00h. Now does it?
in al, dx ; AX is now... 00FFh, which means that 01F2h constains 0FFh :/
Well, not really an "assumption", since the Intel's manual itself states:
so my understanding of the paragraph quoted above is that the I/O space is pretty much a fancy array of 65536 bytes, each with its own address, and when I read two consecutive bytes from 01F0h and 01F1h, I should have gotten the same result as when I read one 16-bit word beginning from 01F0h (it would then read the least-significant byte from 01F0h, and the most-significant byte from 01F1h).Intel wrote:16.3 I/O ADDRESS SPACE
The processor’s I/O address space is separate and distinct from the physical-memory address space.
The I/O address space consists of 2¹⁶ (64K) individually addressable 8-bit I/O ports, numbered 0 through FFFFH. [...] Any two consecutive 8-bit ports can be treated as a 16-bit port, and any four consecutive ports can be a 32-bit port.
So why am I getting those weird, contradictory results?
Can anyone explain to me this strange behaviour?
My question is related to the fact that I've seen an actual code for reading sectors from the disk through ATA ports, which used the insw instruction to read two bytes at a time from the Command Block "data" register 01F0h into some memory buffer, and it worked just fine, no strange behavior. But I see that the "error code" register 01F1h is just next to the "data" register 01F0h, so I'm confused how is it that when insw is reading words from 01F0h, it doesn't read the 01F1h port as the higher half of the data word :q Am I missing something?