这可能是非常基本的,但我无法理解它。
我正在使用8255的A和B端口输入一个字。我有类似的东西:
PORT_A EQU 0008h // inputs low byte
PORT_B EQU 000Ah // inputs high byte
稍后在代码段中,我有一个部分执行此操作:
MOV DX, PORT_B
IN AL, DX
MOV AH, AL
MOV DX, PORT_A
IN AL, DX
MOV DX, AX
我在这里有几个问题。 MOV DX, PORT_B
有效地做了什么?它是否在DX中存储PORT_B的地址?为什么它在AL中输入B的高字节,然后将AL移到AH,而不是简单地将其写为IN AH, DX
?
对于端口A和B的地址,“0008h”和“000Ah”的明智选择是什么?我以前只使用8085组装,如果之前我选择了0008h(0000 0000 0000 1000b),那么我就不会选择000A(0000 0000 0000 1010b),因为A3位重叠(例如,I' d选择0001h(... 0001b)和0002h(.... 0010b),以便没有位重叠)。
答案 0 :(得分:3)
我使用8255的A和B端口输入单词
然后,您将从8255的A端口获取该字的低字节,并从8255的B端口获取该字的高字节。
要从任何端口获取任何内容,我们首先移动DX
寄存器中的I / O端口地址。然后,我们使用in
指令实际获取内容。这可以是:
in al, dx
in ax, dx
in eax, dx
这些是来自I / O端口的in
的唯一可能目的地。 (AH
不是一个选项!)
wallyk对您提供的代码做了很好的评论。所以我想你明白为什么以及如何。
我想补充的是,此代码可以进行优化。
PORT_A EQU 0008h // inputs low byte PORT_B EQU 000Ah // inputs high byte
鉴于上述端口地址,可以更直接地完成阅读该单词的任务。对于适合单个字节的I / O地址,从0000h到00FFh,根本不需要使用DX
寄存器。这些端口地址可以在in
指令本身中指定。
这提供了相当小的代码大小:
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
还有1个字节的短版本(8086编程只是喜欢空间保护)是:
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
答案 1 :(得分:2)
缺少的评论将是这样的
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
为什么它在AL输入B的高字节,然后将AL移到AH,而不是简单地将其写为IN AH,DX?
因为唯一的指令选择是
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
没有in ah, dx
。 x86指令集看起来正交,但是充满了半惊人的限制和限制。
答案 2 :(得分:0)
MOV DX PORT_B将常数(EQU创建一个常数)PORT_B的值移入16位寄存器DX。因此,AX获得的值为000Ah(基数为10)。 IN在低位字节上完成,因为000Ah足够小以适合AX的8位部分。 AH获取AL的值,以便在将PORT_A放入AL时保留PORT_B的值。