简体   繁体   中英

8086 assembly related troubles

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).

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:

  • a byte when we use in al, dx
  • a word when we use in ax, dx
  • a dword when we use 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 ( 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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM