Honeywell ARGUS
ARGUS was an Assembly Language devised in the 1960s by Honeywell for their Honeywell 800 and 1800 computers. The name ARGUS was an acronym standing for Automatic Routine Generating and Updating System.[1] As with other Assembly Languages, each line of ARGUS was copied on to one card and related to one word in memory, except that one ARGUS command, RESERVE, could reserve any specified number of words in the position specified. The RESERVE command was also exceptional in not prescribing the initial data in the reserved words. With a few exceptions Machine Language words were coded in the same order as the ARGUS lines .[2]
Honeywell 800 Memory
The Honeywell 800 and 1800 had a main memory and a control memory, both using ferrite cores. The main memory had between 4 and 16 banks, depending on customer requirements. Each bank contained 2048 words of 48 bits each. The actual number of banks in an individual installation had to be a multiple of 4.[1]
The control memory had 256 registers of 16 bits each. At any given time the machine could theoretically run one Operating System and 7 application programs, each with exclusive use of 32 registers.[1]
A program that required more than 2048 words (data and instructions combined) had to be split into segments of 2048 words or less. Each segment would have exclusive use of one bank of main memory. There were special instructions to pass control from one segment to another.
Layout of ARGUS Commands
Each line of ARGUS command had fields as follows:
Location[3] was an optional ARGUS name to be assigned to that word in memory. When the address of each word had been assigned in memory, the ARGUS name of the line would be linked with the position of its corresponding word. Other lines of ARGUS could refer to that name and their words would be assigned the correct memory address. Within the program, each name had to be unique.
This field may begin with R, . If so then the rest of the card is remarks only.
This field may begin with X, or X,addressname. If so then this line and any other X, lines will be placed away from the lines not so marked. They can then be addressed by X,+n or by the addressname in the address field.[4]
This field may begin with M,maskname. If so the line defines a Mask
Operation: The ARGUS name of a Machine Language command or an ARGUS-only command. This could be followed by the address of a mask, if required. A few commands had extra information.
A, B and C addresses: To be translated into machine code (see below). The A and B addresses were typically the two input words and the C address was the destination.
ID: Normally a serial number punched on to the card by the card punch machine. Used to resort any cards that might be dropped.
Layout of Machine Language Commands
Each Machine Language Command used one word of 48 bits. This was split into 4 sections of 12 bits each. The first 12 bits specified the operation, with ancillary information including the offset address of any mask for the command. The three other sections were the A, B and C addresses.
If a mask was specified then the final result of the command would pass through that mask before reaching the destination. For example, if bit 17 of the mask was 1 then the result would go to bit 17 of the destination. If bit 17 of the mask was 0 then something else would go to bit 17 of the destination. It might be 0 or it might be the unchanged bit 17 of the input word, depending on the command.
A segment was allowed up to 16 masks and they had to be in consecutive words, beginning at an address whose last four bits were all 0. All of them had ARGUS location names. A special register called the Mask Register held the base address. The command field had 4 bits to hold the offset address of the named mask.
Modes of Addressing Memory
For most commands the A, B and C address sections were used to denote actual locations in memory. There were six modes of addressing. Two were rarely used. The remainder were: Direct, Direct Special Register, Indirect Addressing and Indexed.
Direct Addressing
The main memory address is specified directly by the command. In machine language one of the 12 bits indicates direct mode, the other 11 specify the exact address. 11 bits can represent the numbers 0 to 2047 but nothing larger. However this is the most efficient type of addressing. This dilemma is why a bank has only 2048 words and a segment is confined to only one bank.
There are two ways of writing this in a line of ARGUS code: 1. A name, previously defined in the location column. A number (decimal) can be added to this, e.g.: BUFFER0+59 2. A location several lines (words) beyond the current line, e.g. C,2 means the line two beyond this one.
Indirect Addressing
In 12 bits the mode of addressing and the address of a register in control memory are identified. Also an increment between 0 and 32 is specified. The main memory address is in the register in control memory. The processor will first obtain the main memory address from the register, then call for the word at that main memory address. Finally it will increase (increment) the register value by the amount specified. The 16 bit address from the register contains a bank address from 0 to 31 using 5 bits and a word in that bank using 11 bits. Incrementing was recommended only for addresses A and B.
In ARGUS: N,R0,3 means use register R0 and then increase it by 3.
Direct Special Register
A register is addressed directly in the same manner as a word in main memory.
In ARGUS: Z,R0,3 means read from or write to register R0 directly and then increase it by 3. The increase is not recommended when writing.
Indexed Addressing
This applies only to 8 registers, called index registers. It takes 3 bits to specify the index register and another 7 to specify an offset of 0 to 127. So the offset is added to a full-length main memory address. This is a powerful tool. It is helpful for processing a multiword text or record. Tape buffers are usually addressed this way.
In ARGUS: X0,35 or 0,35 means use Index Register 0, increase that number by 35 (decimal) and read from or write to that location in main memory. DO NOT change the value in X0.
Inactive Address
In ARGUS, the address field was a dash (-). I don’t know what the machine code was. It meant the field would be ignored by the processor, thereby nullifying part of the usual action of the command.
Registers
As mentioned, the program had access to 32 registers. 8[5] had special functions, 16[5] registers (R0 to R15) were general purpose and 8 (X0 to X7) were index registers.
Index addressing was only possible for index registers.
Direct and Indirect addressing were applicable to both general purpose and index registers. They would probably work with other registers too but that would be bad practice.
SC (Sequence Counter) SH (Sequence History) CSC (Cosequence Counter) CSH (Cosequence History) MSK (Mask Register) AU1 and AU2
In operation, the Sequence Counter always contains the full address of the command that is running. Normally commands are executed in location order. The Sequence History contains the last value of the Sequence Counter. This value has to be stored immediately upon jumping to a subroutine. Otherwise it will be impossible to return. The Cosequence Counter and History perform the same functions for any command that had X, at the beginning of its ARGUS location.
The MSK register holds the full location of the first mask (see below).
AU1 and AU2 are used internally by some commands, especially TN. They can also be used by programs. However, there is a risk that an internal operation might interfere so it is not a wise choice.
Commands
Each ARGUS line defines a word in memory. In normal operation the processor performs each command in address order. Some commands can order a JUMP to another address (by Direct Addressing into the same bank).
Arithmetic
The commands WA, BA and DA, in different ways, all obtain numbers from addresses A and B, add them together and put the result into address C.
The commands BS and DS both subtract the number in address B from the number in address A, placing the result into address C.
WA (Word Add) treats the two input numbers as binary numbers with no sign. This was often used to add an increment to a known address.
BA and BS (Binary Add and Binary Subtract) treat the two input numbers as signed binary.
DA and DS (Decimal Add and Decimal Subtract) treat the two input numbers as signed decimal.
The leftmost four bits define the sign. If they are all zero then the sign is positive. Otherwise it is negative.
The command DM multiplies the number in address B by the number in address A, placing the left half of the result into address C. The remaining low end digits are left in LOP, the Low Output Register. They can be transferred from there to a main memory address by the TX or TS command. DM is fully supported by the Floating Point Adaptor. In its absence, simulation is required.
Data Transfer and Program Control
TX Transfer from address A to address C. Address B MUST be Inactive (see Modes of Addressing)
TS Transfer from address A to address B then JUMP out of sequence to the command at address C. C must be a direct address. Optionally A and B can be Inactive and the command becomes a pure jump. This is the nearest that this machine gets to a GOTO command.
MT Transfer from address A to address C several times. The number of times is specified as a decimal number in address field B. This number is NOT a true address. It is converted to binary and positioned in the operation section of the machine language command. So the value cannot be large.[6] Address C MUST be Indirect with an increment of one or more so that each individual transfer operates on a different word. This command was rarely used in my experience of application programming. However it may be more useful in operating systems and compilers.
TN Transfer from address A to address C. Then transfer from A+1 to C+1. Continue in total for the number of times specified in address B. As for MT this is a decimal number that ends up in binary in the operation section of the machine command.[7] This command was frequently used in applications, especially for “blanking” out areas of text. This command used registers AU1 and AU2 to manage the address increments.
NA Compare addresses A and B. If equal continue as normal. If unequal JUMP to address C.[8]
LA Compare addresses A and B. If A (as unsigned binary) is less than or equal to B then continue as normal. Otherwise JUMP to C.[9] For a loop with a counter, LA is safer than NA. If the logic goes astray than an NA loop could run away.
PR Proceed. This was a "do nothing" command which nevertheless would take some time. All three addresses would be inactive. It could be used in a loop to wait for the operator to take some action before perhaps reminding him.
Constants and Initial Value Definition
These were ARGUS commands to be translated into the initial value in binary of an address in memory. The actual value would go into address A, continuing into addresses B and C, as long as necessary. Most of these lines were for use as constants and would have a location code for reference by active commands.
OCT The punched letter or number is translated into a three bit octal code. So 0 becomes 000, 1 becomes 001, 2 becomes 010…. and 7 becomes 111.
HEX The punched letter or number is translated into a four bit hexadecimal code. 0 becomes 0000, 1 becomes 0001, ….. 9 becomes 1001. Then B to G indicate decimal 10 to 15, which in binary is 1010 to 1111. Honeywell hexadecimal code used B to G where IBM used A to F.
DEC The punched letter or number is translated into a four bit decimal code. This is like hexadecimal except that only 0 to 9 are valid.
ALF The punched letter or number is translated according to Honeywell’s own binary code for Alphanumeric numbers, letters and symbols.
M,x,text plus separate entries of x,text in EACH address field. Here, x can be O, H, D, or A allowing each 12 bit section of the word to be encoded using any one of the methods above.
For OCT, HEX and DEC, the leftmost 4 bits are used to denote the sign of the number.
Masks and Switch Commands
A mask was a constant with a location entry of M,maskname. It was good practice to put all masks together in ARGUS. In any case ARGUS would put them together in consecutive words. The maximum number of masks was 15.
A mask could be used to modify the action of any command that could change the value of a word, for example: TX,maskname would apply the mask “maskname” to a TX command. Masking was essential for a Switch Word command but not very valuable for other commands. Some installations had a standard to use them ONLY for Switch Word. The full address of the first mask would be placed in the MSK register and the offset of an individual mask would be placed into the command section of the Machine Language command for which it was specified. Consequently, a program needed and had only one set of masks and they could be used from any segment.
Switch Word commands were used to move some bits in the word to other bit positions. There were two Switch Word commands and they were very similar. Switch Word and Extract had an ARGUS command of: SWE,maskname, the A address was the source and the C address the destination. The B address field was for the amount of switch: x,n,d . x was B, D or A representing Binary, Decimal or Alphanumeric, i.e. units of 1, 4 or 6 bits respectively. d was L or R for Left or Right.
In operation:
The word was obtained from address A The bits were moved Left or Right by the number and size of unit specified Bits that “fell off” the end were put back into the opposite end The shifted word was passed through the mask bit by bit. If the mask bit was 1 then the shifted bit would be copied through. Otherwise a 0 bit would be passed. The modified word was placed in address C
The other Switch Word command was Switch Word and Superimpose, SWS, with the same syntax. The action differed in the mask stage. If the mask bit was 0 then the unshifted rather than the shifted bit was placed in the output word. For a mask bit of 1 the action was the same as for SWE.
Example Address A contains 8 characters of 6 bits each: ABCDEFGH Mask ONECHAR contains 1 in its right-most 6 bits and 0 elsewhere.
The command is: SWE,ONECHAR A A,4,R C Then Address C will contain: 0000000D
If the command is: SWS,ONECHAR A A,4,R C Then Address C will contain: ABCDEFGD
In Machine Language all shifts were represented as Binary right. All the ARGUS codes in the x,n,d format can be reduced to Binary right.
Macros and Subroutines
A macro would be called by: L$,macroname This would request the assembler to insert the ARGUS text of macro “macroname” at that point. This was done during at an early stage of assembly before the ARGUS was translated to machine code. There were quite a few macros in the standard library (held on its own tape) and customers could add more. The macros GET and PUT would get an item from the input tape buffer or put an item into the output tape buffer, reading or writing a record as appropriate.
There were two types of subroutine. One was entirely written in ARGUS. Here is an example, using the subroutine SUBA:
Location | Command | Address A | Address B | Address C |
---|---|---|---|---|
U,NEWPROG | MYPROG | |||
R, | ||||
R, MAIN PROGRAM BEGINS | ||||
R, THE R COMMA DEFINES THE LINE AS A COMMENT LINE. | ||||
R, | ||||
……. | ||||
……. | ||||
R, THE TS COMMAND CAUSES JUMP TO SUBROUTINE SUBA. THE NEXT LOCATION IS STORED IN REGISTER SH. | ||||
TS | - | - | SUBA | |
R, THE SUBROUTNE WILL JUMP BACK TO HERE. | ||||
WA | ...... | |||
.... | ||||
.... | ||||
R, MAIN PROGRAM ENDS ABOVE HERE. SUBROUTINES CAN BEGIN. | ||||
R, | ||||
R, SUBROUTINE SUBA | ||||
R, | ||||
R, SUBROUTINE MUST BEGIN BY SAVING CONTENTS OF SEQUENCE HISTORY REGISTER (SH). | ||||
R, OTHERWISE IT MAY BE LOST BY ANOTHER TS, NA OR LA COMMAND. | ||||
R, | ||||
SUBA | TX | Z,SH | – | Z,R0 |
R, SUBROUTINE PROCESS BEGINS | ||||
……… | ||||
R, SUBROUTINE PROCESS COMPLETED SO GO TO SAVED LOCATION TO CONTINUE MAIN PROGRAM. | ||||
TS | - | - | N,R0 | |
R, END OF SUBA |
The other type of subroutine was delivered in machine language with a Macro wrapper. It was normally written by Honeywell staff. The Macro used the command GOSUB to call the subroutine.
Floating Point Commands
The Honeywell 1800 had an optional Floating Point Adaptor for scientific computing. There was a set of commands for it.[10] These commands were also available in simulation form if the hardware did not include the adaptor but this was not recommended for regular use. The ARGUS floating point commands were the same regardless of whether there was an adaptor. In its absence, ARGUS would supply a machine language simulation of true floating point operation.
Peripheral Input/Output Control
Input and Output device addresses at machine level were two octal digits 0-7. At ARGUS level it was two letters A-G. The first digits identified the controller, the second digit identified the device number on that controller.
For tape processing, one unit of data on the tape was called, in Honeywell manuals, a record. IBM called, and still calls, this a block. A subdivision of a record was called an item. IBM called this a record. IBM’s terminology became the American standard.
Commands:
The command RW,AA would rewind the tape on tape unit AA, octal 00.
The command RF,AA would read the next record on tape unit AA, octal 00.
The command RB,AA would read back over the previous record on tape unit AA, octal 00, without delivering data. To amend an existing tape, you could use RF to find the first record that you didn’t want, then RB to reach the space before it, then WF to write over it and onwards.
The command WF,AB would write the next record on tape unit AB, octal 01.
The command RF,GA would read the next card on the card reader, device GA, octal 70.
The A address would be the first word in the buffer for that read or write operation. It was normal to use two buffers for each device so that reading or writing could run in parallel with processing. This is called double-buffering. Buffer size was a limiting factor in the size of “records” (blocks) because core memory was limited.
When preparing to write a record on tape, each item was terminated by an End of Item word with a prescribed code. Each record was terminated by an Ortho word for error checking followed by an End of Record word. After the output buffer had been filled with items the Compute Ortho (CC) command was used to calculate the Ortho word and provide the End of Record word. For the Compute Ortho command Addresses A and B marked the first and last word positions.[11] Next, the record would be written by the WF command. Finally control would be returned to the main program.
For normal application work all peripheral commands, except perhaps RW, would be placed in a subroutine.
Program Administration Commands
There were ARGUS commands to deal with the administration of programs. In order to assemble a program the following were required:[12]
- A deck of cards containing ARGUS code for all the changes required.
- An input tape containing all the ARGUS programs at the installation.
- An output scratch tape to contain all the new ARGUS programs and all revisions to old ones.
- An input tape containing all the machine language programs at the installation.
- An input tape to contain all the machine language programs - unchanged, new or reassembled.
- An input tape containing a library of macros. These macros would be added into the ARGUS code during assembly and before translation into machine code.
- One or more scratch tapes for sorting the card images.
A very few administration commands were required for each program that was to be created or changed.
U,NEWPROG progname The cards that follow are for a complete, new program called progname. U,REASSMB progname The cards that follow are revisions to the existing program progname. U,NEWSEG progname segname The cards that follow are a complete, new segment called segname of the (new or existing) program called progname. U,SEGMENT progname segname The cards that follow are revisions to segment segname of program progname. U,ENDSEG This is the end of the segment (or its revisions). U,ENDPROG This is the end of the program (or its revisions).
References
- 1 2 3 Company Sales Manual for the Honeywell 1800
- ↑ The initial author of this article programmed a Honeywell 1800 for Eastern Electricity Board, UK from January to August 1966 and this article is mainly written from memory. If anyone has documentary material and can review and correct the article, providing inline references, that would be useful. This information is broadly correct but a few errors of detail may be found. It seems better to write some article from memory than wait for a fully referenced article that may never emerge. Honeywell was a significant force in the embryo computer industry and its work is worth recording
- ↑ It may have had another name but its function was to keep track of the word in memory
- ↑ I never saw this used except in Honeywell’s own macros
- 1 2 Not sure about this number
- ↑ I think the maximum was 63
- ↑ I think the maximum was 15
- ↑ Possibly it jumps on EQUAL and continues on UNEQUAL. Not quite sure
- ↑ Possibly the other way around
- ↑ which I did not learn
- ↑ Detail of Compute Ortho needs checking
- ↑ I am guessing a bit here
External links
Ascher Opler and Myra Gray, (1961), Design of a multiprogrammed algebraic compiler (Subscription only)
- Automatic Routine Generating and Updating System. From HOPL: an interactive Roster of Programming Languages. See History of Programming Languages Conference.