Z-machine memory

I have recently found myself once again working on my too-long ignored z-machine library.

While refreshing my memory on bits of the standard I was reminded of something that has puzzled and irritated me for over a decade and a half and it finally bothered me enough to post this topic.:upside_down_face:

In section one of the standard there is a remark at the bottom:
Note that the total of dynamic plus static memory must not exceed 64K. (In fact, 64K minus 2 bytes.) This is the most serious limitation on the Z-machine.

I’ve never understood how the maximum total of dynamic + static = 64K minus 2 bytes. Surely it is 64K exactly.

I realize Inform doesn’t compile overlap between static and high memory, but that isn’t called out as a Z-machine requirement. Assuming the start (and end) of static is at the maximum we can store in the header word at 0x0e: 0xffff, and high memory also starts at the same address, then dynamic memory is 64K minus 1 byte and static is 1 byte, giving us 64K exactly. The wording on the ending of static memory is a bit vague, saying “it must end by the last byte of the story file or by byte address $0ffff (whichever is lower)”. The language used isn’t clear if it means at the address or before, but since it uses the wording “by” for both the end of the story file and the adress, it would seem to mean “at” rather than “before”.

4 Likes

Yeah I can’t see any reason for the -2 either.

The closest I can come to a reasonable explanation would be if high memory was thought to need to begin at an address that could be validly encoded as a packed address, so only $fffe, not $ffff. And if the statement was really only about dynamic memory, not dynamic plus static.

I’ve often thought it intended to say the total applied to just dynamic memory. (I think I mistakenly read it as such originally).

In that case, we can get 64K minus 2 bytes if we also assume no overlap between static and high memory, as the lowest address at which high memory can start is 0xffff, so static memory must start no later then 0xfffe, and dynamic must then end on 0xfffd at the latest, giving us 64K minus 2 bytes.

Edit: Section 1.1 of the standard does say the starting addresses of static and high memory stored in the header are byte addresses, not packed addresses, so I think we can rule that out.