I/O ports are sort of like memory addresses, but are accessed differently, using IN and OUT instructions. The full story on modern hardware is very complicated, but accessing legacy devices in real mode is straightforward. Here's an example of how to read a scan code from the keyboard (technically, the keyboard controller).
Wait:
IN AL, 64H ; read keyboard status port
AND AL, 1 ; a key is ready when bit 0 is set
JZ Wait
IN AL, 60H ; read scan code
The port numbers 60H and 64H were established by IBM sometime before you were born, but every PC since then has mimicked this behavior in the name of backwards compatibility. Other legacy devices have fixed port numbers as well. Here's a fun one, if you've got a floppy drive:
MOV DX, 3F2H ; 3F2 is the floppy controller's control port
MOV AL, 10H ; turn on bit 4
OUT DX, AL ; start the floppy motor!
For port numbers bigger than 8-bits (e.g. 3F2), you have to put the port number in DX first (just a quirk of the instruction set). Again, the 3F2 assignment was fixed a long time ago with the introduction of the IBM PC.
Accessing today's devices on a modern bus is much, much trickier.