Add the basics
+175
@@ -0,0 +1,175 @@
|
||||
# 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](https://gitea.orca-central.de/jali/PiDP10Services), 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:
|
||||
|
||||
```asm
|
||||
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:
|
||||
|
||||
```asm
|
||||
[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`:
|
||||
|
||||
```asm
|
||||
;-*-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.
|
||||
|
||||
```asm
|
||||
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.
|
||||
|
||||
```asm
|
||||
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:
|
||||
|
||||
```asm
|
||||
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 `POP`s than
|
||||
`PUSH`es 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:
|
||||
|
||||
```asm
|
||||
;-*-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
|
||||
```
|
||||
Reference in New Issue
Block a user