I am reading the manual, and it's a bit complex. I can't understand the machine code encoding for the life of me, but that's not my main concern ... my main concern is the address/data buses.

I do not understand the difference between the "address out" from the OUT instruction, and the port configuration as well, AND the involvement of the register data operands.

Quoted directly from the z80 manual:

The contents of register C are placed on the bottom half (A0 through A7) of the address bus to select the I/O device at one of 256 possible ports.

Question time:

1.What does "the bottom half" mean?

2.Where/what are the 256 possible ports, and how does it select one, and where does it go exactly from there?

Next quote:

If the contents of register C are 01H, and the contents of register D are 5AH, at execution of OUT (C),D byte 5AH is written to the peripheral device mapped to I/O port address 01H.

So if I have 1 in register C, and 90 in D, and I write OUT(C), D 90 is written to the something mapped to 1? How do I know what is mapped at 1?

PS: Also, if I have hardware at mapped address 1, where does 90 (the value represented) go to in that hardware?

Do not get me wrong by my confusion here, I am a programmer ... I just have very limited experience coding at this low-level, and just need some clarification.


4 Answers 4


The versions of the IN and OUT instructions which include an I/O address only allow the bottom 8 bits of the address to be specified in the instruction. For that reason, most Z80-based I/O hardware ignores any address bits beyond the bottom 8, and in most cases programmers don't worry about what the processor does with the upper 8 bits. In actuality, the Z80 outputs BC as an address (as it would for e.g. LD A,(BC)), but if hardware doesn't care about the upper address bits there's no reason for programmers to care about what the B register contains. Incidentally, I don't think OUT nn,A always outputs zero on the upper address bits; I vaguely recall it outputs the I value, but I'm not sure. What's important is that if I/O decoding hardware cares about the upper address bits, code should always use the OUT (BC),r form of the instruction and make certain B is loaded suitably.

EDIT -- A further clarification about addressing: when code executes an instruction like LD (BC),A or OUT (C),A, the Z80 doesn't really care what the address in BC "means". The Z80 drives the address bus with the contents of the BC register, puts the contents of the A register onto the data bus, and asserts a combination of signals that indicate either "memory write" or "I/O wrote". Each memory or device needs to be connected with hardware to let it know what, if anything, it is supposed to do with any given request; it must do so in such a fashion that it will ignore any requests which are directed toward other devices, but that does not mean it will necessarily ignore requests directed at all "unused" addresses. For example, if the only I/O devices in a system were two UART chips, each of which had four I/O addresses, a system designer might design things so that any I/O request where address bit 7 was low would access the first chip, using address bits 0-1 to select a function, and any request where address bit 7 was high would access the second. The designer might specify that the first chip used addresses 00h-7Fh, and the second used 80h to 0FFh, but in reality the first chip would respond to addresses 04h, 08h, 0Ch, 10h, ... 7Ch, just as it would to 00h; it would likewise respond to 05h, etc. just as it would to 01h. Making the chip ignore writes to addresses in the range 04h-7Fh would require more hardware than simply having such addresses "shadow" the functions of the specified ones.

  • 2
    \$\begingroup\$ An interesting story related to this is that the Amstrad CPC series were wired such that it was the 'extra' upper 8 bits in B that were used to select the address, and C wasn't used for addressing. They could then, in one fell swoop, perform LD BC,(addr << 8) | data and then OUT (C),C - thus effectively performing OUT (B),C. An interesting micro-optimisation created by rather strange hardware design in both the CPC and the Z80 itself. \$\endgroup\$ Oct 1, 2015 at 13:05
  • 1
    \$\begingroup\$ That's somewhat clever, though unless one was fetching BC as a 16-bit value I'm not sure what advantage that would have over LD A,data / OUT (addr),A. The BC form would take 10 cycles to do the load and 8 to fetch the OUT (plus the time to execute it); the A form would take 7 to do the load and 7 to fetch the OUT. I don't think the time to finish executing the OUT is four cycles longer in the A case. \$\endgroup\$
    – supercat
    Oct 1, 2015 at 15:28
  • 1
    \$\begingroup\$ Hmm, good point: By my reading of the manual, the A and BC methods take 18 vs 22 T states resp. I'm not sure I ever checked the timings! Maybe this isn't clever after all... just a quirk of how the CPC was wired up. In that case, I'd have to recant calling it a "micro-optimization". \$\endgroup\$ Oct 1, 2015 at 15:44
  • 1
    \$\begingroup\$ @underscore_d: Thinking about it more, I'm not sure what advantage using the upper address bits gives. A trick that is sometimes useful is to use address bits as data; for example, if for eight outputs, instead of using a 74LS373 that grabs the data bus, one uses a 74LS259 addressable latch wired to the bottom 4 address bits, one can set or clear any bit with "OUT (xx),A" without having to load "A" with any particular value first. Steve Wozniak liked using that trick a lot in the Apple ][, though I've not seen it used a whole lot elsewhere for some reason. \$\endgroup\$
    – supercat
    Oct 1, 2015 at 16:41
  • 1
    \$\begingroup\$ Now that's a micro-optimisation! As for the CPC thing, it seems some devices - which I never worked with during my time programming it - do use bits in the lower 8, too: cpcwiki.eu/index.php/Default_I/O_Port_Summary Although those all seem to be for add-on peripherals. Elsewhere the lower 8 are irrelevant. \$\endgroup\$ Oct 1, 2015 at 19:00

The address bus of the Z80 is 16-bits wide (bits A0 through A15), meaning it can address 65536 locations. The low 8 bits of the bus are bits A0-A7, which can address 256 locations. Each of the I/O ports connected to the Z80 has a corresponding address of 0-255 (256 total addresses). Only one port responds to a particular address.

If the contents of register C are 01H, and the contents of register D are 5AH, at
execution of OUT (C),D byte 5AH is written to the peripheral device mapped to I/O port
address 01H.

The address of the peripheral (01) will be placed on the address bus A0-A7. The contents of the D register will be placed on the 8-bit data bus, and written to the peripheral whose port number is 01.

  • \$\begingroup\$ What do you mean bits A0 through A15? Aren't those pinouts? Also, what if the peripheral has no port number 01? What will happen in such a situation? \$\endgroup\$
    – user33553
    Dec 2, 2013 at 21:55
  • \$\begingroup\$ @JumpifnotEqual A0-A15 are pinouts from the microprocessor which can be connected to either peripherals or memory (there are two other pins -- IORQ and MREQ -- that determine whether an I/O port or memory is being addressed). They are driven by the contents of an internal register in the microprocessor called the address register. Depending on the instruction, the address register may contain either the 8-bit address of an I/O port, or a 16-bit address in memory. If there are no peripherals corresponding to address 01 the I/O instruction will have no effect. \$\endgroup\$
    – tcrosley
    Dec 3, 2013 at 13:19
  • 1
    \$\begingroup\$ @JumpifnotEqual Here is a PDF Z80 manual. www.zilog.com/manage_directlink.php?filepath=docs/z80/um0080 Look at page 5, upper right side of the figure. A0 to A15. \$\endgroup\$ Sep 15, 2015 at 15:32
  1. It's called "bottom half" because these eight address lines are the lower 8 of the 16 address lines.

  2. What the ports are depends on your system, it can be anything. There is some logic hardware in your system that selects the port for the addresses. Usually there is some decoder for the upper bits of the address, and its outputs go to the chip select input (CS) of the chips that implement I/O. The lower bits go directly to the chips to select one of several registers within each.

What the hardware does with the value you write to some port is arbitrary. It could store that value, but it could also cause some arbitrary action.

So you need to read the documentation for your hardware to know what the ports do.

  • \$\begingroup\$ Are "address lines" and "pins" the same thing here? Because A0-A15 are lower-bottom pins of the microprocessor. \$\endgroup\$
    – user33553
    Dec 2, 2013 at 21:57
  • \$\begingroup\$ A0 - A15 are the names given to the 16 lines of the address bus. The pins on the IC package are labelled with both the signal name, and the pin number. If the processor is available in different packages, the pin number for a given signal may vary between packages. \$\endgroup\$ Dec 2, 2013 at 22:37

Typically some of the address lines will go to some logic which will produce chip select signals based on the address which are then used to enable or select the input or output devices.

When an output device receives a chip select signal and the I/O Write signal, the data on the data bus will be written into that output device - what the device does with the data depends on the particular device.

The system designer will decide what I/O addresses corresponds to what I/O device. If the programmer writes to an unused I/O address, the data written will just fall into the bit bucket.

  • \$\begingroup\$ It's rare for the hardware in Z80 systems to fully decode I/O addresses. Hardware will generally examine enough address lines to distinguish among all functions that need to be distinguished; generally, this means that only ~3-6 address wires will be used, and ~2-5 will go unused. Any address where an unused address bit is a "1" will generally behave the same as would an otherwise-identical address where the unused bit is a "0". \$\endgroup\$
    – supercat
    Dec 2, 2013 at 23:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.