Last modified: Mon Jun 15 15:23:12 UTC+0200 2026 © A. Tarpai
I/O PORT MOVE
I/O devices existing in the 8086 era (1979) were rather simple: mostly with an 8-bit data bus and a few address lines or just a chip-select. The 8086 was a little bit ahead of its time and utilized 64K I/O address space driving 16 address lines and could transfer not only 8- but 16-bit of word data in one cycle – to interface easily with both 8- and newer 16-bit data transfer capable I/O devices. The 8086 signals I/O transfer by driving bus type onto S2..S0 outputs for I/O access, so the bus controller and I/O devices recognize the I/O-bus transfer (address/data-lines are the same). The I/O space is not segmented and A19..16 is not driven.
The x86 I/O address-bus is 16-bit and this has not changed since.
8086 PORT I/O instructions
Implicit data movement between Accumulator and 8/16-bit data bus (CPU signals I/O access type, that is the difference).
- IN drives I/O-read bus transfer type
- OUT drives I/O-write bus transfer type
2 x 4 = 8 opcodes:
Fixed port: | Variable port:
8-bit PORT address is IMM8 | 16-bit PORT address in DX
________________________________|_____________________________
| | |
8-bit data: IN AL, imm8 | OUT imm8, AL | IN AL, DX | OUT DX, AL
| | |
16-bit data: IN AX, imm8 | OUT imm8, AX | IN AX, DX | OUT DX, AX
|
|
E4..E7 | EC..EF
_______________ ___________ | _______________
|1 1 1 0 0 1 d w| | IMM8 | | |1 1 1 0 1 1 d w|
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ ‾‾‾‾‾‾‾‾‾‾‾ | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
|
d=0 IN w=0 byte | d=0 IN w=0 byte
d=1 OUT w=1 word | d=1 OUT w=1 word
I/O instructions drive the lower 16-bit part of the address bus to transfer byte- or word data. The 16-bit effective address is either driven by the content of DX or an immediate 8-bit value following opcode (setting address high to zero):
Fixed port: Variable port:
IMM8 DX
+----+ +----+
| 0 | -->------------ A0 | 0 | -->------------ A0
| 1 | -->------------ .. | 1 | -->------------ ..
| 2 | -->------------ .. | 2 | -->------------ ..
| 3 | -->------------ .. | . | -->------------ ..
| 4 | -->------------ .. | . | -->------------ ..
| 5 | -->------------ .. | . | -->------------ ..
| 6 | -->------------ .. | . | -->------------ ..
| 7 | -->------------ A7 | . | -->------------ ..
+----+ 0 ----- A8 | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | 15 | -->------------ A15
0 ----- .. +----+ 0 ----- A16
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- A19 0 ----- A19
IN/OUT IMM8 IN/OUT DX
386 PORT I/O
No new opcodes*. But the 386 can transfer 32-bit data as well to/from accumulator: EAX.
IN/OUT AL <-- 8-bit I/O port W=0
IN/OUT AX <-- 16-bit I/O port W=1 operand-size = 16 (D=0 or D=1 and 66h)
IN/OUT EAX <-- 32-bit I/O port W=1 operand-size = 32 (D=1 or D=0 and 66h)
8-bit PORT address: IMM8 | 16-bit PORT address: DX
________________________________|_____________________________
| | |
8-bit data: IN AL, imm8 | OUT imm8, AL | IN AL, DX | OUT DX, AL
| | |
16-bit data: IN AX, imm8 | OUT imm8, AX | IN AX, DX | OUT DX, AX
| | |
32-bit data: IN EAX, imm8 | OUT imm8, EAX | IN EAX, DX | OUT DX, EAX
* The 386 address bus is 32-bits, but the I/O-bus has never been extended to 32-bits. PORT ADDRESS is still maximum 16-bit and still driven by DX or IMM8. I/O instructions drive the lower part of the address bus (driving zero onto HIGH lines):
Fixed port: Variable port:
IMM8 DX
+----+ +----+
| 0 | -->------------ A0 | 0 | -->------------ A0
| 1 | -->------------ .. | 1 | -->------------ ..
| 2 | -->------------ .. | 2 | -->------------ ..
| 3 | -->------------ .. | . | -->------------ ..
| 4 | -->------------ .. | . | -->------------ ..
| 5 | -->------------ .. | . | -->------------ ..
| 6 | -->------------ .. | . | -->------------ ..
| 7 | -->------------ A7 | . | -->------------ ..
+----+ 0 ----- A8 | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | . | -->------------ ..
0 ----- .. | 15 | -->------------ A15
0 ----- .. +----+ 0 ----- A16
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- .. 0 ----- ..
0 ----- A31 0 ----- A31
INS/OUTS
For INS/OUTS see REP.html.