Table of Contents
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
PUSHincrements both the address pointer in the right half ofPand the left hand side counter. If the counter reaches zero, the stack is full. The next call toPUSHwould 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
POPwill 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 morePOPs thanPUSHes 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