Clone
1
Basics
Jali edited this page 2026-10-31 23:59:10 +01:00

Basics

Introduction

In order to get the PDP-10 to work for us, we need to set up the basic function of our programme. Even though this text is meant to document the process of coding for the PDP-10. It is not a manual, so it will assume the reader already knows about the architecture of the machine and the basics of PDP-10 machine language.

In this chapter we will set up the code file, and define some of the generic functions, such as printing text on the terminal.

File Generation

To begin, we create a new file on ITS.

:EMACS SUDOKU 1

If you prefer editing your source code on a more modern machine, with a more sophisticated editor, you can create it on your modern machine, using your preferred editor. In order to transfer the files to the ITS-machine, you can use git-monitor, and create an appropriate .git-monitor_after.sh script in your git repo.

As with other assemblers, PDP-10 assembly uses symbols, that need to be defined before they can be used and the instructions you want to run. The MIDAS-Assembler we use also has a powerful macro language, that allows us to create pseudo instructions, that automate many things, such as calling system functions. This makes MIDAS feel closer to a high-level language instead of an assembler, when it comes to call the operating system. What we need to know are the types of code lines.

A symbol definition begins with a name and an equal sign, followed by a number:

A=1

This will create a symbol A that always references to the value given. To do this, the assembler creates a symbol table, in which the symbol is then stored. In this regard a symbol is similar to a label, just that is does not refer to a memory address, but a constant value.

It is also possible in MIDAS to declare name without creating a symbol in the symbol table. This is done by using the double =:

PDLLEN==30

In this case, the assembler simply replaces the symbolic name with its values, where ever it is used in the code.

A code line consists of three elements:

[LABEL:]    INST <param>,<param>   ;Comment

The label is optional, as is the comment. Everything after a semicolon is treated as comment and ignored by the assembler.

Armed with this knowledge, we can begin coding. Every file begins with a magic-header that tells the assembler, that the file contains assembly code. It comes in the form of a comment, however, it is necessary to add this first line for MIDAS to work. Then the the programme gets a title using the assembler statement TITLE:

;-*-MIDAS-*-
        TITLE    SUDOKU SOLVER

Next we define symbols for the processor registers. Unlike other computers of the time, the PDP-10 does not have fixed purpose registers, such as a distinct accumulator. Therefore all instructions can be used with every register of the CPU. Actually in the original design of the CPU, the registers where located in the first 18 words of RAM, and not part of the CPU itself. This allows the user to address registers to be accessed indirectly through a memory address. Technically, it is not necessary to define symbols for the register addresses, but it makes the code so much mal readable. Normally, the default accumulator is named A, and multiple other registers are defined, starting with B, as well as two index registers, that are used for all instructions that hold an index. We call them X and Y here. And finally, the stack register. The PDP 10 does not come with a predefined stack, or even a built-in stack register, so we have to define one. We use the highest register address, 17, for this purpose. Since register 0 can, for reasons that have to do with the instruction architecture, not be indexed, we leave it out here.

A=1                              ;Define ACs as universial rgisters
B=2                              ;from A to E
C=3
D=4
E=5
X=10                             ;X and Y are used for indexing
Y=11                             ;loops etc.
P=17                             ;Define P as the stack pointer. 

The use of the registers is arbitrary, you can choose them however you like. There is no given order for which register takes which function.

Since the PDP-10 does not have a built-in stack, we need to reserve some memory for it. It makes sense to place this memory at the beginning of the programme, before the code block.

PDLLEN==30                        ;Set the size of the stack to 30 words
PDL:    BLOCK PDLLEN              ;Reserve the stack memory

The label PDL creates an entry in the symbol table, that points to the memory address where the memory area reserved by the BLOCK statement begins. The BLOCK statement is an assembler statement, not a machine instruction. It tells the assembler to reserve a block of multiple words in memory, at the exact point in the assembly image. So our image will begin with a header, then 30 words of space reserved for the stack, and after that comes the code.

Next we need to initialise the stack. This must be the very first instruction in our programme:

START:  MOVE  P,[-PDLLEN,,PDL-1]  ;Initialize the stack

The MOVE instruction will move a data from one place in memory to another. In this case, we move a literal word (defined by the []) into our push down pointer in register P. The stack works like this:

  • It is initialised with the negative of its size (-PDLLEN) in the left half of the word.
  • The right side of the word is loaded with the address of the word before the beginning of our reserved stack. This is important, because the stack operations will first increase the push down pointer and then access the data!
  • Every call to PUSH increments both the address pointer in the right half of P and the left hand side counter. If the counter reaches zero, the stack is full. The next call to PUSH would make it positive, which will automatically raise an exception in the CPU, thus preventing the stack from overflowing into other memory areas. This is a simple and effective method, other CPUs of the time didn't have.
  • Every call to POP will decrease both the left hand side counter, and the address in the right half of the register, freeing space on the stack again. The stack does not have underflow protection, so calling more POPs than PUSHes does not throw an exception! Luckily, this is a much rarer scenario than the overflow.

Keep in mind that, if need be, you could initialise another stack with a different accumulator, and use it independently from the first one.

Der komplette Code sieht dann so aus:

;-*-MIDAS-*-
        TITLE    SUDOKU  SOLVER

A=1                                ;Define ACs as universial rgisters
B=2                                ;from A to E
C=3
D=4
E=5
X=10                               ;X and Y are used for indexing
Y=11                               ;loops etc.
P=17                               ;Define P as the stack pointer. 

PDLLEN==30                         ;Set the size of the stack to 30 words
PDL:    BLOCK  30                  ;Reserve the stack memory

; Here follows some more intitalisation later

START:  MOVE  P,[-PDLLEN,,PDL-1]   ;Intialize the stack