PDP-8 Assembler


Example PDP-8 Assembler Language Program - see page 4.1 of the PDP-8 Emulator User's Manual

/
/    Program : Add01.pal
/    Date    : May 30, 1997
/
/    Desc : This program computes C = A + B
/
/-------------------------------------------
/
/    Code Section
/
*0200                   / code starts at address 0200
Main,   cla cll         / clear AC and Link
        tad A           / load A
        tad B           / add B
        dca C           / store sum at C
        hlt             / halt program
        jmp Main        / to continue - goto Main
/
/    Data Section
/
*0300                   / data starts at address 0300
A,      2               / A equals 2
B,      3               / B equals 3
C,      0               / C declared
$Main                   / End of Program; Main is entry point


Type of Assembler Statements

    Assembler Directives : statements that affect how assembler translates assembler language statments; e.g. *0200

    Assembler Language Instructions : generate code; e.g. tad A

    Storage Allocation Statements : allocate storage for data; e.g. A, 2

    Comments : statements beginning with / which are ignored by assembler


General Syntax Rules

  1. all numbers are assumed octal unless they contain an 8 or 9 (e.g 028) or use a 'd' suffix (e.g. 13d) to indicate decimal; pluses and minuses are allowed
  2. symbols (identifiers) begin with a letter followed by zero or more letters and or digits; symbols are not case sensitive; symbols should be no more than 8 characters
  3. characters and strings in single quotes are assembled to their ASCII codes
  4. The characters . (dot) , (comma) / (slash) * (asterisk) $ (dollar sign) ; (semi-colon) = (equals) ' (single quote) all have special meaning or uses.

Format of a PAL instruction

[symbolic address,] opcode(s) [i] [offset] [/comment]

Appendix A from PDP-8 Emulator User's Manual: PDP-8 opcode list


Programming "Tricks"

Using the "dot" operator to perform a relative jump

    isz index    / add 1 to index
    tad index    / add index to running sum in accumulator
    isz count    / add 1 to count and skip if zero
    jmp .-3      / otherwise loop

Allocating an Array of length 10

    array, 0;0;0;0;0;0;0;0;0;0;

Storing the Value of an address at that address

    *0400        / move to address 400
    X, .         / store at X it's own address

Allocating an Array of Length 10 where "array" contains the address of the first component

    array, .+1;0;0;0;0;0;0;0;0;0;0

Defining  a Null Terminated String

    Word,    'Hello World!'; 0

Defining a Null Terminated String which ends with a Carriage Return - Line Feed combination

   Word,     'Hello World!'; 13d; 10d; 0

Defining a Null Terminated String whose first word is its own address (for use with autoindexing)

     Word,     . ;'Hello World!'; 13d; 10d; 0


The PDP-8 Assembly Process: An assembler essentially substitutes numeric values for mnemonic code using table look-up. The simplified  PDP-8 Assembler presented below does this using two tables: a pre-defined opcode table and a user-defined symbol table.

As the assembler scans each line of code, it checks the syntax of each line identifying opcodes (e.g. symbols like tad or cla cll) and user-defined symbols like Main or a which it enters into the user-defined symbol table. At the same time it keeps track of the address of the instruction using a location counter . This is used to define the value of the symbol. Often a symbol  is encountered which has not been defined. This is called the forward-reference problem. One way to solve the forward-reference problem is to use a two-pass assembler. On the first pass through the code (Pass One) the assembler checks syntax and builds the user-defined symbol table. On Pass Two the assembler, using table look-up, translates the mnemonic code into machine code.


An Example

*0200
Main, cla cll                         tad 1000 <- Opcode Table
      tad a                           isz 2000
      spa sna ;skip if AC > 0         dca 3000
      jmp done                        ...
      cia                             jmp 5000
      tad m                           ...
Loop, tad b                           cla 7200
      isz m                           cll 7100
      jmp Loop                        spa 7510
Done, dca c                           sna 7450
      hlt                             cia 7041
      jmp Main                        hlt 7402
*0300
a, 11d
b, 12d                                Main 0200 <- User Symbol Table
c, 0                                  Loop  0206
m, 0                                  Done  0211
$Main                                 a     0300
                                      b     0301
                                      c     0302
                                      m     0303



Pass One: First the location counter (LC) is initialized to 0. As each line of code is read and its syntax checked, the location counter is incremented so that it always equals the address of instruction. As user-defined symbols are identifed, they are entered into the user-defined symbol table along with the value of the location counter if the symbol is a label.

Note that the  *nnnn directive changes the value of the location counter.

 
LC = 0
PassOne = True;
While PassOne Do
    begin
    Read Line
    if Line == *<integer> then
        LC = value of <integer>
    else if Label (i.e. <symbol>,) detected then
        begin
        check syntax of Line for either
            Line == <symbol>, <opcode(s)> [i] [<expression>] or
            Line == <symbol>, <expression>
        add (<symbol>, LC) pair to Symbol Table
        increment LC
        end
    else if Line == <symbol> "=" <integer> the
        add (<symbol>, value of <integer>) to Symbol Table
    else if Line == <expression>
        begin
        check syntax of line for either
            Line == <opcode(s)> [i] [<expression>] or
            Line == <expression>
        increment LC
        end
    else if Line == $<symbol> then
        PassOne = False;
    end {PassOne}



Pass Two: On this pass assembler is tranlsated into machine code using table-look up. Note that effective addresses of instructions are encoded into the format of a machine language instruction.

LC = 0;
PassTwo = True
While PassTwo Do
    begin
    <instruction> = 0000;
    Read Line
    if Line is MRI instruction
        begin
        Get <opcode value> from PDP-8_Symbols_Table
   <instruction> = <instruction> or <opcode value>
        if indirect bit then
            <instruction> = <indirection> or 0400
        evaluate <expression> using User_Symbol_Table look up
   if <expression value> is on Page Zero then
            <instruction> = <instruction> OR (<expression value> AND 0177)
        else if <expression value is on Current Page then
            <instruction> = <instruction> OR 0200 OR (<expression value> AND 0177)
        else
            Report "Out of Range Error"
        Deposit <instruction> at LC
        increment LC
        end
    else if Line is I/O Transfer Instruction
        ...
    else if Line is Microinstruction
        ...
    else if Line is <symbol>, <expression> then
        begin
        Evaluate <expression> using User_Symbol_Table look up
        Deposit <expression value> at LC
        increment LC
        end;
    else if Line == *<integer>
        LC = <integer>
    else if Line == $<symbol>
        begin
        Look Up value of <symbol> in User_Symbol_Table
        Set PC = <symbol value>
        PassTwo = False;
    end; {PassTwo}


Return to Comp 255 Home Page