I thought the i8080 had 8 16-bit IN ports and 8 16-bit OUT ports. Doesn't that mean the instructions
IN d8 ; only index 0-7?
OUT d8
can only take 8 possible values? What would it be indexing otherwise?
I thought the i8080 had 8 16-bit IN ports and 8 16-bit OUT ports. Doesn't that mean the instructions
IN d8 ; only index 0-7?
OUT d8
can only take 8 possible values? What would it be indexing otherwise?
I thought the i8080 had 8 16-bit IN ports and 8 16-bit OUT ports.
The 8080 does not have any I/O Ports. It's a microprocessor, not a microcontroller.
(Maybe the system you're playing with does have these 8+8 ports, but they are always external to the CPU)
The 8080 features a 16 bit data/program address space and an 8 bit I/O i/o address space. Or in other words it can address 64 KiB of memory and 256 I/O locations. Each of them with 8 Bit width.
in
and which are out
? Is it like 0-127 and 128-256 kinda thing?
The other answers explain it from a software perspective. Here is the hardware perspective, which may explain why it is another "address space".
The 8080 has 16 pins for the address bus A0
-A15
, 8 pins for the data bus D0
-D7
, and pins DBIN
and !WR
to time reads and writes. The processor re-uses the data bus to output information ("processor state") about what it will be using the address and data buses for; an additional pin called SYNC
is pulled high when this information is available. The remaining pins are for power, clock, reset, interrupts, and direct-memory-access.
Most systems using the 8080 would capture the processor state from pins D0
-D7
using a simple latch. Intel made a special chip (the 8212) that did the same thing, more expensively. Certain bits of the processor state were found to be so useful that later Intel processors dedicated pins just for their use; in particular, the IO/!MEM
pin which specified whether a read/write was to memory or to I/O space.
Some of the most common uses of the address and data buses were as follows:
When fetching the first byte of an instruction, the processor would output the (program counter) address on A0
-A15
, set D5
high, clear the other data bus bits, and then pulse SYNC
. This would be a signal to external hardware that an instruction fetch would occur. The address would remain on the address bus, and DBIN
would be pulsed. The memory was responsible to place the instruction byte on the data bus by the falling edge of DBIN
.
Reading from memory was a similar operation, except now D7
was pulled high in the processor state, rather than D5
.
Prior to a write to memory, the desired address was placed on the address bus, D1
was pulled high, the other data bus pins were pulled low, and SYNC
was pulsed. Then the data to be written was placed on the data bus, and !WR
was pulsed. The memory was responsible for capturing the data by the rising edge of !WR
.
IN
instructions have an 8-bit I/O address. When such an instruction occurred, the I/O address was placed on A0
-A7
, and an identical copy was placed on A8
-A15
. D6
was set high, the other data bus bits were cleared, and SYNC
was pulsed. This was a signal that the processor wanted to read from the I/O space. The address would remain on the address bus, and DBIN
would be pulsed. The peripheral was responsible to place the resulting byte on the data bus by the falling edge of DBIN
.
OUT
instructions placed their 8-bit addresses on A0
-A7
and A8
-A15
, set D1
and D4
, cleared the other data bus bits, and pulsed SYNC
. It then proceeded similarly to a write to memory.
By decoding the processor state bits, one could therefore separate the targets of IN
and OUT
instructions from ordinary memory. The was considered an additional "address space". Considering that ordinary memory is limited to 64k, you might need that extra address space. Intel even touted "512 Directly Addressed I/O Ports" -- which was true if your hardware distinguished the 256 IN
addresses from the 256 OUT
addresses -- but that was rarely done as it was an unnecessary complication.
Could you ignore the processor state bits, and just put everything into one address space? Certainly, and some systems did just that. However, such a scheme reduces the amount of general memory available to less than 64k.
The question of whether something is "memory" or "I/O" depends upon how it responds to various control signals. There is nothing that would prevent anyone from wiring an I/O device so that it would respond to a range of "memory" addresses, and for some kinds of I/O device that could be more useful than wiring it to the "I/O" read/write signals. On the other hand, an I/O device which is wired to behave as a memory device will respond to an instruction that writes to HL
whenever HL holds its address, without regard for whether HL was supposed to hold that address. An I/O device that response to I/O address 0x57 by contrast will only respond to an "out 57h" instruction, and the likelihood of the processor encountering that byte sequence by chance is smaller than the likelihood that HL might end up with a bogus address.
While it would have been possible to make the OUT nn
instruction take a two-byte address operand, that would have made the opcode bigger and slower while offering little benefit for most applications, especially given that the applications which would need more than 256 bytes of I/O space would also need to access I/O devices using register-based addresses and should thus likely be wired as "memory" devices.
A
register on the upper 8 bits of the address bus. Not useful for output of course.
The port number can take 256 possible operands. Apparently d8
means an 8-bit operand.
From the 8080 Assembly Programming Manual
The OUT
instruction has a similar description.
Seeing this line
IN d8 ; only index 0-7?
in some actual source code could mean that the particular hardware the program runs on implements (decodes) only the three least significant address bits, writing to a port address greater than 7 would wrap around to the [0..7] range, do weird things, or simply be ignored.