I was dicking about with an IM2 interrupt in C using z88dk. I wanted to return to BASIC leaving my interrupt routine running, but z88dk doesn't support that. (It restores IM1 when returning to BASIC from C.) It's a simple-ish change to add support to the framework, but I discovered I really didn't understand the relationship between the Spectrum BASIC interrupt handler at 0x0038 and the IY register. The fix Alcoholics Anonymous gave me on the z88dk forum was, at the end of my ISR, to load IY with 0x5c38, then call 0x0038, then return. I have no doubt he'll be right, but... why?

I was looking at the Spectrum ROM disassembly book, and I see in there:

but searching for "IY" in the rest of the book yields nothing. Um, eh? IY is set but never read or referenced? That can't be right. I must be missing something.

So I sort of understand. The BASIC ISR (and possibly the entire BASIC system?) expects IY to always hold the value 0x5c3a, so restoring it to that value before calling the BASIC ISR would clearly be the right thing to do. But why is IY needed to point to the ERR NR system variable and why doesn't it appear to be dereferenced in the Spectrum ROM?

0038 MASK-INT PUSH AF Save the current values held in
PUSH HL these registers.
LD HL,(FRAMES) The lower two bytes of the
INC HL frame counter are incremented
LD (FRAMES),HL every 20 ms. (U.K.) The highest
LD A,H byte of the frame counter is
OR L only incremented when the
JR NZ,0048,KEY-INT value of the lower two bytes
INC (FRAMES-3) is zero.

With a bit of attention and clairvoyance, the reader will be able to infer that the line, INC (FRAMES-3), is actually implemented as INC (IY+#40).

Ah, a rookie mistake. The BASIC interpreter—well, many ROM routines, to be precise—make heavy use of IY and prime registers. If you fool around with them, you need to save and restore them before returning to BASIC.

0 x

Every man should plant a tree, build a house, and write a ZX Spectrum game.

How is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book. Is there a way of expressing such things in Z80 assembly language which I'm not familiar with?

L0038: PUSH AF ; Save the registers that will be used but not
PUSH HL ; the IY register unfortunately.
LD HL,($5C78) ; Fetch the first two bytes at FRAMES1.
INC HL ; Increment lowest two bytes of counter.
LD ($5C78),HL ; Place back in FRAMES1.
LD A,H ; Test if the result was zero.
OR L ;
JR NZ,L0048 ; Forward, if not, to KEY-INT
INC (IY+$40) ; otherwise increment FRAMES3 the third byte.

How is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book.

Regarding the lack of constant/variable list in the book at least, perhaps the 'ROM Disassembly' authors were relying on the fact that these are listed in this Spectrum manual, which I assume was part of the package. As I've never owned any of the original Spectrum models, I can't really tell.

How is the reader of the book supposed to go from "FRAMES-3" to "IY+40"? The word "FRAMES" doesn't appear anywhere else in the book.

Now that you’ve mentioned it, it does appear to be a little, well, idiosyncratic on their part. Granted, they used the standard names for Spectrum’s system variables, so anybody familiar with them wouldn’t have questions about them.

That said, I’ve always consulted that book “the other way around.” That is, I rarely read the book first and wrote my routines around it later. I used a debugger/monitor, found an entry point, and then consulted the book. That way I generally read the comments, rather than looked at the disassembly in the book.

In any event, there’s an excellent electronic version of it you can consult instead of the printed book or a PDF. It does treat index registers the proper way and many things are hyperlinked for easy access.

0 x

Every man should plant a tree, build a house, and write a ZX Spectrum game.