Besides memory, the 8086 has a separate I/O address space of 65536 byte ports, where devices such as the keyboard controller, the timer and the video card are connected. IN reads one of these ports into the accumulator: a byte into AL or a word into AX. A word read from port p takes the low byte from p and the high byte from p+1. No flags change.
Forms
The port number is either an immediate from 0 to FFh, written in the instruction, or the 16-bit value in DX, which reaches every port from 0 to FFFFh. The destination is always AL or AX: IN BL, 60h does not exist, and neither does IN AL, 3DAh (the number is too large for the immediate form; load it into DX).
IN AL, 60h ; the last byte the keyboard sentMOV BL, ALMOV CL, 4SHR AL, CL ; high nibbleCALL HEX1MOV AL, BLAND AL, 0Fh ; low nibbleCALL HEX1HEX1 PROC NEAR ; print AL (0..15) as a hex digitADD AL, '0'CMP AL, '9'JBE PUT1ADD AL, 7 ; 'A'..'F'PUT1:MOV DL, ALMOV AH, 02hINT 21hRETHEX1 ENDP
Waiting on a status bit
A common pattern reads a status port in a loop until a bit changes. On a VGA card, bit 3 of port 3DAh is set during the vertical retrace, the moment to update the palette or the screen without flicker.
MOV DX, 3DAh ; VGA input status register 1WAITR:IN AL, DXTEST AL, 08h ; bit 3: vertical retrace in progress?JZ WAITR
Pitfalls
Reading a port can have side effects: some devices clear a status or advance an internal pointer when read, so read only what you mean to. A port is not memory; reading it twice can give two different answers. Under DOSBox the ports are emulated, but the common PC ones behave as on real hardware.
Later CPUs
The 80186 adds the string forms INSB and INSW (with REP, a block read into ES:DI). The 80386 reads 32 bits with IN EAX, DX. In protected mode the I/O privilege level, and on the 80386 the I/O permission bitmap, decide whether a program may use a port.