Question on Operand Type Determination (Z-Machine Spec)

I feel like I’m misreading something here. Section 4.2 says brings up the operand types:

  $$00    Large constant (0 to 65535)    2 bytes
  $$01    Small constant (0 to 255)      1 byte
  $$10    Variable                       1 byte
  $$11    Omitted altogether             0 bytes

Section 4.4.2 says, which is also talking about the operand types says:

“In long form, bit 6 of the opcode gives the type of the first operand, bit 5 of the second. A value of 0 means a small constant and 1 means a variable.”

It’s the last sentence that throws me off. Why is a value of 0 a small constant and a value of 1 a variable? It looks like the value of 0 would be a large constant. A value of 1 would be a small constant. I feel like I’m probably confusing what the spec means by “type” here.

“Long form” can be understood as a special encoding of a subset of the Variable-length instructions, if exactly two operands are used, and they are either variables or small constants. Otherwise, the regular variable-length encoding is used, with two type-bits per operand.

Hmm. Okay, thank you for the response. But I have to admit my sheer ignorance here: I have no idea how that corresponds with the table the spec provides.

Are you saying that the 0 (small constant) and 1 (variable) from section 4.4.2 is not relating to the table provided in 4.2? Is that what you mean by it being a “special encoding”?

Maybe a better question is: how would I have known what you just said from the spec? Section 4.4.3.1. mentions a “special case of the ‘double variable’” but I’m not seeing any other special (read: exception) considerations.

The table in 4.2 has nothing to do with 4.4.2. It could probably do with being a bit more explicit.

You’ll notice that the text above the table in 4.2 says that operands are ‘often’ stored in 2 binary digits. The format referred to in 4.4.2 stores the operands in 1 binary digit.

Also worth noting is that, for decoding, I found the table at the bottom of the page under ‘On disassembly’ to be far easier to understand.

I guess the reason I linked the two in my mind is that 4.2 mentions “types” and section 4.4 (of which 4.4.2 is a part) also mentions “types.” So it seems like the two would be related in concept which is where apparently my mistake was.

The “2 binary digits” vs “1 binary digit” bit was not even something I thought of. I see where it says 2 binary digits, but I don’t see that clearly contrasted with the alternative, which is also probably where my confusion was stemming from a bit.

I appreciate the clarifications here. I’m working on building a heavily commented implementation of a Z-Machine interpreter and I’m hoping those comments will help someone directly relate the implementation (code) to the specification.

1 Like

I think a major problem in the text of the Standard is that it was written by, and for, people for whom the general structure of the Z-Machine was well understood, so there are places where things are correct but potentially confusing if you’re not already familiar with the system. I have vague memories of the instruction format confusing me a lot when I was first trying to write a Z-Machine interpreter from scratch.

Yep, understood on that. It’s a fun challenge, if a bit frustrating sometimes. To show you how bad my initial implementation was, you can see the heavy memory module I wrote:

Memory.py

That being said, I did use the table you mentioned (at the bottom of that part of the spec) as part of the calculations.

My overall implementation there turned out to be a total mess, however, once I got into handling the read opcode and parsing. So I’m effectively starting over with a new implementation from scratch since I have no clue where I went wrong.

Ah, and following up on something else, I see in section 4.4.3, it says “The values are operand types as above.”

Here someone could easily wonder: is the “as above” meant to refer to 4.4.2 (which is, as I now know, 1 binary digit) or 4.2 (which is 2 binary digits)? It seems that this refers to the actual table in 4.2.

So I think the spec is basically, like you said, accurate; it just wasn’t written in some cases with an eye towards removing certain ambiguities. (In the spec writing world, we say it was “written for correctness, not necessarily for value.”)