Numberix Programming Language Documentation Written by Jeffry Johnston September 16, 2000 Introduction ------------ Numberix was designed to make the source appear as lines of Hex digits, rather than instructions that read like English words. Along with this, a goal was to have a limited number of commands packed together in a useful way. It is inspired by a creative mix of 8088 Assembly, BrainF, Weird, Basic, and even Intercal. The name Numberix has no one meaning, but feel free to use any of these words to describe it: Num-berics, Barbaric numerics, Number-ICKs, Numb-erix :). Disclaimer ---------- IMPORTANT - READ BEFORE COPYING, INSTALLING OR USING. Do not use or load this software and any associated materials (collectively, the "Software") until you have carefully read the following terms and conditions. By loading or using the Software, you agree to the terms of this Agreement. If you do not wish to so agree, do not install or use the Software. THE SOFTWARE IS PROVIDED "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OR FITNESS FOR A PARTICULAR PURPOSE. Jeffry Johnston (hereafter referred to as "Author") does not warrant or assume responsibility for the accuracy or completeness of any information, text, graphics, links or other items contained within the Software. The software is not intended for use in medical, life-saving, or life-sustaining applications. LIMITATION OF LIABILITY. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, LOST PROFITS, INSANITY, HAIR LOSS, MARITAL PROBLEMS, MEMORY LOSS, BUSINESS INTERRUPTION OR LOST INFORMATION) RESULTING FROM THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. The author disclaims all warranties and liabilities for the use of this document and the information contained herein, and assumes no responsibility for any errors which may appear in this document, nor does the author make a commitment to update the information contained herein. The author reserves the right to make changes to this document at any time, without notice. Instruction format ------------------ All instructions are 6 Hex (0-9, A-F) characters long. The format is represented as: HIWXYZ "H" defines two directions, "Dir." and "If_Mem=0". These help decide the program flow from one instruction to the next. "Dir." is the direction that the program will go if MEMORY(INDEX)<>0, otherwise the program will follow the "If_Mem=0" direction. This direction changing is ignored by certain instructions. Table 1: "H" Directions ------------------------ Value Dir. If_Mem=0 0 ^ ^ 1 > ^ 2 v ^ 3 < ^ 4 ^ > 5 > > 6 v > 7 < > 8 ^ v 9 > v A v v B < v C ^ < D > < E v < F < < "I" defines the instruction to be executed. Some of these instructions were designed for the IBM-PC and will need to be adapted for use in other computer systems. In the "I" instructions "W", "X", "Y", and "Z" are data values. The data values are one byte in size each, providing a total of 4 bytes of data for each instruction. Table 2: "I" Instructions -------------------------- Value Instruction 0 MEMORY(INDEX+WX)=YZ 1 MEMORY(INDEX+WX)=(MEMORY(INDEX)+YZ) MOD 100 2 MEMORY(INDEX+WX)=MEMORY(INDEX)+YZ; if >FF then =FF. 3 MEMORY(INDEX+WX)=MEMORY(INDEX)-YZ; if <00 then =00. 4 If INDEX=WXYZ then force If_Mem=0, otherwise use Dir. 5 INDEX=INDEX+WXYZ; if +0000 then =0000. 6 MEMORY(INDEX)=MEMORY(INDEX) OR WX; MEMORY(INDEX)=MEMORY(INDEX) XOR YZ 7 LINE=LINE+WXY; COLUMN=Z; ignore direction changes (H). 8 MEMORY(INDEX+WX)=(StandardInput+YZ) MOD 100 9 Output=(MEMORY(INDEX+WX)+YZ) MOD 100 A MEMORY(INDEX)=PortIn(WXYZ) B PortOut(WXYZ)=MEMORY(INDEX) C MEMORY(INDEX->INDEX+WX)=(datafile+YZ) MOD 100 D MEMORY(INDEX+W)=(MEMORY(INDEX) ROL X) AND YZ E MEMORY(INDEX+WXYZ->INDEX+WXYZ+3)=Number of clock ticks since midnight F YZ=00:END, ErrorLevel=WX. YZ=80:WX<>80:MEMORY(INDEX+WX)=# bytes left in file; if >FF then =FF. YZ=80:WX=80:Toggle between StandardOutput and file output. YZ<>0:MEMORY(INDEX+WX)=(MEMORY(INDEX+WX)+ MEMORY(INDEX+YZ)) MOD 100 Program Layout, Version, and Flow --------------------------------- Numberix groups characters into 13 instructions per line (78 characters). This is accomplished by ignoring any non-Hex characters including line breaks. The last line does not need to be 13 instructions long. Program flow can be up, down, left or right. The direction "H" defines which way will be traveled to find the next instruction. Instructions forcing Numberix to travel off the edge of the defined program can cause unpredictable results. There are two values "LINE" and "COLUMN" that define which instruction is being used. At program start, both "LINE" and "COLUMN" are equal to 1. The top left instruction is the program start, however it is not actually executed. Instead, its "WXYZ" value is used to allocate the amount of memory that the program needs. Also, the instruction value "I" is used as a version number. Values of "0" or "1" will be understood as Version 1.0, which should be used for all programs currently made. If a future specification varies, it will use another number to distinguish it from Numberix Version 1.0. Program flow starts in the "Dir." direction. Memory ------ In Numberix, memory is treated as one large block. If an instruction reads past the end of memory it will loop around to the beginning. The first instruction will allocate memory in the range [0000->WXYZ-1]. Each location in memory holds one byte. So, "WXYZ" must be at least "0001" (for one byte of memory). All memory locations are initially cleared to zero and "INDEX" points at location "0000" in memory. In the instruction listing above, "MEMORY(INDEX)" is referred to. "INDEX" is used as a pointer in the block "MEMORY". In the case of "INDEX+W...", the "W" is signed. The high bit of "W" is the sign for the entire value (0=+, 1=-). File Handling and I/O --------------------- By default, input will be taken from StandardInput and output will be directed to StandardOutput. The Numberix program can request a file read, however, so those programs will need filenames for I/O. In addition, an input file can be specified instead of StandardInput. Files are opened automatically before a read/write if they are closed. All files are closed on program exit. Instruction Details ------------------- Instruction 0: MEMORY(INDEX+WX)=YZ Stores the value "YZ" in the memory location "INDEX+WX". Instruction 1: MEMORY(INDEX+WX)=(MEMORY(INDEX)+YZ) MOD 100 Adds "YZ" to the current memory location and stores it in the memory location "INDEX+WX". If the result is a value higher than FF, it will wrap around to be in range. Instruction 2: MEMORY(INDEX+WX)=MEMORY(INDEX)+YZ; if >FF then =FF. Adds "YZ" to the current memory location and stores it in the memory location "INDEX+WX". If the result is a value above FF, the stored value remains at FF. Instruction 3: MEMORY(INDEX+WX)=MEMORY(INDEX)-YZ; if <00 then =00. Subtracts "YZ" from the current memory location and stores it in the memory location "INDEX+WX". If the result is a value below 00, the stored value remains at 00. Instruction 4: If INDEX=WXYZ then force If_Mem=0, otherwise use Dir. Compares "INDEX" to "WXYZ". If they are equal, the program will travel to the next instruction at "If_Mem=0". Otherwise, the "Dir." direction will be used. Instruction 5: INDEX=INDEX+WXYZ; if +0000 then =0000. Adds the signed value "WXYZ" to "INDEX" and stores the result in "INDEX". However, if the value "WXYZ" is +0000 then "INDEX" will be reset to 0000. Instruction 6: MEMORY(INDEX)=MEMORY(INDEX) OR WX; MEMORY(INDEX)=MEMORY(INDEX) XOR YZ Performs the logical OR of the current memory value and "WX". It then performs the logical XOR on that value and stores it in the current memory location. If only an OR is desired, use the value 00 for "YZ". If the XOR alone is required, use the value 00 for "WX". Instruction 7: LINE=LINE+WXY; COLUMN=Z; ignore direction changes (H). Stores the signed value "WXZ" in "LINE" and the value "Z" in "COLUMN", jumping to that location for the next instruction. The direction "H" is ignored. Instruction 8: MEMORY(INDEX+WX)=(StandardInput+YZ) MOD 100 Reads a value from "StandardInput" (waiting on a keystroke or other input if necessary), then adds "YZ" to it and stores the result in the memory location "INDEX+WX". If the value to be stored is higher than FF, it will wrap around to be in range. Instruction 9: Output=(MEMORY(INDEX+WX)+YZ) MOD 100 Takes the value at memory location "INDEX+WX", adds "YZ" to it, and sends it to "Output". If the value to be sent is higher than FF, it will wrap around to be in range. "Output" can be either "StandardOutput", or a file, depending on which one is selected. Instruction A: MEMORY(INDEX)=PortIn(WXYZ) Reads the value from hardware port "WXYZ" and stores it in the current memory location. Instruction B: PortOut(WXYZ)=MEMORY(INDEX) Stores the value of the current memory location in hardware port "WXYZ". Instruction C: MEMORY(INDEX->INDEX+WX)=(datafile+YZ) MOD 100 Reads "WX"+1 bytes from "datafile", adds "YZ" to the value, and stores the results in memory from the current memory location to "INDEX+WX". Instruction D: MEMORY(INDEX+W)=(MEMORY(INDEX) ROL X) AND YZ Takes the value at the current memory location, rotates the bits left "X" positions, then performs the logical AND on the resulting value. This value is then stored in the memory location "INDEX+W". If a shift is desired rather than a rotate, use AND to zero the bits that would be lost. If AND alone is required, use the value 0 for "X". Table 3: Multiply and Divide ----------------------------- x / 1 0FF 0FF 2 1FE 77F 4 2FC 63F 8 3F8 51F 16 4F0 40F 32 5E0 307 64 6C0 203 128 780 101 Use the values in Table 3 for "XYZ" to perform the desired multiplication or division. Instruction E: MEMORY(INDEX+WXYZ->INDEX+WXYZ+3)=Number of clock ticks since midnight Stores the number of clock ticks since midnight in four consecutive memory locations, starting with "INDEX+WXYZ". In the IBM-PC there are approximately 18.2065096664429 clock ticks per second and 1573042.43518066 in a 24-hour period. Instruction F: YZ=00:END, ErrorLevel=WX. YZ=80:WX<>80:MEMORY(INDEX+WX)=# bytes left in file; if >FF then =FF. YZ=80:WX=80:Toggle between StandardOutput and file output. YZ<>0:MEMORY(INDEX+WX)=(MEMORY(INDEX+WX)+MEMORY(INDEX+YZ)) MOD 100 If "YZ" is 00, exits the program with the ErrorLevel "WX". If "YZ" is 80, and "WX"<>80, stores the number of bytes remaining to be read from "datafile" in memory location "INDEX+WX". If "YZ" is 80, and "WX"=80, toggles between storing output in "StandardOutput" or a file. If "YZ" is not 00 or 80, adds the value at memory location "INDEX+YZ" to "INDEX+WX" and stores it in memory location "INDEX+WX". If the value to be stored is higher than FF, it will wrap around to be in range. Example Programs ---------------- Echo (echos back whatever is typed, Esc to exit): 5000016800E5FF0000000000000000000000000000000000000000000000000000000000000000 00000009001B 500001 reserve 2 bytes of memory, go right (6800E5) 6800E5 reads in a character and adds E5 to it(E5+Esc=00) goes right (FF0000) if 00, otherwise down (09001B) [FF0000] exit, errorlevel 0 09001B print character+1B (E5+1B=00,back to normal), go up (6800E5) Hello World: A0000159006CA9006C590057A9006F590064A90021000000000000000000000000000000000000 59004809006559006F09002059007209006CFF0000 A00001 reserve 2 bytes of memory, go down (590048) 590048 print the letter "H", go right (090065) 090065 print the letter "e", go up (59006C) 59006C print the letter "l", go right (A9006C) A9006C print the letter "l", go down (59006F) 59006F print the letter "o", go right (090020) 090020 print a space, go up (590057) 590057 print the letter "W", go right (A9006F) A9006F print the letter "o", go down (590072) 590072 print the letter "r", go right (09006C) 09006C print the letter "l", go up (590064) 590064 print the letter "d", go right (A90021) A90021 print the character "!", go down (FF0000) FF0000 exit, errorlevel 0 Command Line for Numberix Interpreter ------------------------------------- Usage: NUMBERIX sourcefile[*] [datafile [outfile]] sourcefile Numberix source code * Turn on Debug mode datafile Input datafile outfile Output file If datafile or outfile are omitted they are replaced by the names DATAFILE and OUTFILE, respectively. Numberix Debugger ----------------- To enter the debugger, put an asterisk "*" in the command line, preferably after the sourcefile name. The debugger prompt, "-" will appear. There are several commands: ?: Help Shows a quick listing of the possible commands. A: About Displays copyright notice and version. D: Dump Memory Displays the contents of memory starting from the given offset. If no offset is given it will display from offset 0000 or continue from the last memory dump. G: Go Continues execution of the program from the current position. If coordinates are given the program will stop when they are reached, otherwise the debugger is exited and execution continues uninterrupted. If the program ends, a message will be displayed. I: Initial Status Displays allocated memory, command line and I/O filenames. P/T: Proceed/Trace Single-steps through the instructions one at a time. Q: Quit Exits Numberix Interpreter R: Registers Displays the contents of several memory locations and the instruction to be executed next, among other things. Special Thanks -------------- Joshua Gregorio: For twisted ideas and showing me Intercal Russell McRae: Numberix name Contact Me ---------- Please let me know what you think about Numberix. If you have written any Numberix programs (!), or have comments, additional instruction suggestions, or questions, contact me by E-Mail: numberix@kidsquid.com http://kidsquid.com/ Or visit the official Numberix website: http://calamari.8k.com/numberix Thank you for your interest in Numberix!