perm filename FAIL.DOC[CMU,AIL] blob
sn#288418 filedate 1977-06-19 generic text, type T, neo UTF8
FAIL
Sponsored by
Advanced Research Projects Agency
ARPA Order No. 2494
Stanford Artificial Intelligence Laboratory June 1977
Memo AIM-291
Computer Science Department
Report STAN-CS-76-577
FAIL
by
F. H. G. Wright II
R. E. Gorin
COMPUTER SCIENCE DEPARTMENT
STANFORD UNIVERSITY
Abstract
This is a reference manual for FAIL, a fast, one-pass assembler for
PDP-10 and PDP-6 machine language. FAIL statements, pseudo-
operations, macros, and conditional assembly features are described.
Although FAIL uses substantially more main memory than MACRO-10, it
assembles typical programs about five times faster. FAIL assembles
the entire Stanford A. I. Lab time-sharing operating system (two
million characters) in less than four minutes of CPU time on a KA-10
processor. FAIL permits an ALGOL-style block structure which
provides a way of localizing the usage of some symbols to certain
parts of the program, such that the same symbol name can be used to
mean different things in different blocks.
This manual was supported by the Advanced Research Projects Agency of
the Department of Defense under Contract No. MDA903-76-C-0206. The
views and conclusions contained in this document are those of the
authors and should not be interpreted as necessarily representing the
official policies, either expressed or implied, of Stanford
University, the Advanced Research Projects Agency, the U.S.
Government, or, for that matter, anyone else.
This manual supersedes SAILON-26 and AIM-226.
Available from the National Technical Information Service,
Springfield, Virginia 22161.
Acknowledgments
The original version of FAIL and the original manual (SAILON-26) were
written by Phil Petit in 1967. Various additions and modifications
were subsequently contributed by William Weiher, Fred Wright, Ralph
Gorin, and others. This manual was prepared using PUB, the document
compiler created by Larry Tesler. Brian McCune and Les Earnest
reviewed the manuscript and made helpful suggestions.
FAIL i
Table of Contents
Section Page
1. Introduction 1
2. Basic Syntax 2
2.1 Statements 2
2.1.1 Instruction Statement . . . . . . . . . 3
2.1.1.1 Opcode Field . . . . . . . . . 3
2.1.1.2 Accumulator (AC) Field . . . . . . 4
2.1.1.3 Indirect (@) Field . . . . . . . 4
2.1.1.4 Address Field . . . . . . . . . 4
2.1.1.5 Index Field . . . . . . . . . . 5
2.1.2 Halfword Statement . . . . . . . . . . 5
2.1.3 Full-Word Expression . . . . . . . . . . 5
2.1.4 Truncated Expression . . . . . . . . . . 6
2.1.5 Input-Output Instruction Statement . . . . . 6
2.1.5.1 Device Selection Field . . . . . . 6
2.1.6 Comment Field . . . . . . . . . . . . 7
2.1.7 Statement Termination . . . . . . . . . 7
2.2 Expressions 7
2.3 Atoms 10
2.3.1 Identifiers . . . . . . . . . . . . 10
2.3.2 Values . . . . . . . . . . . . . 10
2.3.3 Constants . . . . . . . . . . . . 11
2.3.3.1 Simple Numbers . . . . . . . . 12
2.3.3.2 Decimal Numbers . . . . . . . 12
2.3.3.3 Scaled Numbers . . . . . . . . 12
2.3.3.4 Floating-Point Numbers . . . . . 13
2.3.3.5 Ascii Constants . . . . . . . 14
2.3.3.6 Sixbit Constants . . . . . . . 14
2.3.4 Symbols . . . . . . . . . . . . . 15
2.3.4.1 Labels . . . . . . . . . . 16
2.3.4.2 Parameters (Assignment
Statements) . . . . . . . . . . . . 17
2.3.4.3 Variables . . . . . . . . . 18
2.3.4.4 Predefined Symbols . . . . . . 18
2.3.4.5 Half-Killed Symbols . . . . . . 19
2.3.4.6 Block Structure . . . . . . . 20
2.3.4.7 Linkage with Separately
Assembled Programs . . . . . . . . . 23
2.3.4.8 Symbols and Arrows . . . . . . 24
2.3.5 Complex Atoms . . . . . . . . . . . 25
2.3.5.1 Atomic Statements . . . . . . . 25
2.3.5.2 Literals . . . . . . . . . . 26
ii Table of Contents FAIL
3. Pseudo-Ops 28
3.1 Destination of Assembled Code 28
3.1.1 LOC, RELOC, and ORG . . . . . . . . . 28
3.1.2 SET and USE . . . . . . . . . . . . 29
3.1.3 PHASE and DEPHASE . . . . . . . . . . 30
3.1.4 HISEG . . . . . . . . . . . . . . 30
3.1.5 TWOSEG . . . . . . . . . . . . . 30
3.1.6 LIT . . . . . . . . . . . . . . 32
3.1.7 VAR . . . . . . . . . . . . . . 32
3.2 Symbol Modifiers 33
3.2.1 OPDEF and .GOPDEF . . . . . . . . . . 33
3.2.2 BEGIN and BEND . . . . . . . . . . . 33
3.2.3 GLOBAL . . . . . . . . . . . . . 34
3.2.4 INTERNAL and ENTRY . . . . . . . . . 34
3.2.5 EXTERNAL . . . . . . . . . . . . . 34
3.2.6 LINK and LINKEND . . . . . . . . . . 35
3.2.7 .LOAD and .LIBRARY . . . . . . . . . 35
3.2.8 PURGE . . . . . . . . . . . . . . 36
3.2.9 XPUNGE . . . . . . . . . . . . . 36
3.2.10 SUPPRESS and ASUPPRESS . . . . . . . . 37
3.2.11 UNIVERSAL . . . . . . . . . . . . 37
3.2.12 SEARCH . . . . . . . . . . . . . 38
3.3 Entering Data 39
3.3.1 DEC and OCT . . . . . . . . . . . . 39
3.3.2 BYTE . . . . . . . . . . . . . . 39
3.3.3 POINT . . . . . . . . . . . . . . 39
3.3.4 XWD . . . . . . . . . . . . . . 40
3.3.5 IOWD . . . . . . . . . . . . . . 40
3.3.6 ASCII, ASCIZ, ASCID, and SIXBIT . . . . . 40
3.3.7 RADIX50 . . . . . . . . . . . . . 41
3.4 Reserving Space for Data 42
3.4.1 BLOCK . . . . . . . . . . . . . . 42
3.4.2 INTEGER and ARRAY . . . . . . . . . . 42
3.5 Assembler Control Statements 43
3.5.1 TITLE . . . . . . . . . . . . . . 43
3.5.2 END and PRGEND . . . . . . . . . . . 43
3.5.3 COMMENT . . . . . . . . . . . . . 44
3.5.4 RADIX . . . . . . . . . . . . . . 44
3.5.5 .INSERT . . . . . . . . . . . . . 44
3.5.6 .FATAL . . . . . . . . . . . . . 45
3.5.7 .DIRECT . . . . . . . . . . . . . 45
FAIL Table of Contents iii
3.6 Loader Control Statements 46
3.6.1 .COMMON . . . . . . . . . . . . . 46
3.6.2 .ASSIGN . . . . . . . . . . . . . 46
3.6.3 .TEXT . . . . . . . . . . . . . . 46
3.7 Listing Control Statements 47
3.7.1 TITLE and SUBTTL . . . . . . . . . . 47
3.7.2 LIST, XLIST, and XLIST1 . . . . . . . . 47
3.7.3 LALL and XALL . . . . . . . . . . . 47
3.7.4 NOLIT . . . . . . . . . . . . . . 47
3.7.5 NOSYM . . . . . . . . . . . . . . 48
3.7.6 CREF and XCREF . . . . . . . . . . . 48
3.7.7 PAGE . . . . . . . . . . . . . . 48
3.7.8 PRINTX . . . . . . . . . . . . . 48
3.7.9 PRINTS . . . . . . . . . . . . . 48
4. Macro Operations 49
4.1 Macros 49
4.1.1 Macro Bodies . . . . . . . . . . . 50
4.1.2 Concatenation . . . . . . . . . . . 50
4.1.3 Arguments in Macro Definitions . . . . . 50
4.1.4 Macro Calls . . . . . . . . . . . . 51
4.1.5 Arguments in Macro Calls . . . . . . . 52
4.1.6 How Much is Eaten by a Macro Call . . . . 53
4.1.7 Complex Example . . . . . . . . . . 54
4.2 FOR 55
4.2.1 String FOR . . . . . . . . . . . . 56
4.2.2 Character FOR . . . . . . . . . . . 56
4.2.3 Arithmetic FOR . . . . . . . . . . . 57
4.3 REPEAT 58
4.4 Conditional Assembly 59
4.4.1 Numeric IFs . . . . . . . . . . . . 59
4.4.2 Text IFs . . . . . . . . . . . . . 59
4.4.3 Symbol IFs . . . . . . . . . . . . 60
Appendices 61
A Command Language 61
B Relocatable and Undefined Values 64
C Predefined Opcodes 65
D Stanford A. I. Lab Character Set 74
E Summary of Character Interpretations 76
iv Table of Contents FAIL
Index 79
FAIL Introduction 1
1. Introduction
FAIL is an assembly program for PDP-6 and PDP-10 machine language.
FAIL operates in one pass, which means that it reads the input file
only once; the linking loader program (LOADER or LINK-10) completes
any aspects of the assembly which could not be done by FAIL. The
efficiencies which have been employed in its coding make FAIL five
times faster than MACRO-10, the DEC assembler.
FAIL processes source program statements by translating mnemonic
operation codes into the binary codes needed in machine instructions,
relating symbols to numeric values, and assigning relocatable or
absolute core addresses for program instructions and data. The
assembler can prepare a listing of the program which includes a
representation of the assembled code. Also, the assembler notifies
the user of any errors detected during the assembly.
FAIL has a powerful macro processor which allows the programmer to
create new language elements to perform special functions for each
programming job.
FAIL permits an ALGOL-style block structure which provides a way of
localizing the usage of symbols to particular parts of the program,
called blocks. Block structure allows the same symbol name to be
given different meanings in different blocks.
The reader of this manual should be familiar with the PDP-10
instruction set, which is described in both DECsystem-10 System
Reference Manual and PDP-10 and PDP-6 Instruction Sets (SAILON-71).
Other documents of interest:
Frost, M. UUO Manual, SAILON-55.3, December 1973
Petit, P. RAID, SAILON-58, September 1969
Harvey, B. Monitor Command Manual, SAILON-54.3, December 1973
The following are available in the DECsystem-10 Software Notebooks:
Cross-Reference Listing: CREF, June 1973
DDT-10 Programmer's Reference Manual, June 1973
Linking Loader Programmer's Reference Manual, August 1971
LINK-10 Programmer's Reference Manual, May 1973
MACRO-10 Assembler Programmer's Reference Manual, June 1972
DECsystem-10 Operating System Commands, February 1974
DECsystem-10 Monitor Calls, June 1973
2 Basic Syntax FAIL
2. Basic Syntax
This section describes the basic components of a typical FAIL source
program. It covers the normal mode of turning each source statement
into a binary word. Pseudo-operations and macro features are
explained in later sections.
This section is organized in a top-down manner: the complex
constructs, statements, are described first, followed by a
description of the language elements from which statements are built,
etc.
Statements are the elements of the language that generate machine
code and other binary data. A statement is generally free format,
consisting of several fields, each of which is an expression.
Expressions are composed of atoms and operators. The operators
signify typical arithmetic and boolean operations, such as addition
or logical OR. Atoms are either constants, symbols, or complex
atoms.
2.1 Statements
Statements are the syntactic units which actually produce code. The
statements that are described in this section usually generate one
word of code. A null statement, which consists of no expressions,
generates no code. A typical statement consists of one or more
expressions separated by spaces, commas, or parentheses.
There are five kinds of statements: instruction statements, full-word
expressions, truncated expressions, halfword statements, and input-
output statements. The most common of these is the instruction
statement. Also, there are pseudo-operations (called pseudo-ops),
which are described in section 3, page 28. A pseudo-op may
direct FAIL to perform an assembler control function or to assemble
data in a particular format.
The examples that are given below are intended to be as general as
possible. In most cases, many of the indicated fields may be
omitted.
FAIL Basic Syntax 3
2.1.1 Instruction Statement
OPCODE AC,@ADDRESS(INDEX) ;COMMENT
An instruction statement is used to assemble one machine instruction.
The typical format is shown above; the parts will be explained later.
Any portion of the instruction statement may be omitted. The comment
field is not really part of the instruction statement, but may be
included on the same line for clarity and conciseness. The parts may
appear in any order, except that the opcode field, if present, must
be the first expression. Also, each part must be syntactically
identifiable. The form above is hallowed by years of use; departure
from it will render a program less intelligible to other readers.
If the opcode field is omitted, all other fields will be recognized
and handled normally, unless the address expression is the first
field seen, in which case the statement is treated as a full-word
expression.
2.1.1.1 Opcode Field
If the first atom appearing in the statement (excluding labels and
assignment statements) is an identifier, it will be looked up in the
opcode table to see if it is an opcode, in which case the opcode
alone will be returned as the first expression, overriding any
significance it may have as a symbol. An opcode (short for operation
code) may be a machine instruction mnemonic, a UUO mnemonic, a
pseudo-op, or a user-defined opcode (see OPDEF in section 3.2.1,
page 33). An opcode, if it appears, must be the first thing in the
statement (except for labels or assignment statements).
If an opcode is a pseudo-op mnemonic, FAIL will process that
particular pseudo-op as appropriate. The syntax of pseudo-ops
differs from that of normal statements.
If an opcode is a machine instruction, UUO mnemonic, or user opcode,
its value is placed in the binary word being assembled. These
opcodes are treated as having full-word values, but in most cases
only the opcode field (bits 0-8) is non-zero. A few machine
instructions, and many UUO mnemonics, specify values for other fields
as well. The values of the other fields (except the address field,
if non-zero) can be modified by subsequent operands.
Whenever an opcode is recognized, it is immediately processed without
regard for any arithmetic operator that might follow. Although FAIL
tries to allow a symbol and opcode with the same name to co-exist, it
cannot resolve the ambiguity in all circumstances; it is a good idea
4 Basic Syntax FAIL
to avoid conflicts as much as possible. FAIL will not recognize an
identifier as an opcode if the identifier is followed by any one of
the characters colon (:), left-arrow (←), up-arrow (↑), tilde (~), or
number sign (#).
2.1.1.2 Accumulator (AC) Field
If an expression appears in a statement followed by exactly one
comma, its value will be placed in the accumulator field of the
current word (bits 9-12), possibly replacing the accumulator field
indicated by an opcode. This expression must be defined, available,
and absolute (some of these terms are defined in section 2.3.2,
page 10). For the sake of brevity, "accumulator" is often written as
"AC".
2.1.1.3 Indirect (@) Field
If one or more at-sign characters (@) appear as part of a statement,
the indirect bit (bit 13) will be turned on in the word being
assembled. The at-sign may appear anywhere in the statement as long
as it is not embedded inside symbols or expressions. The character
open single quote (`) may be used as an alternative to at-sign.
2.1.1.4 Address Field
If in a statement an expression appears which is neither enclosed in
parentheses nor followed by a comma, it is considered to be an
address expression unless it is the first expression (including the
opcode) in the statement. Address expressions are truncated to 18
bits and placed in the address field (bits 18-35) of the word being
assembled.
Only one address field may be assembled per statement; an attempt to
assemble more than one is an error. This error sometimes occurs
because an undefined opcode is used, which is treated as an
expression in case it is really an undefined symbol. This error can
also occur when an opcode includes an address field and the user
attempts to supply another address field.
FAIL Basic Syntax 5
2.1.1.5 Index Field
If an expression is enclosed in parentheses in a statement, the right
half of its value will be ORed into the left half of the current
word. Also, if no address field has appeared yet, the left half of
its value will be ORed into the right half of the current word. The
expression must be defined, available, and absolute. This construct
is most commonly used for specifying the index field (bits 14-17).
Sometimes, this construct is used for putting left-half quantities in
address fields, or as a general halfword-swapping operation. Often
when this is done, the expression in parentheses must be enclosed in
brokets (< and >) to force its evaluation as an atomic statement; see
section 2.3.5.1, page 25. If the left half of the expression is non-
zero, the word will be flagged as containing an address field, making
another address field illegal.
Examples:
MOVEI 2,-1(6) ;assembles 201106 777777
MOVSI 1,(<JRST>) ;assembles 205040 254000
2.1.2 Halfword Statement
EXPR,,@ADDRESS(INDEX) ;COMMENT
If an expression is followed by comma-comma (,,), it will be placed
in the left halfword of the current location, and FAIL will continue
to process an address field, index field, and indirect field. This
is more convenient than the XWD pseudo-op for assembling halfwords
since it allows the entire effective address to be specified in the
usual way. The only restriction is to beware of possible
interpretation of the first symbol as an opcode. If the expression
followed by the comma-comma is not the first thing assembled in the
word, the warning message Illegal ,, will be printed, although the
statement will assemble correctly. This prevents confusion if an
extra comma is typed after an accumulator field.
2.1.3 Full-Word Expression
EXPR ;COMMENT
When the first expression in a statement is not preceded by a comma
and is not an opcode, FAIL assumes that the expression is a full-word
expression. The entire 36-bit value of the expression is placed in
6 Basic Syntax FAIL
the current word. The full-word expression is the only ordinary
statement (i.e., not a pseudo-op) that assembles a single expression
with a full 36-bit value. Full-word expressions are treated as
address fields for purposes of the multiple address field error.
If a full-word expression contains any undefined symbols, unavailable
symbols, or strange relocation constants, the entire word will be
updated with the value of the expression when it becomes known. This
will obliterate any index, indirect, or accumulator field appearing
after the expression on the line. If the expression actually has
only an 18-bit value, this can be fixed by prefixing the expression
with a comma (i.e., by using a truncated expression). If a full-word
value is actually needed and the problem is not just one of
availability (curable by the use of GLOBAL or down-arrow (↓); see
section 2.3.4.6, page 21), it may be necessary to use an explicit
expression to set the accumulator, index, and indirect fields.
2.1.4 Truncated Expression
,EXPR ;COMMENT
If a comma appears before any expression in a statement, it flags the
current word as containing data in order to force a subsequent
expression to be treated as an address field even when it is the only
expression in the statement. This can be used to form an 18-bit
truncated expression. Note that a statement consisting of a single
comma will assemble a zero word.
2.1.5 Input-Output Instruction Statement
OPCODE DEV,@ADDRESS(INDEX) ;COMMENT
An input-output instruction statement is used to assemble one
hardware I/O instruction. Most parts are the same as in an
instruction statement, except that a device selection field appears
instead of an accumulator field. Also, the opcode portion must be
one of the PDP-10 hardware input-output instructions (e.g., DATAO).
Note that hardware I/O instructions are not related to operating
system UUOs.
2.1.5.1 Device Selection Field
The same syntax and restrictions that apply to an accumulator field
apply also to the device selection field. The value of the device
selection field is right-shifted by two places (by convention, device
FAIL Basic Syntax 7
numbers are multiples of 4) and stored in bits 3-9 of the current
word. This value is often called the device code or the device
number.
2.1.6 Comment Field
When FAIL's statement processor encounters a carriage return or
semicolon (;), all characters up to the next line feed or form feed
are completely ignored except for listing and certain macro processor
functions (see section 4.1, page 49). Upon reaching the line
feed or form feed, the comment is terminated. Usually, this is used
to insert a relevant comment at the end of a line of code.
2.1.7 Statement Termination
A statement is terminated by a comment or by any of the characters
line feed, double-arrow (↔), right bracket (]), or right broket (>)
when not processing a comment. When a statement is terminated, the
value of the current word (if any) is returned. A statement returns
no value at all if no expressions appear in it or if it is a pseudo-
op which assembles no code. Terminating a statement with one of the
bracket characters often has special significance, as in atomic
statements or literals. Double-arrow can be used for assembling more
than one statement on a line, but will not terminate a comment.
2.2 Expressions
Expressions are built from atoms connected by operators which allow
the specification of values based upon arithmetic and logical
functions of several values. These expressions follow essentially
the same rules as conventional programming languages. Each operand
in an expression may be an atom, an atomic statement, or an
expression in parentheses, preceded by any number of unary operators.
If parentheses are used, the expression inside the parentheses is
evaluated before performing any operations using that operand. If a
unary operator appears, its function will be evaluated before any
operations using that operand (but after the expression in
parentheses, if parentheses are used). Multiple unary operators are
evaluated from right to left, so -¬1 is processed as -(¬1). Finally,
these operands can be connected with binary infix operators whose
order of evaluation is determined by their assigned precedence levels
8 Basic Syntax FAIL
(highest first) and is left-to-right for operators of the same level.
An expression may, of course, consist of a single operand (i.e.,
atom) with no operators at all.
Surrounding an entire expression with parentheses sometimes signifies
an index field (see section 2.1.1.5, page 5). All arithmetic is
integer or boolean; no type conversion is done for floating-point
operands.
The following is a list of the available operators and their
precedence levels:
Symbol Meaning Precedence Level
binary operators
+ Addition 1
- Subtraction 1
* Multiplication 2
/ Division 2
∂ Remainder from Division 2
& Logical AND 3
∧ Logical AND 3
! Logical OR 3
∨ Logical OR 3
≠ Exclusive OR 3
≥ Exclusive OR 3
⊗ Logical Left-Shift 4
unary operators
- Negation (two's complement) 5
¬ Logical NOT (one's complement) 5
| Absolute Value 5
∃ JFFO (bit number of the first
1 in the binary representation
of the argument) 5
If an expression contains any undefined values, its own value is
undefined. If an expression is used in a context where undefined
values are legal, FAIL retains a structure describing the evaluation
needed, called a Polish fixup for its similarity to Polish arithmetic
notation, in order to complete the evaluation when the unknowns
become defined. As soon as all values in the expression are defined,
a fixup will be output (to the loader) to correct the value (or the
value will be corrected directly in the case of a literal). If the
expression is not completely defined by the end of the assembly (due
to external references or errors), the Polish structure is sent to
FAIL Basic Syntax 9
the loader for evaluation at load time. In other words, the right
thing usually happens with a partially undefined expression as long
as it is legal in the context where it is used.
Expressions may also begin with any number of labels or assignment
statements, which have no effect on the value of the expression.
Examples
FOO⊗2 ;value of FOO shifted left 2 bits
(BAR-1)⊗-2 ;value of BAR-1 shifted right 2 bits
(A+2)*B
-(A+2)*-B ;same value as above
<A+2>*B ;another way (The symbol A must
;be defined and available. See
;Atomic Statements, section 2.3.5.1, page 25)
=60*=60
"A"-40
[0]-1 ;even literals can appear in expressions
FOO:BAR←1 105 ;the value of this expression is 105
;(labels and assignment statements have no
;effect on the value of the expression)
∃1 ;value is 43 (bit 35 is the leftmost 1)
∃4 ;value is 41
∃-1 ;value is 0 (bit 0, the sign bit, is 1)
∃0 ;value is 44 (no bits are 1)
7/3 ;value is 2
6∂5 ;value is 1
Note: the operators ∂, ∃, and | are new. They require a modification
to the loader to handle additional Polish operators. Unless this
modification has been made, do not attempt to use these operators
where the value of their arguments is undefined.
10 Basic Syntax FAIL
2.3 Atoms
An atom is the most basic syntactic element. An atom is either a
symbol or a constant. There are also complex atoms which are not
really atoms at all, but which can be used in the same way as atoms
in forming expressions. Every atom represents a value.
2.3.1 Identifiers
Identifiers are very basic syntactic elements. They have many
different uses, all of which involve referring to something by a
convenient symbolic name. The uses of identifiers will be covered as
the various applications arise. Identifiers may be defined either by
the programmer or by FAIL.
The characters legal in an identifier are letters, digits, and the
four characters dollar sign ($), percent sign (%), point (.), and
underbar (_). An identifier is any non-null string of characters
from this set, delimited by characters not from this set, except that
the first character of an identifier must not be a digit. Only the
first six characters of an identifier are significant, and upper and
lower case letters are treated as equivalent. Thus "FOOBAR" and
"foobarbletch" are equivalent identifiers. Also, "_" is considered
equivalent to ".", so, for example, "A_7" and "A.7" are equivalent
identifiers.
Certain identifiers have special meaning in FAIL, and cannot be used
except with their own special meanings. Some of these reserved
identifiers are IFAVL, IFDEF, IFDIF, IFE, IFG, IFGE, IFIDN, IFL,
IFLE, IFMAC, IFN, IFNAVL, IFNDEF, IFNMAC, IFNOP, IFOP, IOWD, .INSERT,
.FNAM1, .FNAM2, .CPU., ".", and "$.".
2.3.2 Values
Most of the normal assembly process consists of translating text
strings into their corresponding binary values. The main
transformation happens when the atomic elements are converted to
their binary representations; these are combined by binary
operations into more complex constructs.
Often the final 36-bit value of an atom depends upon information not
available at the time the atom is seen. This value may become known
when a later part of the program is assembled, or it may not be known
until the program is actually loaded. Consequently, up until the
FAIL Basic Syntax 11
final loading of a program into a core image, its representation must
be a slightly expanded form of simple binary so that the steps
necessary to complete the calculation of all binary values can be
adequately described. Partially defined values are commonly used in
writing FAIL programs; several mechanisms exist to enable FAIL (and
the loader) to handle such values correctly. The full impact of
forward references and relocatable values is discussed in appendix
B, page 64.
Some of the different kinds of values that often occur in FAIL are
distinguished by particular names: relocatable, absolute, defined,
undefined, available, and unavailable. The definitions that follow
involve symbols and block structure to some extent. Refer to section
2.3.4, page 15, and section 2.3.4.6, page 20, for further
elucidation.
A value that depends on where the program is when it is loaded in
core is called relocatable. Relocatable values occur most frequently
when some location in the program or in the data is referred to.
Values that do not depend on where the program is located are called
absolute or unrelocatable. An example of an absolute value is a
constant. Another example of an unrelocatable value is the length of
a table (that is, the difference between two relocatable values).
A symbol is an identifier that has a value. A symbol is defined when
a value is assigned to it. A symbol can be referenced before it is
defined, that is, when the value of the symbol is undefined. FAIL
makes sure that the right thing happens when the value becomes
defined as long as an undefined value is legal in the particular
context where it is used.
A symbol that is defined is said to be available (after the point of
definition) in the block where it is defined. When another (lower)
block is entered, such a symbol becomes unavailable unless the
programmer has taken steps to force the availability of that symbol
in lower blocks.
2.3.3 Constants
Constants are the simplest forms of atoms; their values do not
depend on context or previous operations (with the exception of the
radix for interpretation of numbers). Constants are absolute, i.e.,
independent of where the program is loaded. A constant may be one of
several types of numerical or text constants. In addition to the
atomic constants described here, there are various data entry pseudo-
ops described in section 3.3, page 39.
12 Basic Syntax FAIL
2.3.3.1 Simple Numbers
A simple number consists of a string of digits, interpreted as a
number in the current radix. Since the radix is initialized to 8,
simple numbers are usually interpreted as octal by default. In this
case, the accumulation is done by logical shifting, so the number is
considered unsigned. If the radix is anything other than 8, the
accumulation is done by multiplication, and the sign bit cannot be
set (but a negative number can be entered as an expression). The
current radix can be set with the RADIX pseudo-op (see section
3.5.4, page 44).
Examples:
1743
2
2.3.3.2 Decimal Numbers
Decimal numbers provide a way of entering decimal information
regardless of the current radix. A decimal number is a simple number
preceded by an equal sign (=).
Examples:
=100 assembles as: 000000000144
=69 000000000105
2.3.3.3 Scaled Numbers
A simple number or decimal number may be followed by the letter "B"
and a scale factor. The scale factor may be any atom that is defined
and absolute. Any simple numbers that appear in the scale factor
will be interpreted as decimal, regardless of the current radix. The
value of the scale factor specifies the low-order bit position of the
number in the word. That is, the number preceding the B is shifted
left logically a number of bit positions equal to 35 (decimal) minus
the scale factor.
FAIL Basic Syntax 13
Examples:
254B8 assembles as: 254000000000
1B33 000000000004
22B18 000011000000
22B<17+1> 000011000000
10B37 000000000002
=10B27 000000005000
2.3.3.4 Floating-Point Numbers
Numbers may also be entered in standard floating-point notation, in
which case they will be converted to PDP-10 single-precision
floating-point format. Floating-point numbers are always interpreted
in decimal regardless of the current radix. Note that any arithmetic
performed by FAIL on numbers is always integer arithmetic, even if
the operands are floating-point numbers.
A floating-point number consists of two strings of digits, separated
by a decimal point and followed by an optional scale factor. The
digit strings before and after the decimal point represent the
integer and fraction parts of the floating-point number,
respectively. The scale factor is the letter "E", an optional minus
sign, and one or two digits. The number following the "E" specifies
a power of ten by which the number will be multiplied.
Although the fraction part of the number may be omitted, it is
probably better to include the redundant 0 to avoid a possible future
conflict that could arise if FAIL were modified to allow a decimal
point following a digit string to signify a decimal number.
Examples:
10.7E1 ;equivalent to 107.0
9.973
0.13
10. ;better to write this as 10.0
1.86E05
31.4159E-1
69E1 ;presently equivalent to 690.0
14 Basic Syntax FAIL
2.3.3.5 Ascii Constants
Constants may also be specified as the ascii value of a character or
string of characters. The ascii value of a character is its 7-bit
code in the Stanford Character Set, a modified form of the USASCII
code (see appendix D, page 74). An ascii constant is written as a
string of characters not containing a double quote ("), enclosed with
double quotes, e.g, "Foo". If the string is null, i.e., "", the
resulting value will be zero. If the string contains exactly one
character the resulting value will be the ascii value of that
character. If the string contains more than one character, each
additional character will shift the total left 7 bits and add its own
value, much as an octal number is accumulated. This results in
packing characters into right-justified 7-bit bytes. Only the low-
order 36 bits of the total are used, so if more than 5 characters
appear in the string, only the last 5 characters and the low-order
bit of the sixth-from-last character will affect the value.
This right-justified form is not the standard way of packing text for
addressing with byte instructions, but is intended mainly for small
immediate operands, etc. Text pseudo-ops (described in section
3.3.6, page 40) are used to store text in the usual left-justified
format in multiple words.
Examples:
"A" ;101 octal
"↑C" ;27503
"foobar" ;337576130362
2.3.3.6 Sixbit Constants
Another character code that is frequently used is sixbit. It is a
modified version of ascii code which uses only 6, instead of 7, bits
in order to pack 6 characters into a word rather than 5.
The basic ascii to sixbit transformation consists of subtracting 40
(octal) from the ascii code, which maps ascii 40-137 (all the
printing characters of 64-character ASCII) into the desired 0-77.
Since the 140-177 range consists mostly of lower-case versions of the
100-137 characters, a better transformation also maps this range to
40-77. The method used by FAIL is to copy the 100 bit into the 40
bit and set the 100 bit to 0. The inverse transformation is
accomplished by adding 40 to each sixbit character.
Sixbit constants can be specified in FAIL in the same way as ascii
FAIL Basic Syntax 15
constants, except that close single quotes (apostrophes) (') should
be used instead of double quotes. Naturally, if more than one
character appears in the string, the shifting will be 6 bits at a
time instead of 7, and the last 6 characters of the string will
always be completely significant. Again, a pseudo-op is available
(see section 3.3.6, page 40) to pack longer strings into multiple
words.
Examples:
'a' ;41
'DSK ' ;446353000000
'gronker' ;625756534562
2.3.4 Symbols
Symbols are one of the most important features provided by an
assembler. One capability provided by symbols is the ability to
abbreviate a complex expression with a single identifier. Another is
to represent an assembly parameter, so that its value can be changed
at the symbol definition only, without having to modify the places
where the parameter is used. A third use is to represent values
which are difficult for the programmer to calculate, such as values
dependent upon exactly where certain parts of the program are stored.
A symbol is an identifier which at some point in the program (or
possibly in an external program) is assigned a value which will be
associated with that identifier whenever it is used in a context
where symbols are recognized (see section 2.1.1.1, page 3, and
section 4.1.4, page 51, for discussion of possible conflicts with
opcodes or macros). The point at which a value is assigned to a
symbol is said to be the point where it is defined.
In most circumstances, a symbol may be used to stand for a value
either before or after it is defined. A symbol is said to be
referenced when it is used to stand for a value. If this reference
occurs earlier in the source file(s) than the definition, it is said
to be a forward reference; if the reference follows the definition,
it is said to be a backward reference. Backward references can be
handled fairly easily, by merely replacing the symbol by its known
value. However, forward references create some complication since
FAIL does not know the value of the symbol until later in the file.
Two-pass assemblers avoid the forward reference problem by assembling
the program twice. On the first pass the assembler calculates the
value for each symbol; on the second pass these known values are
used when the corresponding symbols are referenced. This method
16 Basic Syntax FAIL
probably has the smaller storage requirements, but it requires more
cpu time since the entire source file is scanned twice.
FAIL uses the one-pass approach to save execution time (at the
expense of increasing the storage requirements). In this method,
each forward reference assembles an incomplete word, but sufficient
information is included in the binary file to enable the loader to
complete the assembly. Part of the necessary mechanism exists in the
loader anyway in order to handle externally defined symbols, which
must be treated as forward references even by a two-pass assembler.
Information placed in the binary file to update the value of an
incompletely assembled word is referred to as a fixup.
Because of the problem of forward references in a one-pass assembler,
the meaning of "defined" as used in this manual is not "defined
somewhere within the program", but rather "defined in the program
before the place being considered". In this sense a symbol is not
considered to be "defined" at the time of a forward reference, even
if it is defined later in the program.
A symbol may be defined in one of four ways. It may be defined as a
label, as a parameter, or as a variable, or it may be a predefined
symbol. These types of symbols are discussed in the following
subsections.
2.3.4.1 Labels
Labels are the most common type of symbol. They are used as symbolic
references to locations in the program. Labels help to keep such
references independent of the exact placement of those parts of the
program in the core image. The value of a label is calculated
automatically by FAIL, so that the programmer need not keep careful
account of the exact numeric locations of all parts of his program.
A label is defined by simply writing an identifier followed by a
colon (:) at the beginning of any expression being scanned. This
will normally define the symbol as equal to the location counter,
i.e., the location where the next word will be assembled. However,
in some circumstances involving the use of literals (section 2.3.5.2,
page 26) or the PHASE pseudo-op (section 3.1.3, page 30), the value
of the label may differ from the location counter. The value
assigned to a label is usually relocatable because the location
counter is initialized to relocatable zero, but it may be absolute.
Although labels may occur at the beginning of any expression, they
almost always occur at the beginning of a line. This convention
improves the readability of programs by keeping labels in a place
where they are easily recognized.
FAIL Basic Syntax 17
In order to detect possible conflicts in label usage, FAIL does not
allow any label to be defined more than once. (However, FAIL block
structure allows a label to be redefined in different blocks; see
section 2.3.4.6, page 20.) Once a symbol has been defined as a label,
it cannot be redefined; a symbol cannot be defined as a label if it
has any previous definition. An attempt to do either of these things
will result in a multiple definition error message, and the new
definition will not take effect.
Examples:
LOOP: JRST LOOP ;points to itself
FOO: ;labels the location of the next instruction
2.3.4.2 Parameters (Assignment Statements)
A parameter is a symbol that is given an arbitrary 38-bit value by an
assignment statement. Actually, the final value is 36 bits, but
since either 18-bit halfword may be relocatable two more bits are
included in the representation of the value. The basic format of an
assignment statement is an identifier followed by a left-arrow (←)
followed by an expression. The 38-bit value of the expression, which
must be defined, will be given to the specified symbol. An equal sign
(=) may also be used as an alternative to left-arrow to allow partial
compatibility with other assemblers, but if the first atom after the
= begins with another = to indicate a decimal number, at least one
space should separate the two to distinguish them from ==, which has
a different function (see section 2.3.4.5, page 19).
As with labels, any number of assignment statements may appear at the
beginning of any expression, but they are normally written as
separate statements for improved readability. In its full
generality, an assignment statement may define more than one symbol
by beginning with several symbol names, each followed by a left-
arrow, and finally followed by the expression, whose value will be
given to all symbols mentioned.
Unlike labels, parameters may be redefined as often as desired. Once
a parameter has been defined, each reference to it will use the value
in effect at the time of that reference (i.e., as of the last
assignment). The value appearing in the symbol table in the binary
output file will be the last value assigned. The value used for
forward references (i.e., before the first definition) will be that
of the first assignment. Note that this is an incompatibility with
two-pass assemblers, which would instead use the last value assigned
during pass one.
18 Basic Syntax FAIL
Examples:
FOO←105
BAR←=69
BLETCH←BARF←LOSS←FOO+BAR*3
garp= =97 ;note space between = is necessary
2.3.4.3 Variables
Variables are symbols whose values are the addresses of cells
automatically allocated by FAIL for data storage. A variable is
usually created by immediately following a symbol reference with a
number sign (#). The symbol, which must not be previously defined,
is declared to be a variable and will have its location assigned when
the location of the variables area is known (see section 3.1.7,
page 32). The symbol is not defined at this point; it cannot be
used in contexts which do not allow forward references. However, it
can be used as any other forward-referenced symbol; the number sign
need not be used with more than one occurrence of the symbol.
Similar effects can also be obtained with the INTEGER and ARRAY
pseudo-ops (see section 3.4.2, page 42).
Examples:
SETZM FOO#
MOVEI A,BAR#-1
2.3.4.4 Predefined Symbols
Predefined symbols are available for use in all circumstances where
symbols are recognized.
Two predefined symbols, point (.) and dollar-point ($.) refer to the
location counter, which is the location where the next complete word
will be stored. In the absence of special circumstances, "." and "$."
have the same value; "." is the one usually used. These values are
usually relocatable but may be absolute; see section 3.1.1, page
28.
The reason for having two of these symbols is that some features of
FAIL create complications affecting the location counter; see the
discussion of literals (section 2.3.5.2, page 26) and the PHASE
pseudo-op (section 3.1.3, page 30).
FAIL Basic Syntax 19
Examples:
JRST .-1
JUMPN T,$.+3
The predefined symbols, .FNAM1 and .FNAM2 refer to the name of the
current source file. The value of .FNAM1 is the 36-bit binary
representation of the source file name; .FNAM2 has the value of the
source file extension (or second file name).
The predefined symbol .CPU. denotes the type of processor that FAIL
is running on. This symbol has the value 1 for the PDP-6, 2 for the
KA10, 3 for the KI10, and 4 for the KL10.
Two other symbols, .INSERT and IOWD, are predefined. These symbols
cause actions like pseudo ops so their descriptions appear later; see
section 3.5.5, page 44, and section 3.3.5, page 40, respectively.
2.3.4.5 Half-Killed Symbols
Symbols are included in the binary output file to aid debugging and
to allow the loader to link several programs together. The debuggers
(RAID and DDT) have symbolic disassemblers which take binary words
and interpret their fields to display mnemonic opcodes, addresses,
accumulator names, etc. Sometimes, the user wants to prevent
particular symbol names from being displayed by the symbolic
disassembler. Symbols that have been marked to prevent their display
are called half-killed. Half-killing a symbol is useful for
parameters which might incorrectly be displayed as core addresses or
accumulator names. Half-killing is also handy for labels in code
that is relocated at runtime. The debuggers do recognize half-killed
symbols when they are input.
FAIL treats half-killed symbols precisely the same as other symbols,
except, when the symbol is written in the binary output file, a bit
is set to inform the debugger that the symbol is half-killed.
In FAIL, half-killing a symbol is accomplished by doubling the
defining character (e.g., ::, ←←, or ==). In the case of ==, the two
equal signs must not be separated by any spaces, because this is how
the ambiguity is resolved with respect to the other use of equal sign
to indicate decimal numbers. A parameter will be half-killed if any
one of its definitions specifies half-killing.
20 Basic Syntax FAIL
Examples:
ERRFLG←←100 ;the usual way of writing it
IOFLG ← ← 2000 ;this can have spaces anywhere
BUFSIZ == 100 ;but this can't (100 is octal)
BUFSIZ = = 100 ;since this means decimal, not half-killed
BUFSIZ === 100 ;this is unambiguous (100 is decimal)
BUFSIZ == = 100 ;(100 is decimal)
LOOP:: SKIPN A,(B) ;a half-killed label
2.3.4.6 Block Structure
Block structure is very basic to the usage of symbols. This section
may be skipped if the reader does not plan to use block structure.
The one thing to remember is that in the absence of block structure
any symbol which is defined is also available.
FAIL block structure provides a way of localizing the usage of
symbols to particular parts of the program, called blocks. Block
structure allows the same symbol name to be given different meanings
in different blocks. The block structure used in FAIL is similar to
that of ALGOL, but is somewhat less restrictive.
A program is considered to be a block whose name is the same as the
program name (set by the TITLE statement; see section 3.5.1, page
43). Each block may contain any number of inner blocks, but the
depth of nesting may not exceed 17 (decimal). A definition of a
symbol, a user-defined opcode (see section 3.2.1, page 33), or a
macro (see section 4, page 49) applies only within the scope of
the outermost block in which it is defined. The scope of a block
includes the scope of each block it contains, unless the symbol
(etc.) in question is defined again in an inner block, in which case
the more local definition takes precedence within the scope of that
block. A block is delimited by a BEGIN statement and a BEND
statement (see section 3.2.2, page 33).
Features exist in FAIL for controlling the block level of symbols.
If a symbol, when defined as a label or parameter, is preceded by an
up-arrow (↑), it will be treated as if it were defined in the next-
outer block. If a double up-arrow (↑↑) is used, the symbol will be
treated as though it were defined in the outermost block of the
program. These features are most commonly used for such things as
making subroutine entry points available to outer blocks when the
subroutines themselves are contained in blocks. In simple cases,
this could be done by beginning the block after the entry label(s) or
even after some of the code, but this makes reading the routine more
FAIL Basic Syntax 21
difficult and hence the up-arrow construct is preferred. Tilde (~)
may be used instead of up-arrow.
Here are some examples of symbol usage, with and without block
structure. Both examples generate the same code:
FOO1: JRST FOO1 FOO1: JRST FOO1
JRST FOO2 JRST FOO2
JRST FOO3 JRST FOO3
JRST FOO5 JRST FOO5
BEGIN
FOO2: JRST FOO1 FOO22: JRST FOO1
↑FOO3: JRST FOO2 FOO3: JRST FOO22
JRST FOO3 JRST FOO3
BEGIN
JRST FOO1 JRST FOO13
↑↑FOO5: JRST FOO2 FOO5: JRST FOO22
JRST FOO3 JRST FOO3
FOO1: JRST FOO4 FOO13: JRST FOO4
BEND
↑FOO4: JRST FOO4 FOO4: JRST FOO4
BEND
FOO2: JRST FOO4 FOO2: JRST FOO4
A complication arises with FAIL block structure due to the absence of
the ALGOL requirement that all identifiers be declared at block entry
time. FAIL allows forward references, yet does not require any
declaration of symbols other than their defining occurrences. Hence,
FAIL cannot decide whether to use an existing outer-block version of
a symbol or to make a forward reference to a more local definition
that may occur later.
To resolve this ambiguity, FAIL always considers a symbol reference
to be a forward reference when the symbol has not been defined in the
current block, even if it has been defined in some outer block. If
no other definition is given by the time the block ends, then the
outer-block definition is used to resolve the forward reference.
While in the inner block in this situation, the outer-block symbol is
still said to be defined, but it is also said to be unavailable.
Thus block structure forces many references to be forward references,
even when they would not otherwise be such.
Macros and user-defined opcodes cannot be forward-referenced. Such
symbols are always available; references to them will use their
outer-block definitions.
22 Basic Syntax FAIL
Examples:
FOO: MOVSI 1,-62 ;FOO is defined as a label
BAR: CAME 2,ZOT(1) ;so is BAR
AOBJN 1,BAR ;BAR is referenced
BEGIN ;FOO and BAR are defined, but now unavailable
LOSS: MOVEI 1,0 ;LOSS is defined
JRST LOSS ;a backward reference to LOSS
JRST FOO ;this is treated as a forward reference
FOO: HRRM 6,LOSS ;so it can reference this definition
BAZ: JRST BAR ;this is treated as a forward reference
JRST FOO ;this refers to this block's FOO
BEND ;The outer-block definition of BAR becomes
;available at this BEND. A fixup is emitted
;to fix the reference to BAR at BAZ
Many contexts do not accept forward references (e.g., accumulator and
index fields). In these contexts unavailable symbols cannot be used,
even if they are defined. Therefore, FAIL provides two mechanisms
for forcing defined symbols to be available to lower blocks. One is
the down-arrow mechanism, which is used at the defining occurrence of
the symbol, and the other is the GLOBAL pseudo-op (see section
3.2.3, page 34), which is used in the referencing block.
The down-arrow mechanism is the more commonly used method, since this
problem is most often associated with particular symbols (accumulator
names, assembly parameters, etc.). Preceding the symbol name in a
label or assignment statement with a down-arrow (↓) causes that
symbol to remain available whenever inner blocks are entered.
Usually it is dangerous to redefine such symbols locally, since any
forward references will have incorrectly referred to the outer-block
definition. Consequently a warning message is printed in this case,
but if no forward references are made to the local version, it will
assemble correctly. However, if the redefinition of a down-arrowed
parameter is effective at its original block level (possibly via ↑ or
↑↑), FAIL will change the original definition without complaint.
This allows redefinition of global parameters from inner blocks. A
question mark (?) may be used instead of down-arrow.
FAIL Basic Syntax 23
Examples:
↓A←1 ;some accumulator (AC) definitions
B←2
↓FOO←←=69 ;and a parameter
BEGIN
ADD B,A ;this is illegal because AC
;symbols must be available
MOVE A,B ;but this is legal since A is available
;by ↓
A←5 ;this will produce a message and is too
;late to affect the instruction above
B←6 ;this is legal and will fix up the MOVE
;to be MOVE 1,6
MOVE A,B ;whereas this will be MOVE 5,6
↑FOO←←105 ;this is legal since it is "aimed" at the
;FOO in the outer block
BEND
There are further details in section 3.2.2, page 33, and section
3.2.3, page 34, about the block structure pseudo-ops BEGIN, BEND,
and GLOBAL.
2.3.4.7 Linkage with Separately Assembled Programs
It is sometimes desirable to have a program which is assembled in
several parts, either to save reassembling the entire program for
each change or because the program is written in a mixture of
languages. Even with a single assembly it is usually necessary to
use some of the job data area symbols, and sometimes symbols from the
debuggers (RAID or DDT), all of which are reached through the linking
loader. In this context, the word program refers to the result of
one assembly or compilation, and thus a core image may contain
several programs.
To allow reasonable communication between these programs, the loader
allows symbol definitions to be passed between programs. For this
purpose, symbols are divided into two classes, local symbols and
global symbols. (There is no relation between the GLOBAL pseudo-op
and the global symbols discussed here.)
Symbols are normally considered local, which means that they will not
be available outside their own program and may be defined in more
than one program without conflict. Global symbols, however, are
available to all programs and hence must not have conflicting
24 Basic Syntax FAIL
definitions within the set of programs to be loaded. The easiest way
to declare a symbol to be global is to follow some occurrence of the
symbol by an up-arrow. This flags the symbol as a global without
specifying whether it is defined in this program or another program,
since FAIL will have figured that out by the end of the assembly.
Undefined globals (external symbols) will have appropriate fixup
information passed to the loader for resolution when the defining
programs are loaded. Globals may also be declared with the EXTERNAL
(section 3.2.5, page 34) and INTERNAL (section 3.2.4, page 34)
pseudo-ops.
Declaring a symbol global forces its scope to the outermost block in
the same way as does a double up-arrow. Therefore, if a symbol is
defined and declared global in an inner block, there must not be a
conflicting definition in an outer block.
One other related feature is the library mechanism. A library is a
file that contains a set of utility programs. Each program in the
library may be loaded independent of the others, depending on whether
it is required by the programs that have been loaded thus far. To
implement this, there is associated with each program in the library
(in one or more entry blocks) a list of certain global entry points
defined in that program. In most cases these are the names of the
routines contained in the program. When the loader is in library
search mode, it loads only those programs for which at least one of
the entry points corresponds to an existing unsatisfied global
request (external symbol). Only those programs actually needed are
loaded from the library; the rest are ignored. The ENTRY pseudo-op
(section 3.2.4, page 34) is used to declare symbols to be entry
points which will be available to a library search.
2.3.4.8 Symbols and Arrows
This is a brief restatement of the ways that identifiers are used as
symbols in conjunction with arrows.
Examples:
↑SYM: ;SYM is available at the next-outer block
↑↑BOL←←10 ;BOL is half killed and available at the
;outermost block
↑↑ZOT= =69 ;ZOT is available at the outermost block
↓A↑←7 ;A is global and available to lower blocks
FOO↑: ;FOO is global and defined here (internal),
;available at the outermost block
PUSHJ P,BAZ↑ ;BAZ is global, may be external, available at the
;outermost block
FAIL Basic Syntax 25
2.3.5 Complex Atoms
Two constructs exist which assemble one or more statements in much
the same way as FAIL's normal top-level statement processor, but then
return as an atom the value associated with the statement(s)
assembled, rather than outputting the binary data. Both of these
constructs involve the use of opening and closing characters to
delimit the text. For an atomic statement, broken brackets, called
brokets (< and >), are the delimiters. For literals, the delimiters
are square brackets ([ and ]).
When the opening character is recognized, FAIL saves its present
state and enters an auxiliary statement-assembly loop, continuing to
assemble statements until a statement is encountered which terminates
with the closing character. The closing character is located as a
statement delimiter, not by keeping a count of the opening and
closing characters. Thus if the delimiter character appears in a
text constant, it will not be counted toward the match; also,
attempting to use a comment (see section 2.1.6, page 7) in the final
statement of the sequence will prevent recognition of the closing
delimiter. Note that this method of counting brokets is different
from the macro processor, which counts brokets rigidly, independent
of context. Nesting of complex atoms is handled by the recursive
nature of FAIL's statement processor.
2.3.5.1 Atomic Statements
When it is useful to have the value of an entire statement treated as
an atom, enclose that statement in brokets. Some number of
statements will be assembled as described above, and the value of the
first word assembled will be returned as the value of the atom, just
as if the corresponding number had been typed. The values of any
additional words assembled up to the closing broket will be ignored,
although their side effects (if certain pseudo-ops are used) may
remain. For example, if one of the multiple-word text pseudo-ops is
used inside brokets, only the first text word will be returned, and
the rest will be dispatched to the great bit bucket in the sky. This
type of atom is constrained by FAIL to be handled as a number, so all
symbols used in this context must be defined and available.
26 Basic Syntax FAIL
Examples:
<JRST> ;equivalent to 254000000000
<JRST 105 ;254000000105 will be the value
JRST BAR ;and this statement won't do anything except
;possibly produce an error message if BAR
;isn't defined and available >
> ;this broket will end it, not the one above
2.3.5.2 Literals
Although the PDP-10 instruction set allows a large percentage of
constants to be specified as immediate operands, it is still
frequently necessary to reference constants stored elsewhere in
memory. Instead of explicitly setting up these constants and
referencing them by labels, it is possible to reference these
constants as literals. The basic function of literals is to allow
the programmer to write the value of the desired constant directly
(i.e., literally), while the assembler automatically allocates a
memory location for it, stores the value in it, and supplies the
address of the cell for the reference. Also, an operation called
constants optimization occurs, which consists of comparing (the
binary value of) each literal with previous literals to see if the
required constant has already been allocated, in which case the
existing cell will be used rather than allocating another. This
avoids multiple copies of a given constant.
To use a literal, put a statement of the desired value in square
brackets and use it as an atom. The value (of the literal) will be
the address of the literal in memory, which is treated like an
undefined symbol since the actual location will not be assigned until
later (usually the end of the program; also, see section 3.1.6,
page 32). Literals can be used only where forward references are
legal.
Because of the constants optimization, it is often dangerous (and
considered poor form) to write a program which changes the contents
of a literal. Such a change affects all parts of the program
attempting to use that constant, which is not usually the desired
effect.
A literal may contain more than one word if desired. The syntax of
literals is basically the same as that of atomic statements, except
that all words assembled are used. Multiple-word literals are most
commonly used to store long text strings, but may be used to store
FAIL Basic Syntax 27
sequences of instructions. There is no rigid limit on the maximum
size of a literal, but large literals do consume assembler core
fairly rapidly.
For purposes of assembling code in literals, it should be noted that
the predefined symbol "." retains its value during the assembly of a
literal, rather than referring to the current location within the
literal. Thus it refers to the location where the reference to the
outermost literal is being made. The current location within the
(current) literal can be referred to by using the symbol "$." (but
this may not do the right thing if the PHASE pseudo-op is in use).
Naturally, labels may appear inside literals, but if they do they
will be assigned the value of the current location within the
literal, rather than the value outside. (Labels that appear inside
literals are called literal-labels.) This is the only time that FOO:
and FOO←. assign different values to FOO. The location of a literal
is unknown at the time it is processed; hence, labels that are
defined within literals (and "$." when used inside literals) are
undefined symbols. For example, it is illegal to say FOO←$. inside a
literal because assignment statements do not accept undefined values.
Note also that constants optimization will still occur with labeled
literals, and this may result in several labels having the same
value, if appropriate.
Examples:
PUSH P,[5] ;no PUSHI, so a literal is handy
OUTSTR [ASCIZ /FOOBAR/] ;a two-word text constant
JRST [ MOVEI C,12 ;some code in a literal
PUSHJ P,WRCH
SUB P,[1,,1] ;a nested literal
JRST .+1] ;returns to the next instruction
;outside the literal
PUSHJ P,[YTST: CAIE C,"Y" ;a subroutine in a literal
CAIN C,"y" ;(very rarely done actually)
AOS (P)
POPJ P,]
PUSHJ P,YTST ;calling the above subroutine
28 Pseudo-Ops FAIL
3. Pseudo-Ops
Most statements are translated into operations for the computer to
perform when the program is executed. Pseudo-ops (short for pseudo-
operations), on the other hand, signify operations to be performed at
assembly time. Some of these operations affect the behavior of the
assembler in particular ways; others serve as convenient methods of
entering data in commonly used formats.
3.1 Destination of Assembled Code
The assembler uses a location counter to keep track of the location
where the code it is assembling will go. This counter is initialized
to relocatable 0 at the start of the assembly; it is incremented by 1
for each instruction assembled. The value in the location counter is
the location where the next word assembled will go.
3.1.1 LOC, RELOC, and ORG
The contents of the location counter can be changed with the LOC,
RELOC, and ORG statements.
The LOC pseudo-op takes one argument, an expression, which must be
defined and available. The effect of LOC is to put the value of the
expression into the location counter and to set the relocation of the
counter to absolute, regardless of the relocation of the argument.
The RELOC statement has the same effect as the LOC statement except
that the relocation is set to relocatable, regardless of the
relocation of the argument.
The ORG statement has the same effect as the LOC and RELOC statements
except that the relocation is set to the relocation of the argument.
For compatibility with MACRO-10, the pseudo op .ORG is also accepted.
Whenever LOC, RELOC or ORG is used, the current value (and
relocation) of the location counter is saved (there is only one such
saved location counter, not one for each pseudo-op). A LOC, RELOC,
or ORG statement with no argument will cause the saved value and
relocation to be swapped with the current value (and relocation) of
the location counter.
FAIL Pseudo-Ops 29
3.1.2 SET and USE
It is possible to have multiple location counters and to switch back
and forth among them. Only the currently active location counter is
incremented. Location counters may be given any names which fit the
syntax of identifiers. There is no relationship between location
counters and labels with the same name.
The SET pseudo-op is used to initialize a location counter. It takes
two arguments separated by a comma. The first is the name of the
location counter; the second is the value to which the counter will
be set. SET has the same effect as ORG except that it changes the
indicated location counter and has no effect on the current location
counter unless it is the same as the indicated one. SET is usually
used to create a new location counter.
The USE pseudo-op is used to change location counters. It takes one
argument, the name of the location counter to change to. USE causes
the current location counter value to be saved away and the value of
the indicated counter to be used. If a subsequent USE indicates the
location counter which was saved away, the value it had when it was
saved away will become the current value. If the indicated location
counter has not appeared in a SET before its appearance in a USE
(i.e., if it has no value), it will be given the value of the current
location counter. The location counter which the assembler starts
with has a blank name (i.e., a null argument indicates this first
one).
In the example below, a close single quote (apostrophe) (') is used
to denote that the value it follows is relocatable. This is the
convention that FAIL uses when making a listing of the assembled
code.
Example:
Location Instructions
0' JRST FOO
1' JRST BAZ
2' SET GARP,37
2' USE GARP
37 JRST FOO
40 USE
2' JRST FOO
30 Pseudo-Ops FAIL
3.1.3 PHASE and DEPHASE
It is sometimes desired to assemble code in one place which will
later be moved by the program itself to another place. In this case,
it is desired that labels be defined as referring to locations in the
place where the code will be moved, rather than where the assembler
will put it. To accomplish this, the PHASE pseudo-op is used. PHASE
has one argument, the location to which the next word assembled will
be moved by the program. For instance, if, while the location
counter is at 74, a PHASE 32 appears and a label appears on the next
line, the label will be given the value 32, but the code on that line
will be placed in location 74. Under these circumstances, the "."
symbol will have the value 32, but the "$." symbol will have the
value 74. The PHASE pseudo-op remains in effect until cancelled by a
DEPHASE pseudo-op (no argument).
If a RELOC, LOC, or ORG pseudo-op (see section 3.1.1, page 28)
appears while PHASE is in effect, the following considerations apply.
If the relocation of the location counter remains unchanged by the
RELOC (or LOC or ORG), then the value of the phase will be offset by
the same amount as the location counter changes. That is, the value
of "." and "$." will be changed by the same amount. If the
relocation of the location counter changes and the relocation of the
phase was the same as the relocation of the (old) location counter,
then the relocation of the phase will be changed and the phase will
be offset by the same amount as the location counter changes.
Otherwise, the error message Indeterminate Phase due to RELOC will
occur and FAIL will dephase.
3.1.4 HISEG
This statement outputs information directing the loader to load the
program into the high segment. It should appear before any code is
assembled.
3.1.5 TWOSEG
This statement directs FAIL and the loader to assemble and load a
two-segment program. This complicates the relocation process because
the loader must maintain two relocation constants, one for each
segment. Since only one bit of relocation information is available
for each value in the relocatable binary file, a kludge is used to
decide which relocation to apply to each relocatable value. To do
this, the loader compares the unrelocated value to a quantity known
FAIL Pseudo-Ops 31
as the high-segment origin, which is the first address used for the
high segment within that program. Any value greater than or equal to
this quantity will be considered a high-segment address, while any
value less than this quantity will be considered a low-segment
address. When the value in question is a location specifier, the
choice of relocation will determine which segment the code is
actually loaded into.
Unfortunately, there is a possible bug in this relocation method. It
is possible to have an expression which evaluates, through normal
relocation arithmetic, to a relocatable quantity whose unrelocated
value does not correspond to the segment the relocation was
originally derived from. For example, if FOO is a label at high
segment location 120, it will probably have a value of relocatable
400120. The expression FOO-400000 would be calculated by FAIL to
have the value relocatable 120. This value would be passed directly
to the loader since Polish appears unnecessary. However, the loader
would apply the low-segment relocation to this value and probably
have incorrect results. At present, the best way to get around this
is to say FOO*1-400000, which will force the Polish to be passed to
the loader.
The high-segment origin is specified by an optional argument to the
TWOSEG pseudo-op, or set to the default of 400000 in its absence. In
this case a RELOC 400000 followed by a RELOC 0 will initialize the
dual location counter to assemble into the low segment and to switch
segments whenever a RELOC statement with no argument is encountered
(see section 3.1.1, page 28). Like HISEG, TWOSEG should be used
before any code is assembled.
32 Pseudo-Ops FAIL
Example:
TITLE EXAMPLE
PDLEN←←100
P←17
TWOSEG 400000 ;initialize to two segments
RELOC 0 ;initialize dual location counters
RELOC 400000 ;now assemble code in the high segment
START: TDZA 1,1
MOVNI 1,1
MOVEM 1,RPGSW#
CALLI 0
MOVE P,[IOWD PDLEN,PDLIST]
RELOC ;set the relocation to low segment
PDLIST: BLOCK PDLEN ;define space for data storage
RELOC ;set location counter to the high segment
PUSHJ P,CORINI ;code is assembled in the high segment
;the rest of the program goes here
RELOC ;back to the low segment
VAR ;do variables in the low segment
RELOC ;to the high segment
LIT ;and literals here
END START
3.1.6 LIT
The LIT statement causes all previously defined literals to be placed
where the LIT statement occurs. The LIT statement must not appear
inside a literal. If a two segment sharable program is being
assembled, LIT should appear in the upper segment.
3.1.7 VAR
The VAR statement causes all variables which appeared with a # in
this block (or a sub-block of this one) to be placed where the VAR
appears. VAR must not appear inside a literal. If a two segment
sharable program is being assembled, VAR should appear in the lower
segment.
FAIL Pseudo-Ops 33
3.2 Symbol Modifiers
The pseudo-ops in this section perform several functions, all
relating to the definition or availability of symbols, or affecting
the linkage of this program to others.
3.2.1 OPDEF and .GOPDEF
The OPDEF statement has the following form:
OPDEF symbol [value]
OPDEF inserts the symbol into FAIL's opcode table with the indicated
value. The symbol, which is a user-defined opcode, may then be used
as any other opcode. The value part of the OPDEF must be defined and
available. User-defined opcodes are sometimes called opdefs because
of the pseudo-op by which they are defined.
Symbols defined by OPDEF follow block structure. If, in an inner
block it is necessary to define opcodes that will be available
outside that block, the .GOPDEF pseudo op may be used. .GOPDEF will
define an opcode at the outermost block level.
3.2.2 BEGIN and BEND
The BEGIN statement is used to start a block. The block it starts
will end at the corresponding BEND statement. The BEGIN may be
followed by an identifier that will be used as the name of that
block. DDT and RAID recognize block names. If no identifier
appears, the assembler will create one of the form A.000, where the
000 will be replaced by the block number of this block in octal.
(The block number is initialized to zero and incremented for each
BEGIN.) There is no relationship between labels and blocks with the
same name. All text following the identifier is ignored until the
next line feed or double-arrow.
BEND may be followed by an identifier which, if present, is compared
to the block name of the block being ended; if they don't match,
FAIL prints an error message.
FAIL does not require block names to be unique; however, the loader
and the debuggers sometimes depend on unique block names, so the user
would be wise to avoid conflicts.
For a discussion of block structure, see section 2.3.4.6, page 20.
34 Pseudo-Ops FAIL
3.2.3 GLOBAL
The GLOBAL pseudo-op should be followed by a list of symbols
separated by commas. Each symbol should be defined in an outer
block. The effect of GLOBAL is to find the nearest outer block in
which that symbol is defined and to make the definition in that block
immediately available in the block in which the GLOBAL appears.
GLOBAL does not affect the definition of the symbol in any
intervening blocks.
If a symbol has been declared GLOBAL in a block and later is
redefined in that block, the redefinition affects the definition in
the outer block where GLOBAL found the original definition. Doing
this causes strange effects if the definition was not in the next-
outer block; it should not be done without some careful thought.
The GLOBAL pseudo-op has no relation to the concept of global
symbols.
3.2.4 INTERNAL and ENTRY
These statements declare certain locally defined symbols to be
internal symbols. Internal symbols are those which are made
available to other programs by the loader. INTERNAL (or ENTRY)
should be followed by a list of symbols separated by commas. These
symbols need not be defined before the INTERNAL (or ENTRY) statement
appears, but they must be defined by the end of the program.
ENTRY emits special library entry blocks to the loader; see section
2.3.4.7, page 24. ENTRY statements must appear before any other
statements that emit code, except that it is specifically legal to
precede ENTRY statements by a TITLE statement.
3.2.5 EXTERNAL
The EXTERNAL statement declares that certain symbols are external
symbols. An external symbol is a symbol that is declared internal in
some other program. EXTERNAL is followed by a list of symbols
separated by commas. The loader will fix up any references to an
external symbol when the program in which it is defined is loaded.
Symbols must not be defined at the time they are declared with an
EXTERNAL statement. If an external symbol is subsequently defined, it
is automatically converted to an internal symbol.
FAIL Pseudo-Ops 35
If any occurrence of a symbol is immediately followed by an up-arrow
(↑), that symbol is made external if it is not yet defined, or
internal if it is defined. If an external symbol is subsequently
defined, it will be made internal.
3.2.6 LINK and LINKEND
LINK and LINKEND are used to establish a single-linked list among
several separately assembled programs. Each linked list is
identified by a link number in the range 1-20 (octal). The formats
are
LINK number,location
LINKEND number,location
The number is the link number; the location is the address where the
link information will be stored. The effect is to allow 20 lists to
be threaded through several separately assembled programs.
The loader initializes each link (and linkend) to zero. LINK N,FOO
causes the loader to store in FOO the current value of link N. Then
link N is set to (point at) FOO. LINKEND N,BAZ causes the the loader
to store the address BAZ as the linkend for link N. When the loader
finishes loading all programs, the final value of each link will be
stored in the corresponding linkend address, only if that address is
non-zero. The LINKEND feature allows the head of the list to be in a
known place, rather than in the last place LINKed.
For compatibility with MACRO-10, the pseudo ops .LINK and .LNKEND are
accepted for LINK and LINKEND, respectively.
3.2.7 .LOAD and .LIBRARY
The .LOAD pseudo-op causes the loader to load a specific REL file as
a consequence of loading the program in which this pseudo-op occurs.
The format is
.LOAD DEV:FILE[PRJ,PRG]
The DEV: field is optional (the default is DSK:); it specifies the
device where the REL file can be found. The [PRJ,PRG] field is
optional; it has the usual meaning. The file named must have the
extension REL (this is a loader restriction).
36 Pseudo-Ops FAIL
The FAIL assembly has conditional assembly switches for a variety of
sites; file names are scanned in accordance with the file naming
conventions that prevail at each site.
The .LIBRARY pseudo-op is similar to .LOAD, except that instead of
loading the file, the loader will search the named file as a library.
For compatibility with MACRO-10, the pseudo ops .REQUIRE and .REQUEST
are accepted for .LOAD and .LIBRARY, respectively.
3.2.8 PURGE
The PURGE pseudo-op takes a list of symbols, separated by commas, as
its argument. Each of the symbols named will be purged, i.e.,
removed from FAIL's symbol table. A purged symbol can be an opcode,
macro, label or other symbol. For PURGE to be legal, the symbol must
be defined and available when the PURGE occurs. Some symbols, such
as variable names literal-labels, and global symbols, cannot be
purged. Purged symbols are not passed to the loader or debugger.
PURGE searches the symbol table for opcodes first, then macro names,
and finally labels (and parameters). This means that if a symbol has
a definition as both an opcode and a label, purging that symbol will
delete the opcode, and a second purge of that symbol will delete the
label definition.
If the identifier name of some purged symbol is used after the purge,
FAIL makes a new and totally different symbol, which has no relation
to the purged symbol. The CREF program will also consider such a
symbol to be different from the purged symbol.
Caution: if an opcode, pseudo-op, or other predefined symbol is
purged, it will remain unavailable to subsequent assemblies performed
by the FAIL core-image from which it was purged. Also, it is unwise
to purge a macro while it is being expanded.
3.2.9 XPUNGE
XPUNGE is used to delete all local symbols from one block. XPUNGE
takes effect only at the next BEND (or END or PRGEND) statement
following the XPUNGE. At that BEND, most local symbols will not be
emitted to the loader. This decreases the size of the REL file and
makes loading it faster. Block names, internal and external symbols,
variables, and literal-labels will be passed to the loader.
FAIL Pseudo-Ops 37
3.2.10 SUPPRESS and ASUPPRESS
When a parameter file (i.e., a file that contains assembly parameters
for use in several assemblies) is used in assemblies, many symbols
get defined but are never used. Unused defined symbols take up space
in the binary file. Unused symbols may be removed from symbol tables
by means of the SUPPRESS or ASUPPRESS pseudo-ops. These pseudo-ops
control a suppress bit associated with each symbol; if the suppress
bit is on and the symbol is not referenced, the symbol will not be
output to the binary file.
SUPPRESS takes a list of symbols, separated by commas, as its
argument. The suppress bit is turned on for each symbol named. A
symbol may be an opdef, a parameter, or a label. The symbol should
be defined before the SUPPRESS statement occurs.
ASUPPRESS turns on the suppress bit for every user-defined symbol and
opcode that exists in the symbol table at the time the ASUPPRESS
occurs.
Variables, literal-labels, internals, and entry point symbols are
never suppressed. Externals that are not referenced can be
suppressed.
If ASUPPRESS appears in a universal program (see section 3.2.11,
page 37), then all symbols in the universal symbol table will have
the suppress bit set when they are used in a subsequent SEARCH.
3.2.11 UNIVERSAL
The UNIVERSAL pseudo-op has the same syntax as TITLE (see section
3.5.1, page 43). In addition to the functions of TITLE, UNIVERSAL
declares the symbols defined in this program to be universal symbols.
Universal symbols are symbols which can be accessed by other programs
that are assembled after the universal symbols have been defined.
That is, UNIVERSAL causes symbols to be retained by FAIL after it
finishes assembling the universal program.
The program name that is set by UNIVERSAL names the universal symbol
table. The universal symbol table contains the universal symbols
defined by this program. Only outer block symbols (and macros and
opdefs) are retained in the universal symbol table. Variables,
literal-labels, and internal symbols are not retained.
Universal symbols are written into a binary universal file which can
be accessed in subsequent assemblies without reassembling the source
38 Pseudo-Ops FAIL
text of the universal program. The binary universal file is given
the same name as the name in the universal statement. This file has
the extension "FUN" and it is written in the current directory.
Output of the binary universal file is automatic, but may be
prevented by use of .NOUNV in .DIRECT (see section 3.5.7, page 45),
or by the /O switch in the command line (see appendix A, page 61).
Access to the symbols in a universal symbol table is controlled by
the SEARCH pseudo op (see section 3.2.12, page 38). Once access is
established, universal symbols can be referenced as any other local
symbols.
Universal programs are intended for making definitions, not for
assembling code. The usual use for UNIVERSAL is to define opcodes,
macros, and parameters for use in subsequent assemblies. It is not
wise to include relocatable symbols in a universal program. The
exception is that a universal program may declare a symbol to be
external; that declaration can be used by subsequent assemblies that
search this universal symbol table.
3.2.12 SEARCH
Access to universal symbols is established by SEARCH. SEARCH takes a
list of arguments, each of which is the name of a universal symbol
table. For each universal table named, all the symbols in that table
are added to the end of the main symbol (or macro or opcode) table.
Thus, when the symbol table is searched, if there is no other
definition of the symbol, the universal definition will be found.
Universal symbols are considered to be defined at the outer block.
If such symbols are to be made available to inner blocks, they must
be defined with a down-arrow, or declared GLOBAL.
If the universal symbol table named in SEARCH does not exist already,
FAIL looks for a binary universal file (sometimes called a FUN file,
because it has the extension "FUN"). The file sought has the same
name as the argument to SEARCH, the extension FUN, and is on the
current file directory, or on device UNV, or on device SYS.
Alternatively, the argument to SEARCH may be followed by a file name
enclosed in parentheses, in which case the named file will be sought
instead of the default.
FAIL Pseudo-Ops 39
3.3 Entering Data
3.3.1 DEC and OCT
The DEC and OCT statements both take a string of arguments, each a
number, separated by commas. The radix is temporarily set for this
one statement to 10 for DEC or to 8 for OCT. The numbers are placed
in successive locations.
Examples:
DEC 5,9,4096 ;assembles three words
OCT 5,11,10000 ;assembles the same three words
3.3.2 BYTE
The BYTE statement is used to enter bytes of data. Arguments in
parentheses indicate the byte size to be used until the next such
argument. The first argument of a BYTE statement must be a byte size
argument. Other arguments are the byte values. An argument may be
any expression that is defined, available, and absolute. Arguments
in parentheses (byte size) are interpreted in decimal (base 10) and
other arguments in the prevailing radix. Bytes are deposited with
the byte instructions, so if a byte will not fit in the current word,
it will be put in the left part of the next word. Unused parts of
words are filled with zeros. Byte size arguments are not surrounded
by commas, but other arguments are separated by commas. For
instance, the statement
BYTE (7) 3,5(11)6
will put two 7-bit bytes (3 and 5) and an 11-bit byte (6) in a word,
left justified.
Two successive delimiters, i.e., two commas or a comma and
parenthesis, indicate a null argument, which is the same as a zero.
3.3.3 POINT
The POINT pseudo-op assembles a byte pointer in one word. The first
argument should be an expression and is interpreted in decimal. The
expression must be defined and available. It indicates the byte
40 Pseudo-Ops FAIL
size, and its value is placed in the size field of the assembled
word. The second argument should contain one or more of an index
field, an address field, and an at-sign. The third field, if
present, indicates the bit position of the low order bit of the byte,
i.e., its value is subtracted from 35 (decimal) and placed in the
position field. It is interpreted in decimal and must be available.
If the third argument is omitted (no comma should be present after
the second argument), the position field is set to 36 (decimal) so
that the first time the pointer is incremented, it will point to the
first byte of the word.
3.3.4 XWD
The XWD statement takes two arguments, separated by a comma, and
assembles a single word with the value of the first argument in the
left half and the value of the second argument in the right half.
Both arguments must be present.
3.3.5 IOWD
IOWD is a permanently defined macro (see section 4, page 49).
Its definition is
DEFINE IOWD (A,B)
< XWD -(A),B-1 >
IOWD takes two arguments and assembles a word in which the negative
of the first argument goes in the left halfword and one less than the
value of the second argument goes in the right halfword. This format
(i.e., negative word count, and memory address minus 1) is often used
in communicating with the operating system to specify the address and
length of a data block. Also, IOWD may be used to initialize an
accumulator for use as a push down pointer.
3.3.6 ASCII, ASCIZ, ASCID, and SIXBIT
There are four text statements: ASCII, ASCIZ, ASCID, and SIXBIT.
Each takes as its argument a string of characters starting and ending
with, and not otherwise containing, some non-blank character which
serves as a delimiter. This delimiter should not be any one of the
characters: left-arrow (←), colon (:), up-arrow (↑), tilde (~), or
number sign (#).
FAIL Pseudo-Ops 41
ASCII puts the 7-bit representation of each successive character in
the string (excluding the delimiters) in successive words, 5
characters per word, until the string is exhausted. The low order
bit of each word and the left-over part of the last word are filled
with zero.
ASCIZ is the same as ASCII except that if the last character is the
5th of a word, a word of zero is added at the end. This is to ensure
that there is at least one 0 byte at the end.
ASCID works as ASCII except that the low order bit of each word
generated is a 1. ASCID assembles data suitable for either the III
or Data Disc display systems at the Stanford A.I. Lab. Also, the
ASCID format is used for line numbers in the SOS and EDIT editors.
SIXBIT works as ASCII except that the characters are converted to the
sixbit representation and packed 6 to a word. The last word is
filled out with zeros if necessary. Ascii characters are converted
to sixbit by replacing the 40 bit with the 100 bit and removing the
100 bit.
3.3.7 RADIX50
This pseudo-op takes two arguments, separated by a comma. The first
argument is a number; the second argument is an identifier. The
value assembled by the RADIX50 statement is the radix50
representation of the identifier, with the number ORed into the high-
order 6 bits. The 2 low-order bits of the number are cleared before
ORing.
Radix50 is the representation used for symbol names in the loader,
DDT, and RAID. Radix50 is used to condense 6-character symbols into
32 bits. Legal characters are reduced to a value in the range 0-47
octal. The radix50 value is obtained by accumulating a total
composed of each character value times a weight. The weight is the
power of 50 (octal) corresponding to the character position. The
weight of the rightmost non-blank character is 1; the second from
the right has weight 50; the third has weight 50*50; etc. The
correspondence between characters and their radix50 value is given
below:
Blank → 0
0-9 → 1-12
A-Z → 13-44
. → 45
$ → 46
% → 47
42 Pseudo-Ops FAIL
3.4 Reserving Space for Data
3.4.1 BLOCK
The BLOCK statement is used to reserve a storage area for data. The
value of the argument is added to the location counter, so subsequent
statements will be assembled beyond the area reserved by BLOCK. The
argument must be defined and available. A warning will be given if
the argument is negative. The loader will initialize each word
reserved by the BLOCK statement to zero; however, well-written
programs do their own initialization. Note that the BLOCK pseudo-op
has no relation to block structure.
BLOCK N and ORG .+N are equivalent.
3.4.2 INTEGER and ARRAY
INTEGER should be followed by a list of symbols, separated by commas.
Each of these symbols is then treated as a variable, i.e., as though
it had appeared in the block where the INTEGER appears, followed by a
number sign.
The ARRAY statement takes a list of arguments separated by commas.
Each argument is a symbol followed by an expression in brackets. The
effect is similar to INTEGER, except that the expression (which ought
to be defined and available) denotes the number of locations to be
reserved (as in BLOCK), with the symbol being the address of the
first one. For example,
ARRAY FOO[10],BAZ[20]
will reserve 10 words for FOO and 20 words for BAZ. The symbols FOO
and BAZ are not defined by this statement; they can only be used
where forward references are legal.
FAIL Pseudo-Ops 43
3.5 Assembler Control Statements
3.5.1 TITLE
TITLE names the program and sets the heading for the pages of the
listing. There should be precisely one TITLE statement per program;
it should appear before any statement that generates code.
TITLE should be followed by a string of characters, the first part of
which should be an identifier. That identifier is used as the
program name which DDT and RAID will recognize. It is also used as
the name of the outermost block.
The string of characters in the TITLE statement is printed as a part
of the heading on all pages subsequent to the one on which the TITLE
statement appears; if TITLE appears on the first line of a page, it
also affects the heading on that page. The string used in the
heading for TITLE is terminated by the first carriage return or
semicolon.
If no TITLE statement appears before the first symbols are emitted
(generally, at the first BEND or END), then FAIL will generate a
title with program name ".MAIN". If a TITLE statement appears after
code has been emitted (except for entry blocks), the resulting binary
file may be unsuitable for use as part of a library file.
3.5.2 END and PRGEND
The END statement is the last statement of a program. It signals the
assembler to stop assembling; no text following it will be
processed. If an argument is given, it is taken as the starting
address of the program.
An END statement includes implicit VAR and LIT statements (see
section 3.1.7, page 32, and section 3.1.6, page 32). That is, all
outstanding variables and literals are placed starting at the current
value of the location counter when the END is seen. Variables are
put out first.
PRGEND is used in place of END when it is desired to assemble more
than one program to and/or from a single file. It behaves exactly
like END, including taking an optional argument as the starting
address, and then restarts FAIL completely, except that I/O is
undisturbed. It therefore cannot appear in a macro expansion or
44 Pseudo-Ops FAIL
similar situation. PRGEND is particularly useful for directly
assembling a library which consists of many small programs.
3.5.3 COMMENT
The first non-blank character following the COMMENT pseudo-op is
taken as the delimiter. All text from it to the line feed following
the next occurrence of this delimiter is ignored by the assembler,
except that it is passed to the listing file. The delimiter should
not be any one of the characters left-arrow (←), colon (:), up-arrow
(↑), tilde (~), or number sign (#).
3.5.4 RADIX
The RADIX statement changes the prevailing radix until the next RADIX
statement is encountered. It has no effect on numbers preceded by an
equal sign. The one argument of RADIX is interpreted in the current
radix unless it is preceded by a equal sign. Thus, the statement
RADIX 10 will have no effect (since 10 in the current radix equals
the current radix). The radix may be set to almost anything, but for
radices above 10 (decimal) there are no digits to represent 10, 11,
etc. Zero is not permitted, and 1 should be avoided if one is going
to use either an arithmetic FOR macro or a macro argument with this
radix.
3.5.5 .INSERT
The .INSERT pseudo-op causes FAIL to remember its position in the
current input file and then start reading (and assembling) another
file. When the end of the inserted file is reached, FAIL continues
processing the original file from the point where it left off. The
format is:
.INSERT DEV:FILE.EXT[PRJ,PRG]
The DEV: field is optional (the default is DSK:); it specifies the
device where the inserted file can be found. The [PRJ,PRG] field is
optional; it has the usual meaning. The file name is scanned in
accordance with the convention that prevails at each installation.
This pseudo-op will not work if it appears in the input stream from
any device other than DSK, since random access features are required
to accomplish the repositioning of the file.
FAIL Pseudo-Ops 45
Unlike a normal pseudo-op, which is recognized only if it appears as
the op-code, .INSERT is recognized anywhere in a line. It is
suggested that .INSERT not be used as a macro argument.
3.5.6 .FATAL
The .FATAL pseudo-op prints the text of the line on which it appears,
and stops the assembly. Usually, .FATAL appears under some
conditional assembly switch to stop the assembly because some
parameter settings are inconsistient.
3.5.7 .DIRECT
The .DIRECT pseudo op takes a list of function names separated by
commas as its argument. The available functions and their uses are
listed below.
The functions KA10 and KI10 are used when the program being assembled
is known to be suitable for only one of these processors. The
default situation allows the code to be executed on either processor.
LINK-10 checks this information to prevent code from being executed
on the wrong kind of processor.
.NOBIN suppresses binary output.
.NOUNV suppresses output of the binary universal (FUN) file (see
section 3.2.11, page 37).
The functions .XTABM and .ITABM modify the behavior of the macro
processor with respect to the treatment of tabs and blanks that
appear in actual arguments to a macro call (see section 4.1.5, page
52). .ITABM is the default; tabs and blanks are kept as part of the
argument. If .XTABM is used, leading and trailing blanks and tabs
are deleted from a macro argument, unless the argument is enclosed in
brokets or braces.
46 Pseudo-Ops FAIL
3.6 Loader Control Statements
The following pseudo-ops are used to pass control information to
LINK-10.
3.6.1 .COMMON
The .COMMON statement passes information to LINK-10, and does not
otherwise affect the assembly. This statement has the same syntax as
ARRAY (see section 3.4.2, page 42). LINK-10 will reserve the
requested amount of space for each block of named common.
3.6.2 .ASSIGN
The .ASSIGN pseudo op (and ASSIGN in the Tenex version) takes three
arguments: two identifiers, and an optional expression. At load
time, the value of the first identifier, which is treated as an
external by the assembler, is assigned to the second identifier.
Then the value of the expression (which is taken as 1 if the
expression is omitted) is added to the value of the first identifier.
3.6.3 .TEXT
The .TEXT statement is used to pass the ascii text of control
statements to LINK-10. The .TEXT pseudo op is like ASCIZ (see
section 3.3.6, page 40) except it does not have a value and does not
affect the location counter.
FAIL Pseudo-Ops 47
3.7 Listing Control Statements
These pseudo-ops affect the format of the assembly listing. Several
descriptions below refer to command line switches; appendix A, page
61, describes the command line format and the different switches.
3.7.1 TITLE and SUBTTL
The TITLE statement can be used to set the heading that appears on
the pages of the listing. See section 3.5.1, page 43.
SUBTTL is followed by a string of characters which is used as a
subheading on all subsequent pages until another SUBTTL appears. If
SUBTTL appears on the first line of a page, it will affect the
subheading of that page also. The string used in the heading for
SUBTTL is terminated by the first carriage return or semicolon.
3.7.2 LIST, XLIST, and XLIST1
The XLIST statement causes listing to stop until the next LIST
statement. LIST causes listing to resume if it has been stopped by
an XLIST or XLIST1 statement. Otherwise it is ignored. LIST is the
default.
The XLIST1 statement has exactly the same effect as XLIST unless the
/I switch was used in the command string, in which case it is
ignored.
3.7.3 LALL and XALL
XALL causes the listing of the body of macros, REPEATs, and FORs to
be suppressed during macro expansion. LALL causes it to start up
again. LALL is the default.
3.7.4 NOLIT
This statement causes the binary listing of code in literals to be
suppressed. This has the same effect as /L in the command string.
48 Pseudo-Ops FAIL
3.7.5 NOSYM
This statement disables the listing of the symbol table,
counteracting /S in the command string.
3.7.6 CREF and XCREF
These turn on and off the emission of information to CREF, the Cross-
Reference Listing program. These pseudo-ops have no effect unless /C
was used in the command string. CREF is the default.
3.7.7 PAGE
This pseudo-op has the same function as a form feed; it is included
for compatibility with MACRO-10. A form feed is placed in the
listing immediately following PAGE. The effect is to skip to the top
of the next page of the listing. Use of this pseudo-op will destroy
the correspondence between listing pages and source file pages, so
its use is generally not recommended.
3.7.8 PRINTX
This pseudo-op causes the line on which it appears to be printed on
the user's terminal. This is sometimes useful for giving a progress
report during long assemblies.
3.7.9 PRINTS
The first non-blank character following the PRINTS pseudo-op is taken
as the delimiter. All text from it to the next occurrence of this
delimiter is printed on the user's terminal. The delimiter should
not be any one of the characters left-arrow (←), colon (:), up-arrow
(↑), tilde (~), or number sign (#).
FAIL Macro Operations 49
4. Macro Operations
The FAIL macro processor provides features for modifying the input
text stream in many ways, such as the ability to abbreviate a
frequently occurring sequence with a single identifier or to iterate
the input of a stream of text a number of times. In both cases,
substitutions can be specified which allow each different occurrence
of the text to be somewhat modified. Provision for making the
assembly of a body of text conditional on any of a variety of
circumstances is also included.
4.1 Macros
Macros are named text strings which may have substitutable arguments.
Macros may be used whenever the same or similar pieces of text (code)
occur in several places. A macro has a name and a macro body; also,
it may have a concatenation character and an argument list. The
several characteristics of a macro are specified by a DEFINE
statement.
DEFINE and the macro name must appear on the same line. The macro
name is an identifier; it may be followed by an optional
concatenation character, which must also be on the same line as
DEFINE. The formal arguments, if any, are enclosed in parentheses
and separated by commas. The argument list may occur on a subsequent
line. The macro body, enclosed in braces ({ and }), appears after
the argument list in DEFINE.
In the macro processor, braces and brokets are equivalent, i.e., "{"
and "<" are equivalent, as are "}" and ">". The equivalence between
brokets and braces applies at all times within the macro processor;
the text and examples that follow use braces, but brokets can be used
instead. The macro processor counts braces independent of context;
specifically, braces and brokets that appear in comments, text
constants, etc. are counted by the macro processor. In the
discussion that follows, "non-blank character" omits both blank and
tab characters.
GDEFINE is similar to DEFINE except that the macro is defined at the
outermost block level. A macro defined by GDEFINE will remain
defined after exiting the block in which it was defined.
50 Macro Operations FAIL
4.1.1 Macro Bodies
The macro body may be any string of characters, subject to the
restriction that the right and left braces must be balanced. The
macro body itself is enclosed in braces and appears after the
argument list in a DEFINE statement. The macro body is stored in
FAIL's memory, associated with the macro name. At any point
following the DEFINE statement, the macro body will be substituted
for occurrences of the macro name.
4.1.2 Concatenation
The concatenation character may be any non-blank character (excluding
also carriage return, line feed, and right brace) that appears in
DEFINE after the macro name and before the argument list and macro
body. This character may then be used to delimit identifiers so that
they will be recognized as arguments. Appearances of this character
will be deleted from the macro body whenever they appear. This
allows a macro argument to be part of an identifier, instead of an
entire identifier. See the example at the end of section 4.1.6,
page 54.
4.1.3 Arguments in Macro Definitions
Arguments in macro definitions must be identifiers. A list of them,
enclosed in parentheses, may appear after the macro name in the
definition. If no list of arguments appears before the macro body,
it is assumed that there are no arguments.
Each instance of an identifier in the macro body which is the same as
one of the arguments will be replaced with the string of text
corresponding to that argument when the macro is called. Thus, if
FUDLY is one of the arguments in the definition of a macro and the
following text appears in the body:
A+FUDLY B
then FUDLY will be recognized as an argument. But if the following
appears:
A+FUDLYB
then, since FUDLYB is an identifier and is different from FUDLY, it
will not be recognized as an argument. To concatenate the "B" above
FAIL Macro Operations 51
with an actual argument, use a concatenation character. For example,
if the concatenation character is "$" and
A+FUDLY$B
appears in the macro body, then FUDLY will be recognized as an
argument, and the "$" will disappear when the macro is expanded.
Here is a sample macro definition:
DEFINE FOO (AC,ADDRS)
{MOVNI AC,3
IMUL AC,ADDRS
ADDI AC,37
MOVEM AC,ADDRS+1}
If the text:
FOO (A,FARB+7)
appears in the program somewhere after the DEFINE above, it will
expand into:
MOVNI A,3
IMUL A,FARB+7
ADDI A,37
MOVEM A,FARB+7+1
4.1.4 Macro Calls
A macro name may appear anywhere and will be replaced by the macro
body, as long as the name appears as an identifier and is considered
to be an identifier by the assembler. A macro name may appear alone
on a line or in the accumulator, index, or address field. If the
macro name appears in a context where it is not considered to be an
identifier, the macro will not be expanded. For example, macro names
that appear in a comment or in the text argument of an ASCII
statement will not be expanded. Also, there are some other cases
where a macro name will not be expanded:
the macro name in DEFINE and GDEFINE,
the formal argument list in DEFINE, GDEFINE and FOR,
the symbol name in OPDEF, PURGE, SUPPRESS and RADIX50,
the tested symbol in a symbol IF,
the block name in BEGIN and BEND,
the location counter name in USE and SET,
the program name in TITLE and UNIVERSAL, and
in any file name scan, e.g., .LOAD, .INSERT, etc.
52 Macro Operations FAIL
Macros may be used recursively. That is, a macro body may contain a
macro call or macro definition. However, if such macro calls are
nested too deep, the macro push-down list may overflow, resulting in
an error message and termination of the assembly. If this occurs,
the /P switch should be used in the command string. Every occurrence
of /P in the command string causes the assembler to allocate an extra
200 (octal) words of memory for the macro push-down list (see
appendix A, page 61). In similar circumstances, a main push-down
list overflow may occur. In this case, the /E switch in the command
string may be used to allocate a larger main push-down list.
4.1.5 Arguments in Macro Calls
The list of arguments to a macro call may be enclosed in parentheses,
or not. The arguments themselves are separated by commas. For
example, if FOO is the name of a macro that requires two arguments,
FOO A,FARB+7 and FOO (A,FARB+7) have the same effect.
If the argument list is enclosed in parentheses, then the first
argument begins with the first character after the "(", even if it is
blank. Subsequent arguments begin with the first character after the
comma that terminates the previous argument. Arguments do not
include the comma or ")" used to terminate them. Arguments are
scanned until the matching ")" is seen.
If the argument list is not enclosed in parentheses, the first
argument begins with the first non-blank character after the macro
name. Subsequent arguments begin with the first character after the
comma that terminated the previous argument. Arguments do not
include the comma or other character used to terminate them.
Arguments are scanned until any one of right bracket, right broket,
right brace, semicolon, or carriage return is seen.
Two commas in a row with nothing in between signify a null argument,
i.e., an argument that consists of no characters. If more arguments
are called for than are supplied, the last ones are considered to be
null. If more arguments are supplied than are called for, the extras
are ignored by the macro processor; see section 4.1.6, page 53.
Unless the first character of an argument is "{", the argument
terminates at the first comma, right parenthesis, right brace (or
broket), right bracket, or carriage return. If the first character
of an argument is "{" (or "<"), then all characters included between
the matching braces are taken as the argument. This allows the
argument to contain commas, parentheses, etc. which would not be
legal otherwise, but the braces must be kept balanced. In addition,
all characters between the "}" that closes the argument and the next
FAIL Macro Operations 53
argument terminator are ignored. This allows the continuation of a
list of arguments from one line to the next (i.e., enclose the last
argument on the line in braces and put the comma for it at the start
of the next line).
If the first character of an argument is a backslash (\) or right-
arrow (→), then the next thing after the backslash (or right-arrow)
is considered to be an expression (and it better be defined). The
expression is evaluated and the value is converted to a string of
ascii digits in the current radix (the radix ought not be 1). This
string of digits is taken as the argument. All characters from the
end of the expression to the next argument termination character
(comma, etc.) are ignored.
After a .DIRECT pseudo op has appeared with the .XTABM argument (see
section 3.5.7, page 45) then in a macro call where the macro argument
is not enclosed in braces, the leading and trailing blanks and tabs
adjacent to the argument in the call will be omitted from the actual
argument passed to the macro. The argument .ITABM to .DIRECT
restores FAIL to the normal treatment of tabs and spaces in
arguments.
4.1.6 How Much is Eaten by a Macro Call
When a macro call appears, some of the text following the macro name
is considered to be part of the call. Any text that is not part of
the macro call will be assembled as usual. For instance, if
DEFINE FOO (A) {A + 7/6}
has appeared, then when
MOVEI A,FOO (3) (6) ;comment
appears, it will be assembled as
MOVEI A,3 + 7/6 (6) ;comment
Thus, the text FOO (3) is considered to be part of the macro call and
is "eaten".
The following rules govern how much text gets eaten in a macro call.
If the macro was defined as having no arguments, then only the macro
name and any following spaces (or tabs) are eaten. If the macro was
defined as having arguments and the first non-blank character after
the macro name is a left parenthesis, then everything from the macro
name to the right parenthesis which closes the argument list,
54 Macro Operations FAIL
inclusive, is eaten. If the macro was defined as having arguments
and the first non-blank character is not a left parenthesis, then
everything from the macro name to the comma or carriage return which
terminates the last macro argument used is eaten. Thus, if
parentheses are not used and too few arguments are supplied,
everything from the macro name to the carriage return will be eaten.
If parentheses are not used and the macro was defined as having
arguments and enough or too many arguments are supplied, then
everything from the macro name to the comma (or carriage return)
which terminates the last argument used will be eaten.
Example:
DEFINE FOO $ (A,B) {A$B}
MOVEI FOO 1,2, ,37(6) ;will expand to:
;MOVEI 12 ,37(6)
;"FOO 1,2," has been eaten
4.1.7 Complex Example
This example is given without a full explanation. It shows an
example of an information carrying macro. The macro BAR is expanded
(by being redefined) every time that ADD1 is used. The \BAR in the
definition of ADD1 is necessary to cause the evaluation of BAR as an
expression (which causes a macro expansion to occur).
FAIL Macro Operations 55
Example:
DEFINE BAR {0,}
DEFINE FOO (A,B,C) {DEFINE BAR {0,<B
C>}}
DEFINE ADD1 (X) {FOO(\BAR,X)}
DEFINE SEC (A,B) {B}
;BAR = 0,
ADD1(X1)
;BAR = 0,<
; X1>
ADD1(X2)
;BAR = 0,<
; X1
; X2>
ADD1(X3)
;BAR = 0,<
; X1
; X2
; X3>
SEC(\BAR) ;THIS GENERATES THE FOLLOWING:
; X1
; X2
; X3
4.2 FOR
There are three types of FORs; all have the same general form. Each
consists of the word FOR, an optional concatenation character, a
range specifier, and a FOR-body. The FOR statement expands into the
text of its FOR-body, possibly with substitutions, repeated once for
each element in the range of the FOR. FOR replaces the IRP and IRPC
pseudo-ops found in MACRO-10. FOR is a pseudo-op; it is recognized
only where FAIL allows opcodes to appear.
The optional concatenation character is specified by following the
word FOR with an at-sign followed immediately by the concatenation
character. If a FOR is used inside a macro and concatenation of FOR
arguments is desired, it is necessary to have a concatenation
character specified for the FOR which is different from the one for
the macro.
56 Macro Operations FAIL
The range specifier is different for each type of FOR and will be
explained below. The FOR statement may have one or two formal
arguments which are specified in the range specification.
The FOR-body has the same form as a macro body; the text is enclosed
in braces, and braces must be balanced.
4.2.1 String FOR
The range specification consists of one or two formal argument
identifiers, followed by either the identifier "IN" or the
containment character (⊂), followed by an argument list. The
argument list has the same syntax as a macro call argument list (see
section 4.1.5, page 52), but the list must be in parentheses. The
effect is that the body of the FOR is assembled once for each element
in the argument list, and that element is substituted for the first
(or only) formal argument each time. The second formal argument, if
present, will have the remainder of the argument list (starting with
the element following the one currently substituted for the first
argument) substituted for it.
Examples:
Source Expansion
FOR A IN (QRN,{(<JRST 4,>)},STORP) MOVSI 13,QRN
{MOVSI 13,A PUSHJ P,GORP
PUSHJ P,GORP MOVSI 13,(<JRST 4,>)
} PUSHJ P,GORP
MOVSI 13,STORP
PUSHJ P,GORP
Source Expansion
FOR ZOT,FUB ⊂ (A,B,C,D) MOVEI A,137 ; B,C,D LEFT
{MOVEI ZOT,137 ; FUB LEFT MOVEI B,137 ; C,D LEFT
} MOVEI C,137 ; D LEFT
MOVEI D,137 ; LEFT
4.2.2 Character FOR
The range specifier consists of one or two formal arguments followed
by either the letter "E" or the character epsilon (ε), followed by a
string of characters enclosed in braces. The only restriction on the
string of characters is that the braces must balance. The body of
FAIL Macro Operations 57
the FOR is assembled once for each character in the list, with that
character substituted for the first formal argument each time and the
rest of the string substituted for the second formal argument, if
any.
Examples:
Source Expansion
FOR ZOT,FUB ε {ABCD} MOVEI A,137 ; BCD LEFT
{MOVEI ZOT,137 ; FUB LEFT MOVEI B,137 ; CD LEFT
} MOVEI C,137 ; D LEFT
MOVEI D,137 ; LEFT
Source Expansion
FOR @$ QRN E {AZ1Q5} ZORPA←0
{ZORP$QRN←0 ZORPZ←0
} ZORP1←0
ZORPQ←0
ZORP5←0
4.2.3 Arithmetic FOR
This type of FOR is similar to the ALGOL FOR statement. The range
specifier consists of one or two formal arguments followed by a left-
arrow, followed by two or three expressions, separated by commas.
The expressions are like the two or three arguments of a FORTRAN DO
statement. The value of the first is the starting value, the value
of the second is the ending value, and the value of the third is the
increment. If the third expression is not present, 1 is used as the
increment.
The body of the FOR is assembled repeatedly, first for the starting
value, then for the starting value plus the increment, etc. until it
has been assembled once for each such value which is less than or
equal to the ending value (greater than or equal if the increment is
negative). If the starting value is already greater than the ending
value (less than, for negative increment), the FOR body is not
assembled at all. For each repetition, the current value is
converted to ascii digits in the current radix, and that string is
substituted for the formal argument(s) (both arguments have the same
value). Note that all expressions must be defined, available, and
absolute.
58 Macro Operations FAIL
Examples (assume RADIX =8):
Source Expansion
FOR I←1+3, 25, 7 XWD FOO,4
{XWD FOO,I XWD FOO,13
} XWD FOO,22
Source Expansion
FOR @$ ZOT←11,4,-1 ZOTQ11 : 11 +3
{ZOTQ$ZOT : ZOT +3 ZOTQ10 : 10 +3
} ZOTQ7 : 7 +3
ZOTQ6 : 6 +3
ZOTQ5 : 5 +3
ZOTQ4 : 4 +3
4.3 REPEAT
The REPEAT statement is included for compatibility with MACRO-10.
REPEAT is a pseudo-op; it is recognized only where FAIL allows
opcodes to appear. The format is
REPEAT exp,{text}
The expression exp is evaluated, and the text is assembled that
number of times, with a carriage return and line feed inserted at its
end each time. The text is like a macro body: braces must balance.
For example, the statement:
REPEAT 3, {0}
will expand to:
0
0
0
FAIL Macro Operations 59
4.4 Conditional Assembly
The conditional assembly opcodes (the IFs) are like macros: they will
be recognized wherever they appear, as long as the assembler sees
them as identifiers. Thus, an IF need not be the first thing on a
line. Attempts to use IFs as symbols will produce erroneous results.
4.4.1 Numeric IFs
There are six numeric IFs:
IFE exp,{text} assembles text if exp=0
IFN exp,{text} assembles text if exp≠0
IFG exp,{text} assembles text if exp>0
IFL exp,{text} assembles text if exp<0
IFGE exp,{text} assembles text if exp≥0
IFLE exp,{text} assembles text if exp≤0
The expression exp is evaluated. If its value bears the indicated
relation to zero, the text is assembled once; otherwise it is not
assembled. The text, which is called the IF-body, is like a macro
body: braces must balance.
Examples:
IFE 3, {ZOT} assembles nothing
IFGE 15, {JRST START} assembles JRST START
PUSHJ P,IFN PARM,{BAZ;}FOO assembles PUSHJ P,BAZ;FOO if PARM≠0
PUSHJ P,IFN PARM,{BAZ;}FOO assembles PUSHJ P,FOO if PARM=0
4.4.2 Text IFs
There are two text IFs. They are IFIDN and IFDIF, which stand for
"if identical" and "if different", respectively. The format is
IFIDN {text 1} {text 2} {text 3}
The texts can be any string of characters in which the braces
balance. For IFIDN, if the two strings text 1 and text 2 are
identical in each and every character, the string text 3 will be
assembled, otherwise it will not. For IFDIF, if text 1 and text 2
are different, text 3 will be assembled, otherwise it will not.
60 Macro Operations FAIL
4.4.3 Symbol IFs
There are eight symbol IFs. They are IFDEF, IFNDEF, IFAVL, IFNAVL,
IFOP, IFNOP, IFMAC, and IFNMAC. A typical example is
IFDEF symbol,{text}
If the indicated condition is true for the symbol, the text is
assembled; otherwise it is not. These conditionals come in pairs;
if one of a pair is true, the other is false.
IFDEF is true if the symbol is defined in this block or in an outer
block. Defined symbols may be either opcodes, macro names, labels,
or parameters. IFDEF will be true if the symbol could be used on a
line by itself (ignoring possible future definitions).
IFAVL is true if the symbol is available. That is, IFAVL is true if
the symbol is defined as an opcode or macro or if it has been defined
in this block, declared global in this block and defined in an outer
block, or defined in an outer block with a down-arrow.
IFOP is true if the symbol is defined as an opcode.
IFMAC is true if the symbol is defined as a macro (including the IFs,
IOWD, and the predefined symbols .CPU., .FNAM1, .FNAM2, .INSERT,
"$.", and ".").
FAIL Appendix A 61
Command Language
The basic format of a FAIL command is
binary-file,listing-file←source-file-1, ... ,source-file-n
File specifications consist of
device:file
If device: is missing, DSK: is assumed. Either (or both) output
file(s) may be omitted. If the listing-file is included, a comma
must precede it. Source-file names are separated by commas. The
device name for source files is sticky, so to change devices the
device name must be explicit, even if it is DSK:. Multiple source
files are concatenated as one assembly. If the last source-file name
on a line ends with a comma (and carriage return-line feed) then the
next line is taken as a continuation of this command.
If no file extension is given for the binary file then REL is
assumed. If no file extension for the listing file is given then at
Stanford A.I. Lab and at Tenex sites (including TOPS-20 sites) LST is
assumed; at other sites, CRF is used. If no extension is given for
the source file(s), FAI is tried first; failing that, a blank
extension is tried.
Switches should follow file names and may be either of the slash type
or parentheses type (e.g., "/x" or "(x)").
Device switches (must follow the name of the affected file):
nA advance magnetic tape n files
nB backspace magnetic tape n files
T skip to logical end of magnetic tape
W rewind magnetic tape
Z zero DECtape directory
Assembler switches (may appear after any file name):
62 Appendix A FAIL
C make a cross-reference (CREF) listing
F don't pause after errors (inverse of R)
I ignore XLIST1 pseudo-op
J turn on cross-reference listing output
K turn off cross-reference listing output
L don't list literal values with text
N don't list assembly errors on TTY
O omit binary universal (FUN) file output
R pause after each assembly error
S list symbol table
U underline macro expansions on listing
nV set the number of lines/page in listing to n
X don't list macro expansions
The P switch is used to allocate extra space for the macro push-down
list (PDL), which is normally 200 (octal) locations long. If
recursive macros are used, more space may be needed. The macro PDL
will be expanded by 200 words for every occurrence of the P switch in
the command string. A numeric argument may given with the P switch
to specify a multiple of 200 words by which to expand the PDL.
The E switch is used to allocate extra space for the main push-down
list. The main PDL will be expanded by 200 words for every
occurrence of the E switch in the command string. A numeric argument
may given with the E switch to specify a multiple of 200 words by
which to expand the PDL.
Sometimes, assembly parameters are specified from the user terminal,
rather than being included in the source program. Suppose the line
SEGSW←←1 needs to be included in the assembly of the file BAZ. The
following command sequence would do that (and make a cross-reference
listing of BAZ):
BAZ,BAZ/C←TTY:,DSK:BAZ
SEGSW←←1
↑Z
The text is typed to FAIL and terminated with control-Z (↑Z) (at
Stanford A.I. Lab displays, control-meta-line feed is used instead of
control-Z). Using SNAIL (known elsewhere as COMPIL), the command
sequence would be
COMPILE/CREF TTY:F+DSK:BAZ
SEGSW←←1
↑Z
The file name F is needed to satisfy the SNAIL syntax; the device
name DSK: is needed to switch the default input device to DSK.
FAIL Appendix A 63
If the command FILE@ is seen, the named file will be read and
interpreted as containing a series of commands of the usual form.
The command FILE! causes FAIL to exit and run the named program. The
default device for this command is SYS:.
To provide some compatibility with SNAIL-style commands, FAIL accepts
"=" for "←" in the command line. Also, either "+" or ";" may be used
instead of "," to separate source-file names.
64 Appendix B FAIL
Relocatable and Undefined Values
FAIL binary programs are usually required to be relocatable, i.e.,
loadable anywhere in a core image. Many values depend upon the
absolute location of a program within its core image, e.g., the
target address of a branch instruction. The final determination of
these values must be made by the loader.
The problem of relocation can usually be reduced to a question of
whether or not to augment a value by the relocation constant, which
is simply the location at which the loader decides to begin loading
this program. The mechanism for handling this involves associating
with each value a relocation factor, which is (at load time) to be
multiplied by the relocation constant and added to the value. For
the simple relocation mechanism to work, the relocation factor must
be a constant and either 0 or 1. Since 36 bits may contain two 18-
bit addresses, a relocation factor is provided for each halfword.
Thus, a value which is completely determined except for simple
relocation can be expressed in 38 bits. A value in which at least
one relocation factor is non-zero is said to be relocatable; one in
which both are zero is said to be unrelocatable or absolute.
There is a more general, less efficient mechanism for delaying
calculations until load time. This is used in more complex cases
where the simple relocation scheme is inadequate. Whenever a value
cannot be calculated immediately and cannot be handled by the
relocation mechanism because it requires some other type of deferred
calculation, the value is said to be undefined. Undefined values are
represented by relatively complex structures which are retained in
FAIL for final evaluation or, if necessary, passed to the loader for
evaluation. Undefined values are illegal in those contexts which
require the value to be immediately known, including some situations
where the relocation factor mechanism is legal. The legality of
undefined or relocatable values is indicated in the discussion of
each possible usage.
FAIL Appendix C 65
Predefined Opcodes
The standard machine instruction mnemonics of the KL10 are defined in
FAIL.
When the Stanford A.I. Lab version of FAIL is started, it obtains
from the system the definitions for all system UUOs and CALLIs that
are available at the time of the assembly.
The table that follows includes all the pseudo-ops, machine
instruction mnemonics, special symbols, and UUO mnemonics currently
available at Stanford A.I. Lab. The indication SAIL is used to
indicate UUOs and machine instructions available only at Stanford
A.I. Lab. The indication UUO is used to mark system calls that are
also available on a DEC system. Hardware I/O instructions are
indicated by I/O; these instructions are not available to normal user
programs. KI and KL signify instructions that are available on the
KI10 and KL10 processors. The entry for each pseudo-op includes the
page number where that pseudo-op is explained.
Note that there are sometimes subtle differences between DEC system
UUOs and Stanford A.I. Lab UUOs; consult the appropriate reference
manual. Also note that some DEC mnemonics conflict with those used
at Stanford A.I. Lab.
66 Appendix C FAIL
$. Predefined page 18 AOJG 347000,,0
. Predefined page 18 AOJGE 345000,,0
.ASSIGN Pseudo-op page 46 AOJL 341000,,0
.COMMON Pseudo-op page 46 AOJLE 343000,,0
.CPU. Predefined page 19 AOJN 346000,,0
.DIRECT Pseudo-op page 45 AOS 350000,,0
.FATAL Pseudo-op page 45 AOSA 354000,,0
.FNAM1 Predefined page 19 AOSE 352000,,0
.FNAM2 Predefined page 19 AOSG 357000,,0
.GOPDEF Pseudo-Op page 33 AOSGE 355000,,0
.INSERT Pseudo-Op page 44 AOSL 351000,,0
.LIBRARY Pseudo-Op page 35 AOSLE 353000,,0
.LINK Pseudo-Op page 35 AOSN 356000,,0
.LNKEND Pseudo-Op page 35 APRENB CALLI 16 UUO
.LOAD Pseudo-Op page 35 ARRAY Pseudo-Op page 42
.ORG Pseudo-Op page 28 ASCID Pseudo-Op page 40
.REQUEST Pseudo-Op page 35 ASCII Pseudo-Op page 40
.REQUIRE Pseudo-Op page 35 ASCIZ Pseudo-Op page 40
.TEXT Pseudo-Op page 46 ASH 240000,,0
ASHC 244000,,0
ACCTIM CALLI 400101 SAIL ASSIGN Pseudo-Op page 46
ACTCHR CALLI 400105 SAIL ASUPPRESS Pseudo-Op page 37
ADD 270000,,0 ATTSEG CALLI 400016 SAIL
ADDB 273000,,0
ADDI 271000,,0 BEEP CALLI 400111 SAIL
ADDM 272000,,0 BEGIN Pseudo-Op page 33
ADJSP 105000,,0 KL BEND Pseudo-Op page 33
ADSMAP CALLI 400110 SAIL BLKI 700000,,0 I/O
AND 404000,,0 BLKO 700100,,0 I/O
ANDB 407000,,0 BLOCK Pseudo-Op page 42
ANDCA 410000,,0 BLT 251000,,0
ANDCAB 413000,,0 BUFLEN CALLI 400042 SAIL
ANDCAI 411000,,0 BYTE Pseudo-Op page 39
ANDCAM 412000,,0
ANDCB 440000,,0 CAI 300000,,0
ANDCBB 443000,,0 CAIA 304000,,0
ANDCBI 441000,,0 CAIE 302000,,0
ANDCBM 442000,,0 CAIG 307000,,0
ANDCM 420000,,0 CAIGE 305000,,0
ANDCMB 423000,,0 CAIL 301000,,0
ANDCMI 421000,,0 CAILE 303000,,0
ANDCMM 422000,,0 CAIN 306000,,0
ANDI 405000,,0 CALL 040000,,0 UUO
ANDM 406000,,0 CALLI 047000,,0 UUO
AOBJN 253000,,0 CALLIT CALLI 400074 SAIL
AOBJP 252000,,0 CAM 310000,,0
AOJ 340000,,0 CAMA 314000,,0
AOJA 344000,,0 CAME 312000,,0
AOJE 342000,,0 CAMG 317000,,0
FAIL Appendix C 67
CAMGE 315000,,0 DIVI 235000,,0
CAML 311000,,0 DIVM 236000,,0
CAMLE 313000,,0 DMOVE 120000,,0 KI
CAMN 316000,,0 DMOVEM 124000,,0 KI
CHNSTS 716000,,0 SAIL DMOVN 121000,,0 KI
CLKINT 717000,,0 SAIL DMOVNM 125000,,0 KI
CLOSE 070000,,0 UUO DMUL 116000,,0 KL
CLRBFI 051440,,0 UUO DPB 137000,,0
CLRBFO 051500,,0 UUO DPYCLR 701000,,0 SAIL
COMMENT Pseudo-Op page 44 DPYOUT 703000,,0 SAIL
CONI 700240,,0 I/O DPYPOS 702100,,0 SAIL
CONO 700200,,0 I/O DPYSIZ 702140,,0 SAIL
CONS 257000,,0 SAIL DSKPPN CALLI 400071 SAIL
CONSO 700340,,0 I/O DSKTIM CALLI 400072 SAIL
CONSZ 700300,,0 I/O DSUB 115000,,0 KL
CORE CALLI 11 UUO
CORE2 CALLI 400015 SAIL EIOTM CALLI 400005 SAIL
CREF Pseudo-Op page 48 END Pseudo-Op page 43
CTLV CALLI 400001 SAIL ENTER 077000,,0 UUO
ENTRY Pseudo-Op page 34
DADD 114000,,0 KL EQV 444000,,0
DATAI 700040,,0 I/O EQVB 447000,,0
DATAO 700140,,0 I/O EQVI 445000,,0
DATE CALLI 14 UUO EQVM 446000,,0
DAYCNT CALLI 400100 SAIL EXCH 250000,,0
DDCHAN CALLI 400067 SAIL EXIT CALLI 12 UUO
DDIV 117000,,0 KL EXTEND 123000,,0 KL
DDTGT CALLI 5 UUO EXTERNAL Pseudo-Op page 34
DDTIN CALLI 1 UUO
DDTOUT CALLI 3 UUO FAD 140000,,0
DDTRL CALLI 7 UUO FADB 143000,,0
DDUPG 715140,,0 SAIL FADL 141000,,0
DEBREAK CALLI 400035 SAIL FADM 142000,,0
DEC Pseudo-Op page 39 FADR 144000,,0
DEFINE Pseudo-Op page 49 FADRB 147000,,0
DEPHASE Pseudo-Op page 30 FADRI 145000,,0
DETSEG CALLI 400017 SAIL FADRL 145000,,0
DEVCHR CALLI 4 UUO FADRM 146000,,0
DEVNUM CALLI 400104 SAIL FBREAD 706000,,0 SAIL
DEVUSE CALLI 400051 SAIL FBWAIT CALLI 400057 SAIL
DFAD 110000,,0 KI FBWRT 707000,,0 SAIL
DFDV 113000,,0 KI FDV 170000,,0
DFMP 112000,,0 KI FDVB 173000,,0
DFN 131000,,0 FDVL 171000,,0
DFSB 111000,,0 KI FDVM 172000,,0
DIAL CALLI 400117 SAIL FDVR 174000,,0
DISMISS CALLI 400024 SAIL FDVRB 177000,,0
DIV 234000,,0 FDVRI 175000,,0
DIVB 237000,,0 FDVRL 175000,,0
68 Appendix C FAIL
FDVRM 176000,,0 HLLOI 521000,,0
FIX 122000,,0 KI xSAIL HLLOM 522000,,0
FIXR 126000,,0 KI HLLOS 523000,,0
FLTR 127000,,0 KI HLLS 503000,,0
FMP 160000,,0 HLLZ 510000,,0
FMPB 163000,,0 HLLZI 511000,,0
FMPL 161000,,0 HLLZM 512000,,0
FMPM 162000,,0 HLLZS 513000,,0
FMPR 164000,,0 HLR 544000,,0
FMPRB 167000,,0 HLRE 574000,,0
FMPRI 165000,,0 HLREI 575000,,0
FMPRL 165000,,0 HLREM 576000,,0
FMPRM 166000,,0 HLRES 577000,,0
FOR Pseudo-Op page 55 HLRI 545000,,0
FSB 150000,,0 HLRM 546000,,0
FSBB 153000,,0 HLRO 564000,,0
FSBL 151000,,0 HLROI 565000,,0
FSBM 152000,,0 HLROM 566000,,0
FSBR 154000,,0 HLROS 567000,,0
FSBRB 157000,,0 HLRS 547000,,0
FSBRI 155000,,0 HLRZ 554000,,0
FSBRL 155000,,0 HLRZI 555000,,0
FSBRM 156000,,0 HLRZM 556000,,0
FSC 132000,,0 HLRZS 557000,,0
HRL 504000,,0
GDEFINE Pseudo-Op page 49 HRLE 534000,,0
GDPTIM CALLI 400065 SAIL HRLEI 535000,,0
GETCHR CALLI 6 UUO HRLEM 536000,,0
GETLIN 051300,,0 SAIL HRLES 537000,,0
GETLN CALLI 34 UUO HRLI 505000,,0
GETNAM CALLI 400062 SAIL HRLM 506000,,0
GETPPN CALLI 24 UUO HRLO 524000,,0
GETPR2 CALLI 400053 SAIL HRLOI 525000,,0
GETPRV CALLI 400115 SAIL HRLOM 526000,,0
GETSEG CALLI 40 UUO HRLOS 527000,,0
GETSTS 062000,,0 UUO HRLS 507000,,0
GETTAB CALLI 41 UUO HRLZ 514000,,0
GLOBAL Pseudo-Op page 34 HRLZI 515000,,0
HRLZM 516000,,0
HALT 254200,,0 HRLZS 517000,,0
HISEG Pseudo-Op page 30 HRR 540000,,0
HLL 500000,,0 HRRE 570000,,0
HLLE 530000,,0 HRREI 571000,,0
HLLEI 531000,,0 HRREM 572000,,0
HLLEM 532000,,0 HRRES 573000,,0
HLLES 533000,,0 HRRI 541000,,0
HLLI 501000,,0 HRRM 542000,,0
HLLM 502000,,0 HRRO 560000,,0
HLLO 520000,,0 HRROI 561000,,0
FAIL Appendix C 69
HRROM 562000,,0 INTACM CALLI 400027 SAIL
HRROS 563000,,0 INTDEJ 723000,,0 SAIL
HRRS 543000,,0 INTDMP 723140,,0 SAIL
HRRZ 550000,,0 INTEGER Pseudo-Op page 42
HRRZI 551000,,0 INTENB CALLI 400025 SAIL
HRRZM 552000,,0 INTENS CALLI 400030 SAIL
HRRZS 553000,,0 INTERNAL Pseudo-Op page 34
INTGEN CALLI 400033 SAIL
IBP 133000,,0 INTIIP CALLI 400031 SAIL
IDIV 230000,,0 INTIPI 723200,,0 SAIL
IDIVB 233000,,0 INTIRQ CALLI 400032 SAIL
IDIVI 231000,,0 INTJEN 723000,,0 SAIL
IDIVM 232000,,0 INTMSK 720000,,0 SAIL
IDPB 136000,,0 INTORM CALLI 400026 SAIL
IENBW CALLI 400045 SAIL INTUUO 723000,,0 SAIL
IFAVL Conditional page 60 INWAIT 051600,,0 SAIL
IFDEF Conditional page 60 IOPDL 726000,,0 SAIL
IFDIF Conditional page 59 IOPOP 725000,,0 SAIL
IFE Conditional page 59 IOPUSH 724000,,0 SAIL
IFG Conditional page 59 IOR 434000,,0
IFGE Conditional page 59 IORB 437000,,0
IFIDN Conditional page 59 IORI 435000,,0
IFL Conditional page 59 IORM 436000,,0
IFLE Conditional page 59 IOWD Pseudo-Op page 40
IFMAC Conditional page 60 IWAIT CALLI 400040 SAIL
IFN Conditional page 59 IWKMSK 723100,,0 SAIL
IFNAVL Conditional page 60
IFNDEF Conditional page 60 JBTSTS CALLI 400013 SAIL
IFNMAC Conditional page 60 JCRY 255300,,0
IFNOP Conditional page 60 JCRY0 255200,,0
IFOP Conditional page 60 JCRY1 255100,,0
ILDB 134000,,0 JEN 254500,,0
IMSKCL 722000,,0 SAIL JFCL 255000,,0
IMSKCR 723240,,0 SAIL JFFO 243000,,0
IMSKST 721000,,0 SAIL JFOV 255040,,0
IMSTW 723040,,0 SAIL JOBRD CALLI 400050 SAIL
IMUL 220000,,0 JOV 255400,,0
IMULB 223000,,0 JRA 267000,,0
IMULI 221000,,0 JRST 254000,,0
IMULM 222000,,0 JRSTF 254100,,0
IN 056000,,0 UUO JSA 266000,,0
INBUF 064000,,0 UUO JSP 265000,,0
INCHRS 051100,,0 UUO JSR 264000,,0
INCHRW 051000,,0 UUO JSYS 104000,,0
INCHSL 051240,,0 UUO JUMP 320000,,0
INCHWL 051200,,0 UUO JUMPA 324000,,0
INIT 041000,,0 UUO JUMPE 322000,,0
INPUT 066000,,0 UUO JUMPG 327000,,0
INSKIP 051540,,0 SAIL JUMPGE 325000,,0
70 Appendix C FAIL
JUMPL 321000,,0 NAMEIN CALLI 400043 SAIL
JUMPLE 323000,,0 NOLIT Pseudo-Op page 47
JUMPN 326000,,0 NOSYM Pseudo-Op page 48
KAFIX 247000,,0 KA SAIL OCT Pseudo-Op page 39
KIFIX 122000,,0 KI SAIL OPDEF Pseudo-Op page 33
OPEN 050000,,0 UUO
LALL Pseudo-Op page 47 OR 434000,,0
LDB 135000,,0 ORB 437000,,0
LEYPOS 702300,,0 SAIL ORCA 454000,,0
LINK Pseudo-Op page 35 ORCAB 457000,,0
LINKEND Pseudo-Op page 35 ORCAI 455000,,0
LINKUP CALLI 400023 SAIL ORCAM 456000,,0
LIOTM CALLI 400006 SAIL ORCB 470000,,0
LIST Pseudo-Op page 47 ORCBB 473000,,0
LIT Pseudo-Op page 32 ORCBI 471000,,0
LOC Pseudo-Op page 28 ORCBM 472000,,0
LOCK CALLI 400076 SAIL ORCM 464000,,0
LOGIN CALLI 15 UUO ORCMB 467000,,0
LOGOUT CALLI 17 UUO ORCMI 465000,,0
LOOKUP 076000,,0 UUO ORCMM 466000,,0
LSH 242000,,0 ORG Pseudo-Op page 28
LSHC 246000,,0 ORI 435000,,0
ORM 436000,,0
MAIL 710000,,0 SAIL OUT 057000,,0 UUO
MAP 257000,,0 KI OUTBUF 065000,,0 UUO
MOVE 200000,,0 OUTCHR 051040,,0 UUO
MOVEI 201000,,0 OUTFIV 051740,,0 SAIL
MOVEM 202000,,0 OUTPUT 067000,,0 UUO
MOVES 203000,,0 OUTSTR 051140,,0 UUO
MOVM 214000,,0
MOVMI 215000,,0 PAGE Pseudo-Op page 48
MOVMM 216000,,0 PEEK CALLI 33 UUO
MOVMS 217000,,0 PGACT 715040,,0 SAIL
MOVN 210000,,0 PGCLR 715100,,0 SAIL
MOVNI 211000,,0 PGINFO 715200,,0 SAIL
MOVNM 212000,,0 PGIOT 715000,,0 SAIL
MOVNS 213000,,0 PGSEL 715000,,0 SAIL
MOVS 204000,,0 PHASE Pseudo-Op page 30
MOVSI 205000,,0 PJOB CALLI 30 UUO
MOVSM 206000,,0 PNAME CALLI 400007 SAIL
MOVSS 207000,,0 POINT Pseudo-Op page 39
MSTIME CALLI 23 UUO POINTS 712000,,0 SAIL
MTAPE 072000,,0 UUO POP 262000,,0
MUL 224000,,0 POPJ 263000,,0
MULB 227000,,0 PORTAL 254040,,0 KI
MULI 225000,,0 PPACT 702040,,0 SAIL
MULM 226000,,0 PPHLD 702340,,0 SAIL
PPINFO 702240,,0 SAIL
FAIL Appendix C 71
PPIOT 702000,,0 SAIL SEND 710000,,0 SAIL
PPREL 702200,,0 SAIL SET Pseudo-Op page 29
PPSEL 702000,,0 SAIL SETA 424000,,0
PPSPY CALLI 400107 SAIL SETAB 427000,,0
PRGEND Pseudo-Op page 43 SETACT 051640,,0 SAIL
PRINTS Pseudo-Op page 48 SETAI 425000,,0
PRINTX Pseudo-Op page 48 SETAM 426000,,0
PTGETL 711540,,0 SAIL SETCA 450000,,0
PTIFRE 711100,,0 SAIL SETCAB 453000,,0
PTJOBX 711700,,0 SAIL SETCAI 451000,,0
PTLOAD 711640,,0 SAIL SETCAM 452000,,0
PTOCNT 711140,,0 SAIL SETCM 460000,,0
PTRD1S 711200,,0 SAIL SETCMB 463000,,0
PTRD1W 711240,,0 SAIL SETCMI 461000,,0
PTRDS 711400,,0 SAIL SETCMM 462000,,0
PTSETL 711600,,0 SAIL SETCRD CALLI 400073 SAIL
PTWR1S 711300,,0 SAIL SETDDT CALLI 2 UUO
PTWR1W 711340,,0 SAIL SETLIN 051340,,0 SAIL
PTWRS7 711440,,0 SAIL SETM 414000,,0
PTWRS9 711500,,0 SAIL SETMB 417000,,0
PTYGET 711000,,0 SAIL SETMI 415000,,0
PTYREL 711040,,0 SAIL SETMM 416000,,0
PTYUUO 711000,,0 SAIL SETNAM CALLI 43 UUO
PURGE Pseudo-Op page 36 SETNM2 CALLI 400036 SAIL
PUSH 261000,,0 SETO 474000,,0
PUSHJ 260000,,0 SETOB 477000,,0
PZE 000000,,0 SETOI 475000,,0
SETOM 476000,,0
RADIX Pseudo-Op page 44 SETPOV CALLI 32 UUO
RADIX50 Pseudo-Op page 41 SETPR2 CALLI 400052 SAIL
REASSI CALLI 21 UUO SETPRO CALLI 400020 SAIL
RELEAS 071000,,0 UUO SETPRV CALLI 400066 SAIL
RELOC Pseudo-Op page 28 SETSTS 060000,,0 UUO
REMAP CALLI 37 UUO SETUWP CALLI 36 UUO
RENAME 055000,,0 UUO SETZ 400000,,0
REPEAT Pseudo-Op page 58 SETZB 403000,,0
RESCAN 051400,,0 UUO SETZI 401000,,0
RESET CALLI 0 UUO SETZM 402000,,0
RLEVEL CALLI 400054 SAIL SIXBIT Pseudo-Op page 40
ROT 241000,,0 SKIP 330000,,0
ROTC 245000,,0 SKIPA 334000,,0
RUN CALLI 35 UUO SKIPE 332000,,0
RUNMSK CALLI 400046 SAIL SKIPG 337000,,0
RUNTIM CALLI 27 UUO SKIPGE 335000,,0
SKIPL 331000,,0
SEARCH Pseudo-Op page 38 SKIPLE 333000,,0
SEGNAM CALLI 400037 SAIL SKIPN 336000,,0
SEGNUM CALLI 400021 SAIL SKPHIM 710200,,0 SAIL
SEGSIZ CALLI 400022 SAIL SKPME 710140,,0 SAIL
72 Appendix C FAIL
SKPSEN 710240,,0 SAIL TDZA 634000,,0
SLEEP CALLI 31 UUO TDZE 632000,,0
SLEVEL CALLI 400044 SAIL TDZN 636000,,0
SNEAKS CALLI 400064 SAIL TIMER CALLI 22 UUO
SNEAKW CALLI 400063 SAIL TITLE Pseudo-Op page 43
SOJ 360000,,0 TLC 641000,,0
SOJA 364000,,0 TLCA 645000,,0
SOJE 362000,,0 TLCE 643000,,0
SOJG 367000,,0 TLCN 647000,,0
SOJGE 365000,,0 TLN 601000,,0
SOJL 361000,,0 TLNA 605000,,0
SOJLE 363000,,0 TLNE 603000,,0
SOJN 366000,,0 TLNN 607000,,0
SOS 370000,,0 TLO 661000,,0
SOSA 374000,,0 TLOA 665000,,0
SOSE 372000,,0 TLOE 663000,,0
SOSG 377000,,0 TLON 667000,,0
SOSGE 375000,,0 TLZ 621000,,0
SOSL 371000,,0 TLZA 625000,,0
SOSLE 373000,,0 TLZE 623000,,0
SOSN 376000,,0 TLZN 627000,,0
SPCWAR 043000,,0 SAIL TMPCOR CALLI 44 UUO
SPCWGO CALLI 400003 SAIL TMPCRD CALLI 400103 SAIL
SPWBUT CALLI 400000 SAIL TRC 640000,,0
SRCV 710100,,0 SAIL TRCA 644000,,0
STATO 061000,,0 UUO TRCE 642000,,0
STATZ 063000,,0 UUO TRCN 646000,,0
SUB 274000,,0 TRN 600000,,0
SUBB 277000,,0 TRNA 604000,,0
SUBI 275000,,0 TRNE 602000,,0
SUBM 276000,,0 TRNN 606000,,0
SUBTTL Pseudo-Op page 47 TRO 660000,,0
SUPPRESS Pseudo-Op page 37 TROA 664000,,0
SWAP CALLI 400004 SAIL TROE 662000,,0
SWITCH CALLI 20 UUO TRON 666000,,0
TRZ 620000,,0
TDC 650000,,0 TRZA 624000,,0
TDCA 654000,,0 TRZE 622000,,0
TDCE 652000,,0 TRZN 626000,,0
TDCN 656000,,0 TSC 651000,,0
TDN 610000,,0 TSCA 655000,,0
TDNA 614000,,0 TSCE 653000,,0
TDNE 612000,,0 TSCN 657000,,0
TDNN 616000,,0 TSN 611000,,0
TDO 670000,,0 TSNA 615000,,0
TDOA 674000,,0 TSNE 613000,,0
TDOE 672000,,0 TSNN 617000,,0
TDON 676000,,0 TSO 671000,,0
TDZ 630000,,0 TSOA 675000,,0
FAIL Appendix C 73
TSOE 673000,,0 XCT 256000,,0
TSON 677000,,0 XGPUUO CALLI 400075 SAIL
TSZ 631000,,0 XLIST Pseudo-Op page 47
TSZA 635000,,0 XLIST1 Pseudo-Op page 47
TSZE 633000,,0 XOR 430000,,0
TSZN 637000,,0 XORB 433000,,0
TTCALL 051000,,0 UUO XORI 431000,,0
TTREAD 051700,,0 SAIL XORM 432000,,0
TTYIOS CALLI 400014 SAIL XPUNGE Pseudo-Op page 36
TTYJOB CALLI 400113 SAIL XWD Pseudo-Op page 40
TTYMES CALLI 400047 SAIL
TTYSKP CALLI 400116 SAIL
TTYUUO 051000,,0 UUO
TWOSEG Pseudo-Op page 30
UFA 130000,,0
UFBCLR CALLI 400012 SAIL
UFBERR CALLI 400060 SAIL
UFBGET CALLI 400010 SAIL
UFBGIV CALLI 400011 SAIL
UFBPHY CALLI 400055 SAIL
UFBSKP CALLI 400056 SAIL
UGETF 073000,,0 UUO
UINBF 704000,,0 SAIL
UNIVERSAL Pseudo-Op page 37
UNLOCK CALLI 400077 SAIL
UNPURE CALLI 400102 SAIL
UOUTBF 705000,,0 SAIL
UPGIOT 703000,,0 SAIL
UPGMVE 713000,,0 SAIL
UPGMVM 714000,,0 SAIL
USE Pseudo-Op page 29
USETI 074000,,0 UUO
USETO 075000,,0 UUO
USKIP CALLI 400041 SAIL
UTPCLR CALLI 13 UUO
UUOSIM CALLI 400106 SAIL
UWAIT CALLI 400034 SAIL
VAR Pseudo-Op page 32
VDSMAP CALLI 400070 SAIL
WAIT CALLI 10 UUO
WAKEME CALLI 400061 SAIL
WHO CALLI 400112 SAIL
WRCV 710040,,0 SAIL
XALL Pseudo-Op page 47
XCREF Pseudo-Op page 48
74 Appendix D FAIL
Stanford A. I. Lab Character Set
The Stanford Character Set is displayed in the following table. The
three-digit octal code for a character is composed of the number at
the left of its row plus the digit at the top of its column. For
example, the code for A is 100+1 or 101.
0 1 2 3 4 5 6 7
000 NUL ↓ α β ∧ ¬ ε π
010 λ TAB LF VT FF CR ∞ ∂
020 ⊂ ⊃ ∩ ∪ ∀ ∃ ⊗ ↔
030 _ → ~ ≠ ≤ ≥ ≡ ∨
040 SP ! " # $ % & '
050 ( ) * + , - . /
060 0 1 2 3 4 5 6 7
070 8 9 : ; < = > ?
100 @ A B C D E F G
110 H I J K L M N O
120 P Q R S T U V W
130 X Y Z [ \ ] ↑ ←
140 ` a b c d e f g
150 h i j k l m n o
160 p q r s t u v w
170 x y z { | ALT } RO
NUL Null
TAB Horizontal Tab
LF Line Feed
VT Vertical Tab
FF Form Feed
CR Carriage Return
SP Space
ALT Altmode
RO Rub Out (On A.I. Lab displays this key is labeled BS)
The differences between ASCII and the Stanford A. I. Lab character
set may be summarized briefly as follows:
1. ASCII codes 0 through 37 do not print anything
2. The Stanford characters "←" and "↑" correspond to the
ASCII characters underbar "_" and carat "∧".
FAIL Appendix D 75
3. In ASCII codes 175 and 176 are "}" and "~".
76 Appendix E FAIL
Summary of Character Interpretations
The characters listed below have special meaning in the contexts
indicated. These interpretations do not apply when these characters
appear in text strings or in comments.
000 NUL null ignored on input
001 ↓ down-arrow makes a symbol available in a lower
block
002 α alpha
003 β beta
004 ∧ logical and boolean AND
005 ¬ logical not boolean NOT
006 ε epsilon delimiter in FOR
007 π pi
010 λ lambda
011 TAB tab same as space (040)
012 LF line feed line delimiter
013 VT vertical tab
014 FF form feed line delimiter; causes new listing
page
015 CR carriage return statement terminator
016 ∞ infinity
017 ∂ partial integer remainder in division
020 ⊂ containment delimiter in FOR
021 ⊃ implication
022 ∩ set intersection
023 ∪ set union
024 ∀ for all
025 ∃ there exists unary JFFO operator
026 ⊗ circle times arithmetic shift operator
027 ↔ double-arrow statement terminator; remainder of
line is interpreted as another
statement
030 _ underbar same as . (056) in identifiers
031 → right-arrow same as backslash (134)
032 ~ tilde same as up-arrow (136); illegal as
the delimiter in ASCIZ, COMMENT, etc.
033 ≠ not equal boolean XOR
034 ≤ less or equal
035 ≥ greater or equal same as not equal (033)
036 ≡ equivalence
037 ∨ logical or boolean OR
040 SP space general delimiter
041 ! exclamation same as logical or (037)
042 " double quote delimits ascii constants
043 # number sign declares a variable; illegal as the
delimiter in ASCIZ, COMMENT, etc.
044 $ dollar sign may be used in identifiers
FAIL Appendix E 77
045 % percent may be used in identifiers
046 & ampersand same as logical and (004)
047 ' close single quote delimits sixbit constants
050 ( left parenthesis encloses macro arguments,
expressions, and index fields
051 ) right parenthesis see left parenthesis (050)
052 * asterisk integer multiply
053 + plus integer addition
054 , comma general argument separator
055 - minus integer subtraction or negation
056 . point may be used in identifiers, floating
point numbers, or predefined symbol
057 / slash integer division
060 0 digits used to form number, parts of
identifiers
...
071 9
072 : colon used to define labels; illegal as the
delimiter in ASCIZ, COMMENT, etc.
073 ; semicolon forces remainder of line to be a
comment
074 < left broket delimits complex atoms; same as left
brace (173) to the macro processor
075 = equal denotes decimal number; alternate to
left-arrow (137) in assignment
statements
076 > right broket see left broket (074)
077 ? question mark same as down-arrow (001)
100 @ at-sign sets indirect bit in instructions;
precedes concatenation character in
FOR
101 A upper case letters used for identifiers; B and E are
special in numbers; E is special in
FOR
...
132 Z
133 [ left bracket delimits literals, value part of
OPDEF, size in ARRAY, PPN in .LOAD
134 \ backslash evaluate a macro argument and
converts the result to a digit string
135 ] right bracket see left bracket (133)
136 ↑ up-arrow moves a symbol definition to an outer
block; makes a symbol INTERNAL or
EXTERNAL; illegal as the delimiter in
ASCIZ, COMMENT, etc.
137 ← left-arrow denotes assignment statement;
arithmetic FOR; illegal as the
delimiter in ASCIZ, COMMENT, etc.
140 ` open single quote same as at-sign (100)
78 Appendix E FAIL
141 a lower case letters same as upper case letters, except in
text constants
...
172 z
173 { left brace delimits macro bodies, IF-bodies,
FOR-bodies, macro arguments
174 | vertical bar absolute value operator
175 ALT altmode same as right brace (176)
176 } right brace see left brace (173)
177 BS backspace illegal in input
FAIL 79
Index
$. 18, 27, 30 backslash 53
backward reference 15
. 18, 27, 30 BEGIN 33
.ASSIGN 46 BEND 33
.COMMON 46 binary universal file 37, 38
.CPU. 19 blank 49
.DIRECT 45 block 11
.FATAL 45 block number 33
.FNAM1 19 BLOCK pseudo-op 42
.FNAM2 19 Block Structure 20
.GOPDEF 33 braces 45, 49, 52, 56
.INSERT 44 brackets 25, 42, 52
.ITABM 45, 53 brokets 5, 25, 45, 49, 52
.LIBRARY 35 BYTE 39
.LINK 35 byte pointer 39
.LNKEND 35
.LOAD 35 carriage return 7, 43, 47, 50,
.NOBIN 45 52
.NOUNV 45 Character FOR 56
.ORG 28 character interpretations 76
.REQUEST 35 close single quote 15, 29
.REQUIRE 35 colon 4, 16, 19, 40, 44, 48
.TEXT 46 comma 4, 6, 29, 34, 39, 40, 41,
.XTABM 45, 53 42, 49, 52, 57, 61
comma-comma 5
absolute 11, 18, 64 Command Language 61
AC 4 comment 7
Accumulator Field 4 COMMENT pseudo-op 44
Address Field 4 COMPIL 62
apostrophe 15, 29 Complex Atoms 25
Arguments in Macro Calls 52 concatenation character 50, 55
Arguments in Macro Conditional Assembly 59
Definitions 50 Constants 11
Arithmetic FOR 57 constants optimization 26
ARRAY 42 containment character 56
ASCID 40 control-meta-line feed 62
ASCII character set 74 control-Z 62
Ascii Constants 14 CREF 1, 48, 62
ASCII pseudo-op 40 CREF pseudo-op 48
ASCIZ 40 Cross-Reference Listing 48, 62
Assembler Control Statements 43
ASSIGN 46 DDT 1, 19, 23, 33, 41, 43
assignment statement 17 DEC pseudo-op 39
ASUPPRESS 37 Decimal Numbers 12
at-sign 4, 55 decimal point 13
atomic statement 5, 7, 25 DEFINE pseudo-op 49
atoms 7, 10 defined 11, 15, 16
available 11, 20, 22 DEPHASE 30
80 Index FAIL
Destination of Assembled IFE 59
Code 28 IFG 59
device code 7 IFGE 59
device number 7 IFIDN 59
Device Selection Field 6 IFL 59
dollar sign 10 IFLE 59
dollar-point 18, 27, 30 IFMAC 60
double quote 14 IFN 59
double-arrow 7 IFNAVL 60
down-arrow 6, 22, 24, 60 IFNDEF 60
IFNMAC 60
END 43 IFNOP 60
Entering Data 39 IFOP 60
ENTRY 24, 34 Index Field 5
entry blocks 24, 34 indirect bit 4
entry point 24 Indirect Field 4
epsilon 56 Input-Output Instruction
equal sign 12, 17, 19, 44 Statement 6
Expressions 7 Instruction Statement 3
EXTERNAL 24, 34 INTEGER 42
external symbols 24, 34 INTERNAL 24, 34
internal symbols 34
fixup 16 IOWD 40
Floating-Point Numbers 13 IRP 55
FOR 55 IRPC 55
FOR-body 55
form feed 48 KA10 45
formal arguments 56 KI10 45
forward reference 15, 42
Full-Word Expression 5 Labels 16
FUN 38, 45, 62 LALL 47
left-arrow 4, 17, 19, 24, 40,
GDEFINE pseudo-op 49 44, 48, 57
GLOBAL pseudo-op 34 library 24
global symbols 23 library search mode 24
line feed 7, 44, 50
Half-Killed Symbols 19 LINK 35
Halfword Statement 5 Linkage with Separately
hardware input-output Assembled Programs 23
instruction 6 LINKEND 35
hardware instruction 3, 65 LIST 47
high segment 30 Listing Control Statements 47
HISEG 30 LIT 32, 43
literal-label 27, 36, 37
Identifiers 10 literals 25, 26, 32, 43
IF-body 59 loader 1, 8, 11, 16, 23, 24,
IFAVL 60 30, 34, 35, 36, 41, 42, 64
IFDEF 60 Loader Control Statements 46
IFDIF 59 LOC 28
FAIL Index 81
local symbols 23 RAID 1, 19, 23, 33, 41, 43
location counter 16, 18, 28, 29 range specifier 56
reference 15
machine instruction 3, 65 RELOC 28
Macro Bodies 50 relocatable 11, 17, 18, 64
Macro Calls 51 relocation constant 64
Macros 49 relocation factor 64
multiple definition 17 REPEAT 58
multiple location counters 29 reserved identifiers 10
Reserving Space for Data 42
NOLIT 47 right-arrow 53
NOSYM 48
null argument 52 Scaled Numbers 12
null statement 2 SEARCH 38
number sign 4, 18, 32, 40, 42, segment 30
44, 48 semicolon 7, 43, 47, 52
Numbers 12 SET 29
Numeric IFs 59 Simple Numbers 12
sixbit 14, 41
OCT 39 Sixbit Constants 14
octal 12 SIXBIT pseudo-op 40
Opcode Field 3 slash 61
OPDEF 33 SNAIL 62
opdefs 33 special characters 76
open single quote 4 Stanford Character Set 74
operator 7 starting address 43
ORG 28 Statement Termination 7
Statements 2
PAGE pseudo-op 48 String FOR 56
parameter 17 SUBTTL 47
parentheses 5, 7, 39, 49, 50, SUPPRESS 37
52, 56, 61 suppress bit 37
percent sign 10 symbol 11
PHASE 30 Symbol IFs 60
point 10, 18, 27, 30 Symbol Modifiers 33
POINT pseudo-op 39 Symbols 15
Polish fixup 8
Predefined Opcodes 65 tab 49
PRGEND 43 Text IFs 59
PRINTS 48 text statements 40
PRINTX 48 tilde 4, 21, 40, 44, 48
program 23 TITLE 43
Pseudo-Ops 28 Truncated Expression 6
PURGE 36 two-segment program 30
TWOSEG 30
question mark 22
unavailable 11, 21
RADIX 44 undefined 11, 64
RADIX50 41 underbar 10
82 Index FAIL
UNIVERSAL 37
universal program 37
universal symbols 37
unrelocatable 11, 64
up-arrow 4, 20, 24, 35, 40, 44,
48
USASCII 14
USE 29
user-defined opcode 33
UUO 1, 3, 6, 65
Values 10
VAR 32, 43
Variables 18, 32, 42, 43
XALL 47
XCREF 48
XLIST 47
XLIST1 47
XPUNGE 36
XWD 40