Download zmac.zip
(version 26sep2010)

zmac - Z-80 Macro Cross Assembler

zmac has been around for a long time. My version runs under Windows (XP or Vista and probably older versions), has a few bug fixes but is most notable for the extensions I've added. There are two new psuedo-ops.

assert expr   Stop assembly if expr is non-zero.
settexprSet the current T-state count to expr
setocfexprSet the current opcode fetch count to expr
tstateexprOld form of sett

And a number of new operators and functions.

==Equality
!=Inequality
<=Less-than or equal to
>=Greater-than or equal to
<Less-than
>Greater-than
!Logical not
t(expr)Current count of T-states up to memory location expr
tilo(expr)Low count of T-states used by instruction as memory location expr
tihi(expr)   High count of T-states used by instruction as memory location expr
ocf(expr)Current count of opcode fetches up to memory location expr

The best description of the T-state counting macros can be found at the end of my cycle counting tutorial. Might also explain why you would want such a feature. setocf and ocf() are newer features not covered there. They're needed when counting clock cycles on the TRS-80 Model 4 when it runs in high speed (4 MHz) mode. While the Z-80 mostly runs twice as fast in that the opcode fetch portion of each instruction is slowed down by 2 wait states. Code on the Model 1 or Model 3 (or Model 4 running in Model 3 mode) can be timed like this:

code:   ld      a,(de)
        ld      b,(hl)
        add     a,b
time    equ     t($)-t(code)
The first two instructions take 7 T-states, the 3rd 4 T-states so zmac will set time equal to 18. But if you need cycle-accurate counts on a Model 4 you'll have to do this:
code:   ld      a,(de)
        ld      b,(hl)
        add     a,b
time    equ     t($)-t(code)+2*[ocf($)-ocf(code)]
As before we get a base time of 18 T-states but in this case each instruction also takes an opcode fetch thus the equation will add an additional 6 T-states and zmac will set time to 24.

While most instructions require only one opcode fetch many others take more. All instructions require at least one opcode fetch so ocf() will be at least a count of instructions.

Be forewarned that sometimes the T-state counting goes off. I'm not sure of the cause, but sometimes the count comes out way off with t($) giving values thousands of times different than expected. This can generally be fixed by putting a tstate 0 before the offending code block. That suggests the error has something to do with a multi-pass problem but at any rate keep this in mind if your timing suddenly goes off.

If you'd like any of these features in your version of zmac or would like the source code, just drop me a line at the e-mail address below.


George Phillips, May 3, 2011. gp2000 -at- shaw.ca
Site Index