-
Notifications
You must be signed in to change notification settings - Fork 2
Assembler
VERY IMPORTANT NOTE: In the bizarre world of Nova systems, Data General decided that the most significant bit is 0 while the least significant bit is 15. Any mention of bit ordering in this document will be following this standard in order to be easily understood in the context of other Nova reference material.
This is a segmented assembler, meaning that your code should be split into several distinct segments in memory. The following segments are recognized by the assembler:
- Zero Page - A segment consisting of exactly the first 256 words of memory, used for speedy zero page addressing.
- Stack - A segment allocated in multiples of 1024 words, used for stack operations on systems that support it.
- Text - A read only segment where your executable code is stored.
- Data - A writable segment used to store predefined values or self modifying code.
- Bss - A segment generated on program load, filled entirely with zeros up to a specified length.
The segments as they appear by default in memory:
[Bottom of memory: 0x0000]
Zero Page (Always from 0 to 0xFF)
Stack (Optional: 0x100 to N * 1024)
Text
Data
Bss
(Any remaining free memory)
[Top of memory: 0x7FFF]
The Text, Data, and Bss segments may be placed anywhere in memory (above 0xFF) so long as they are immediately adjacent to one another and appear in the order specified above. The assembler automatically places each segment in the lowest possible memory location starting at 0x100, just after the zero page segment. Even if the Stack segment size and Zero Page segment size are zero, the Text segment will still appear at 0x100.
There are a variety of constants supported by the assembler, including both single-word integers and multi-word strings.
Integers can be specified in the following numerical bases and will be truncated to 16 bits:
- Base 2 (Binary) - Can contain numbers
0and1, should be prefixed by0bor0B, example:0b1010111011001 - Base 8 (Octal) - Can contain numbers
0through7, should be prefixed by a single0, example:017324 - Base 10 (Decimal) - Can contain numbers
0through9, and does not require a prefix, example:1056 - Base 16 (Hexadecimal) - Can contain numbers
0through9and lettersAthroughF(representing values 10 to 15), should be prefixed by0xor0X, example:0x4F5A
Strings can be specified with either single quotes ' or double quotes ". A string may occupy multiple lines, in which case the line endings are included as part of the string. Double quoted strings are null-terminated (a zero value character is automatically included at the end) while single quoted strings are not. All strings are double packed, meaning that there are two 8-bit characters per word of memory. In the two character string AB the most significant 8 bits 0 to 7 hold the character A while the least significant 8 bits 8 to 15 hold the character B. In the event a string contains an odd number of characters, the least significant 8 bits 8 to 15 of the final word of the string will be zero. If double packed strings are not desired, the .wstr directive is available.
The following escape sequences are recognized:
-
\a(0x07) - Bell -
\b(0x08) - Backspace -
\e(0x1B) - Escape -
\f(0x0C) - Formfeed page break -
\n(0x0A) - Newline -
\r(0x0D) - Carriage Return -
\t(0x09) - Horizontal Tab -
\v(0x0B) - Vertical Tab -
\\(0x5C) - Backslash (The actual ascii character\) -
\'(0x27) - Single Quotation (The actual ascii character') -
\"(0x22) - Double Quotation (The actual ascii character") -
\nnn- Wherennnis a 1 to 3 digit octal number, not exceeding the value0377 -
\xhh- Wherehhis a 1 or 2 digit hexadecimal number
On a given line, any characters following a ; character are ignored by the assembler.
(TODO)
When in doubt, the -h option will display the help info.
The -t [1-31] argument allows you to specify the number of pages you wish to allocate to the stack according to this equation: Stack Size (in words) = N * 1024 - 256
The -g option forces every label to be global (every label will be accessible from every file)
A variety of output formats are supported by the assembler:
By default, the assembler will generate a binary executable file in a format very reminiscent of the original Unix a.out. However the format is not exact to any existing standard and has been specially designed for use with the Data General Nova architecture.
The -mh and -ma options will generate a binary file that can be loaded by SimH Nova Simulator. The -ma options specifies that the executable should auto-start on load.
The -mv options will generate a human readable version of the program which can be directly entered into the Nova 4's virtual console. This format is also very convenient for inputting a program with your Nova's frontpannel.
This assembler was designed with the Nova 4 instruction set in mind. The Nova 4 instructions are a superset of the original Nova instruction set so it should work with older machines provided you do not use avoid certain instructions.
Any of the instructions specified below may be suffixed with their appropriate flags as desired.
Includes: NIO, DIA, DOA, DIB, DOB, DIC, DOC, SKPBN, SKPBZ,SKPDN, SKPDZ
Format: <INSTRUCTION> <DEVICE NUMBER>
Device Number is any integer between the decimal values of 0 to 63.
Examples:
NIO 45
DOB 17
DIAS 22
SKPBN 37
Format: <INSTRUCTION> <DEVICE ALIAS>
Device Number is a official Data General alias for a given device such as: TTI, MDV, DSK.
Examples:
SKPDZ TTI
NIO DSK
DOA MDV
Includes: JMP, JSR, ISZ, DSZ
Format: <INSTRUCTION> [INDIRECT]<DISPLACEMENT>[, MODE]
Indirect (Optional): The following character: @. (See label topic for more info)
Mode (Optional): Value between 0 and 3, default is 0.
0 - Zero Page absolute addressing
1 - Program Counter relative addressing
2 - Accumulator 2 relative addressing
3 - Accumulator 3 relative addressing
Displacement: When mode is zero, an integer between decimal values 0 to 256. When mode is non-zero, an integer value between decimal values -128 to 127.
Examples:
JMP @194
JSR 182, 0
ISZ @-125, 1
DSZ 117, 3
Format: <INSTRUCTION> [INDIRECT]<LABEL>
Indirect (Optional): The following character: @. (See label topic for more info)
Label: A label declared within the zero page segment, or a label declared within the same segment as this instruction. If the label is not a zero page label, it must be no fewer than 128 words behind from this instruction and no more than 127 words ahead of this instruction. If an undefined global label is used then it is flagged as a "zero page undefined" label. This means that when this label is eventually declared, it must be a zero page label or a linking error will occur.
Examples:
JMP myLabel
DSZ @myIndirectLabel
Includes: LDA, STA
Format: <INSTRUCTION> <ACCUMULATOR>, [INDIRECT]<DISPLACEMENT>[, MODE]
Indirect (Optional): The following character: @. (See label topic for more info)
Accumulator: A value between 0 and 3, specifying which accumulator to load from or store to.
Mode (Optional): Value between 0 and 3, default is 0.
0 - Zero Page absolute addressing
1 - Program Counter relative addressing
2 - Accumulator 2 relative addressing
3 - Accumulator 3 relative addressing
Displacement: When mode is zero, an integer between decimal values 0 to 256. When mode is non-zero, an integer value between decimal values -128 to 127.
Examples:
LDA 3, @194
STA 1, 182, 0
STA 2, @-125, 1
LDA 0, 117, 3
Format: <INSTRUCTION> <ACCUMULATOR>, [INDIRECT]<LABEL>
Accumulator: A value between 0 and 3, specifying which accumulator to load from or store to.
Indirect (Optional): The following character: @. (See label topic for more info)
Label: A label declared within the zero page segment, or a label declared within the same segment as this instruction. If the label is not a zero page label, it must be no fewer than 128 words behind this instruction and no more than 127 words ahead of this instruction. If an undefined global label is used then it is flagged as a "zero page undefined" label. This means that when this label is eventually declared, it must be a zero page label or a linking error will occur.
Examples:
LDA 3, myLabel
STA 0, @myIndirectLabel
Includes: COM, NEG, MOV, INC, ADC, SUB, ADD, AND
Format: <INSTRUCTION>[NO LOAD] <SOURCE ACCUMULATOR>, <DESTINATION ACCUMULATOR>[, SKIP]
Source Accumulator: An integer between 0 and 3 specifying the source accumulator for this operation.
Destination Accumulator: An integer between 0 and 3 specifying the destination accumulator for this operation.
No Load (Optional): The following ascii character #, which specifies that the destination accumulator should not be modified by this operation. If a No Load is specified, then a valid Skip must be provided.
Skip (Optional): One of the following skip conditions: SKP, SZC, SNC, SZR, SNR, SEZ, SBZ
Examples:
ADD 0, 3
ADC 2, 1, SZR
SUB# 1, 0, SKP
NEG 0, 0
.text - All input following this directive will be placed into the text segment (this is the default segment for each file)
.data - All input following this directive will be placed into the data segment
.zero - All input following this directive will be placed into the zero page segment. If the amount of data in the zero page segment exceeds 256 words, an error will be thrown.
.bss - Switch to BSS segment allocation mode. In this mode labels can still be declared, but no actual data or instructions can be stored in this segment. Instead, space which will be automatically initialized to zero can be allocated by providing a positive integer.
In this example, 1 word of space is allocated for myValueA followed by 20 words of space for for myArrayB. Then 4 words are allocated, but no label points to them. Finally, a single word is allocated for myValueC.
.bss
myValueA: 1
myArrayB: 20
4
myValueC: 1
Format: .glob <LABEL1>, <LABEL2>, <LABEL3>, ... , <LABEL_LAST>
This directive will flag each of the provided labels as global allowing them to be accessed from inside other files. The -g command line argument can be used to declare all labels as global in which case this directive is useless.
Format: .ent <LABEL>
Label: A label in the text segment from which program execution should begin
Format: .wstr <STRING>
String: Either a single or double quoted string.
Inserts the given string into the current segment where each character of the string occupies an entire word. This directive is useful if you do not want two characters packed into a single word and simplifies accessing an individual character. However, a word string will waste twice as much space as a normal string. An error will occur if the current segment is bss.