Reputation: 369
This may be very basic, but I can't really understand it.
I'm using 8255's A and B ports to input a word. I have something like:
PORT_A EQU 0008h // inputs low byte
PORT_B EQU 000Ah // inputs high byte
Later on in the code segment, I have a part that does this:
MOV DX, PORT_B
IN AL, DX
MOV AH, AL
MOV DX, PORT_A
IN AL, DX
MOV DX, AX
I have several questions here. What does MOV DX, PORT_B
effectively do? Does it store PORT_B's address in DX? Why does it input B's high byte in AL, and then moving AL to AH, instead of simple writing it down as IN AH, DX
?
What is it takes makes "0008h" and "000Ah" wise choices for addresses for port A and B? I've only ever worked with 8085 assembly, and over there I wouldn't choose 000A (0000 0000 0000 1010b) if I'd chosen 0008h (0000 0000 0000 1000b) previously, because the A3 bit overlaps (for example, I'd choose 0001h (... 0001b) and 0002h (.... 0010b), so that no bits overlap).
Upvotes: 4
Views: 275
Reputation: 9899
I'm using 8255's A and B ports to input a word
You will be fetching then the low byte for the word from the 8255's A port and the high byte for the word from the 8255's B port.
To fetch anything from any port we first move the I/O port's address in the DX
register. We then use an in
instruction to actually fetch the content. This can either be:
in al, dx
in ax, dx
in eax, dx
These are the only possible destinations for an in
from I/O ports. (AH
is not an option!)
wallyk did a fine job commenting the code that you provided. So I think you understand the why and how already.
What I would like to add is that this code can be optimized.
PORT_A EQU 0008h // inputs low byte PORT_B EQU 000Ah // inputs high byte
Given the above port addresses, there's a more direct way to complete the task of reading the word. For I/O addresses that fit in a single byte, from 0000h to 00FFh, there is no need to use the DX
register at all. These port addresses can be specified within the in
instruction itself.
This gives a considerable smaller code size:
IN AL, PORT_B ; Fetch high byte from port B
MOV DH, AL ; Becomes high byte of end result in DX
IN AL, PORT_A ; Fetch low byte from port A
MOV DL, AL ; Becomes low byte of end result in DX
Still 1 byte shorter version (8086 programming just loves space conservation) is:
IN AL, PORT_B ; Fetch high byte from port B
MOV AH, AL ; Store in AH for now
IN AL, PORT_A ; Fetch low byte from port A
XCHG DX, AX ; Transfer AX to end result in DX
Upvotes: 3
Reputation: 57764
The missing comments would be something like this
MOV DX, PORT_B ; set up address of port B
IN AL, DX ; read high byte from port B
MOV AH, AL ; save result from port B as most significant byte
MOV DX, PORT_A ; set up address of port A
IN AL, DX ; read low byte from port A
MOV DX, AX ; DX = 16 bit result
Why does it input B's high byte in AL, and then moving AL to AH, instead of simple writing it down as IN AH, DX?
Because the only instruction choices are
in al, dx ; read 8 bits
in ax, dx ; read 16 bits
in eax, dx ; (32 bit mode only, i.e. 80386+) read 32 bits
There is no in ah, dx
. The x86 instruction set looks orthogonal, but is riddled with semi-surprising restrictions and limitations like this.
Upvotes: 2
Reputation: 245
MOV DX PORT_B moves the value of the constant (EQU creates a constant) PORT_B into the 16 bit register DX. So, AX obtains a value of 000Ah (10 in base 10). IN is done on the low order byte, because 000Ah is small enough to fit in the 8 bit portion of AX. AH obtains the value of AL so that the value of PORT_B can be preserved while PORT_A is put into AL.
Upvotes: 0