wo have slowed down slightly, largely because I think I’ve gotten a lot of easy answers out of the way. I haven’t yet addressed – no. 4,
REGISTER. Delegating as much responsibility to internal registers as possible, and allowing a
wo programmer to modify these registers is paramount to opening up the extent of what can be done inside of a limited instruction set. As few system registers as possible will be reset at every turn – this is likely necessary for something like ‘stack depth,’ as it is a valuable value for a user to be able to fetch, but for a user to change it would be both unpredictable and of limited value.
On the other hand, I think this is how I want to handle many important operating values such as word size, current word, and the location (in bits) of the interpreter’s cursor. Potentially even the code itself, which would allow for self-modifying code1 and cheater quines. This will be ‘dangerous’ in the sense that writing and maintaining such code could prove implausible, but that is an exercise left to the coder… no rewriting vital system registers will be necessary.
Beyond these things, registers (instead of instructions) can be used to hold important values for users. Rather than dealing with a complicated time return format and formatting instructions, simply put values like hour, minute, second, day, month, year in their own registers. Random numbers as well, have a seed register and a random register. Have a certain class of register for these things that reinitializes them with a specific instruction (or
REGISTER, given two MNums on the stack2). That would allow initial time to be used as a global seed, and allow users to write over unnecessary time/date registers (and therefore have access to storage early on). Additionally, any register not predefined by the system would be user-definable. Thus it may make sense to leave some low-numbered registers empty3.
Not growing the instruction set for this post, the last one is still valid. Though, I have quite a few instructions to mess with, and it’s largely going to be about stacks, potentially writing instructions (functions, let’s say), and I should really get
DIVIDE in there before the next word size. I think
DIVIDE will return the quotient unless passed MNum, in which case it will pop an additional value and return both quotient and modulo. I’m constantly trying to think of ways to exploit MNum, and since an implied zero would give us a useless NaN, this seems exploitable.
wo5 will be flushed out soon.
- One interesting issue with self-modifying code (and, to a lesser extent, functions) is that inputting integers with the intent of executing them as instructions loses a bit. Assuming our inputs and outputs work on a word level, it would be necessary to be able to modify word size during execution. ↩︎
- This is probably my preference, a
REGISTERinstruction that has threefold use: x and y on stack, write x to y; MNum and y on stack, read y; MNum and MNum on stack, refresh all refreshing sysregs. A separate instruction would allow more granular refresh; though this can always exist as a higher instruction as well. It’s worth keeping in mind that in a typical language, the shortest instruction possible is a single byte. If that’s what I’m competing with, I have 127 instructions to play with in total; redundant and niche instructions can sit comfortably in this upper range. ↩︎
- Same is true for instructions; once
WRITEINSis defined, it may be useful to throw in a
NOPor two to the instruction list so that users have some space to play. ↩︎