About this directory ==================== The contents of this directory (as far as I know) will only be useful on Microsoft operating systems from Windows 98 onward. If you wish to try the SUBLEQ examples, copy all of the files in this directory to a directory on your own computer. There are two types of files: *.vbs are Visual Basic Script files, and *.txt files which are programs written in my dialect of SUBLEQ assembler. To run the SUBLEQ programs, it is necessary first to run them through the assembler to create a loadable program. The output of the assembler is a file called test.txt. This can be loaded and run in a SUBLEQ emulator. At the time of writing, there are two emulators - engine.vbs and bignum.vbs. Engine.vbs is the preferred emulator for most uses. Bignum.vbs was created (as its name suggests) to handle big numbers. The downloaded bignum.vbs uses 448 bit 'words' and allows programs to manipulate numbers of over 100 decimal digits. Engine.vbs is limited to the size handled by the script engine, believed to be 48 bits. Program assemble and run is performed in a Command Prompt window. In Windows XP onward this is found in Accessories. After downloading the files into a directory, and starting the Command Prompt window, it is necessary to set the default for the window to that directory. This is achieved with the cd (change directory) command. The .vbs files are run using the Windows Script Host cscript which is provided by default on all Windows systems. Here is a typical run, assuming the files were downloaded to C:\software\subleq Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:\Documents and Settings\anonymous> cd C:\software\subleq C:\software\subleq> cscript assemble.vbs Microsoft (R) Windows Script Host Version 5.7 Copyright (C) Microsoft Corporation. All rights reserved. Program File: Hello.txt --symbols-- 0 finish 4 inctl 5 inchar 6 ouctl 7 ouchar 10 work 11 Hello 40 main 55 next --constants-- 64 -1 65 0 C:\software\subleq> cscript engine.vbs Microsoft (R) Windows Script Host Version 5.7 Copyright (C) Microsoft Corporation. All rights reserved. Program File: test.txt Hello World! ** Finishing ** C:\software\subleq> etc. If you wish to keep a loadable program, rather than assembling it every time, it can be renamed to something else, e.g. C:\software\subleq> ren test.txt keepthis.slq Note that none of the programs are 'aware' of the file extensions, except cscript. It is useful to use the .txt extension so the assembler source can be viewed and edited. About SUBLEQ ============ Computers almost always have multiple hardware (or firmware) instructions and a range of addressing modes. But it has been determined that a computer with one instruction and one address mode is computationally equivalent, if the instruction is carefully chosen. 'Computationally equivalent' means that it can do whatever any other computer can do, given enough memory and time. Note that this does not include the ability to run all the peripherals like disks and graphics cards - these are not 'computations'. A study of single instruction systems provides insight into computer design - it is a computer reduced to a minimum, and can be used as a starting point to understanding the design of 'real' computer systems. Also, a study of single instruction programs shows what 'real' computer instructions are doing 'under the bonnet'. This is because any instruction can be synthesised from combinations of the single instruction. There are several candidate instructions, the one chosen is SUBLEQ - SUBtract a from b and branch to c if b (as a result) is LEss than or eQual to zero (a,b and c being absolute addresses of memory locations). This instruction seems to be the most flexible of the candidates, and has been studied by a number of people. As an educational tool, a study of SUBLEQ quickly reveals how inefficient it is, both in speed and memory use. Writing SUBLEQ programs brings home how big a gulf can exist between the task (usually expressed in a high level language) and the software that actually is loaded into the machine. As an exercise in masochism, it is hard to beat writing SUBLEQ programs. Depending on your point of view, it is a challenge or a waste of time. THE ENGINE ========== The engine is hopefully self-documenting. For clarity, the loader format is repeated here: The loader reads lines of the form number[,number...] where the first number is an address, and succeeding numbers are placed at succesive memory locations starting at that address. If the line has only an address it must be the last line and the address is used as the address of the first instruction to execute. Here is a valid input: 10,0,72,101,108,108,111,32,87,111,114,108,100,33,13,0 40,11,10,43,7,7,46,10,7,49,64,10,55,0,0,0,65,6,58,64,40,61,10,10,40,-1,0 40 THE ASSEMBLER ============= The output file is called test.txt and is in the right format for engine.vbs. If it is a keeper, rename it to something other than .txt (e.g. keepme.slq) The assembler syntax is arbitrary, and not modeled on anything in particular. The assembler itself was hacked together in a few hours and then grown like topsy as features were added. The code is undocumented and presented 'as is'. It was never intended as an industrial strength application, purely a vehicle to translate carefully crafted (i.e. error free) and documented source code into obscure and undocumentable load code. If there is an error in the input, it will probably crash but hopefully output a meaningful error message before doing so. The syntax ========== 1. Comment ---------- A comment starts with a semicolon (;). It, and the remainder of the line, are ignored. 2. White space -------------- Multiple spaces and non print characters (such as TAB) are collapsed into a single space. Leading and trailing spaces in operands are removed. This allows a layout convention to be used, for the benefit of the reader. 3. Addresses ------------ The start addresses for code and data are set by *
. A common declaration in most programs is: *0 finish *4 inctl inchar ouctl ouchar * * See engine.vbs comments for clarification. 4. Data Declaration ------------------ A data declaration for one location is a label. I haven't determined what is acceptable as a label and stuck to alphanumerics, but I'm pretty confident some special characters will work (like underscore, hyphen, etc). The alpha part is case insensitive. To reserve more than one location, follow the declaration with another address e.g. *99 stackpointer=-99 *200 ; leave stack space of 100 locations ... If the label is followed by an equals (=) then the location is initialised with a value by the loader. If no value is given, it should be regarded as indeterminate. Allowable values after the = are a signed integer, a single character literal bounded by single quote (e.g. 'X'), or a label. If it is a label, the address of the label is resolved and put in during the second pass (which may not be useful - see the use of constants in the instruction). Multiple values can be put in, separated by commas e.g. greeting='H','i',0 5. Instruction -------------- If a line has a comma, and does not contain an equals (=), then it assumed to be an instruction. An instruction has two or three comma separated operands. The third operand is the address of the instruction to go to, if the operation results in a zero or negative result. If the third operand is not explicitly entered, it is assumed to be the address of the next instruction (i.e. the state of the result does not change the order of execution). e.g. ,[,operand C] It is necessary to distinguish between a destination label and a label used to put an address in an operand. A destination label is preceded by a colon (:). There can be any number of occurences of a label as an address of an operand, but the destination label must be unique. e.g. zero,zero,goto means "branch to the label 'goto'" (always, since subtracting something from itself results in zero, and if the result is zero the branch is taken) but zero,zero,:goto has an indeterminate branch address, hopefully another instruction will use the label :goto as a destination and put in a valid address before the branch is taken. Each operand can take both an address and a destination label. e.g. :loop work,work ; work = zero (and branch to next instruction) The first operand has the destination label :loop and the address value of the location work. The first operand can also take a numeric or address constant value as a shorthand for 'address of constant'. Numerics are written 'as is', address constants are preceded by a $ e.g. :loop -1,counter ; add 1 to counter [counter = counter - (-1) equivalent to counter = counter + 1] next,next ; set up a return address in a code snippet $return,next ; by zeroing then plugging in the return address work,work,code ; go to the snippet :return .... :code ... : ; a 'subroutine' work,work,:next ; LOOK HERE for next - branch back to caller Two constants are created. The first is a location with the value -1, and the address of that location inserted as the first operand of the first instruction. The second constant is the *negated* address of the location 'return', with its address inserted in the third instruction. Note the negated form is more useful, but if the actual address is required then an explicit data allocation can be made (i.e. badreturn=next). The second and third operand cannot take a constant (as it doesn't make any sense). 6. First Instruction -------------------- There must be a destination label :main on the first instruction 7. Notes -------- 1. The constants are allocated memory after the last instruction. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HISTORY 16-Jun-2011 - created 18-Jun-2011 - Added bignum.vbs, a SUBLEQ emulator capable of storing much larger magnitude variables than engine.vbs. There is no trace facility, so test the load programs in engine.vbs before using bignum. Be prepared for things running a lot slower. 20-Jun-2011 - Revised this document, after feedback from a reader.