PDP-8
PDP-8のアセンブリ言語プログラムを例として示す。以下のコード例はPAL-IIIアセンブラによる。
単に2つの数を比較するだけでどれだけのコードが必要となるかを示したコード断片。
/Compare numbers in memory at OPD1 and OPD2
CLA CLL     /Must start with 0 in AC and link
TAD OPD1    /Load first operand into AC (by adding it to 0); link is still clear
CIA         /Complement, then increment AC, negating it
TAD OPD2    /AC now has OPD2-OPD1; if OPD2≥OPD1, sum overflows and link is set
SZL         /Skip if link is clear
JMP OP2GT   /Jump somewhere in the case that OPD2≥OPD1;
/Otherwise, fall through to code below.
見ての通り、PDP-8の典型的なプログラムは作者が意図したアルゴリズムよりも低レベルな機構に集中する傾向がある。また、可読性を損なうもう1つの問題として、条件分岐部分のコーディングがある。上の例で判るとおり条件判断命令(JMP命令をスキップしている命令)は、注目している条件とは反対の条件判断をしなければならない。
PDP-8で "Hello, world" をテレタイプ端末に出力するアセンブリ言語のプログラム。
*10                   / Set current assembly origin to address 10,
STPTR,    STRNG-1     / An auto-increment register (one of eight at 10-17)
*200                  / Set current assembly origin to program text area
HELLO,  CLA CLL       / Clear AC and Link again (needed when we loop back from tls)
TAD I Z STPTR / Get next character, indirect via PRE-auto-increment address from the zero page
SNA           / Skip if non-zero (not end of string)
HLT           / Else halt on zero (end of string)
TLS           / Output the character in the AC to the teleprinter
TSF           / Skip if teleprinter ready for character
JMP .-1       / Else jump back and try again
JMP HELLO     / Jump back for the next character
STRNG,  310           / H
345           / e
354           / l
354           / l
357           / o
254           /,
240           / (space)
367           / w
357           / o
362           / r
354           / l
344           / d
241           / !
0             / End of string
$HELLO                /DEFAULT TERMINATOR
PDP-8では汎用スタックをアーキテクチャ上サポートしていないため、サブルーチンを呼び出すときや割り込みが発生したときのコンテキスト(プログラムカウンタやACなどのレジスタ値)をセーブする方法が確立されていない。その代わり、リターンアドレスとしてのプログラムカウンタ値がターゲットサブルーチンの先頭ワードに格納される。従って、間接ジャンプ命令でサブルーチンから戻ることができる。
以下のプログラムはサブルーチンを使うように改造した "Hello world" である。JMS命令でサブルーチンに飛び込むと、OUT1:の位置にある0が書き換えられる。
*200                    / Set assembly origin (load address)
HELLO,  CLA CLL         / Clear the AC and the Link bit
TAD (DATA-1)    / Point AC just *BEFORE* the data (accounting for later pre-increment behavior)
DCA 10          / Put that into one of ten auto-pre-increment memory locations
LOOP,   TAD I 10        / Pre-increment mem location 10, fetch indirect to get the next character of our message
SNA             / Skip on non-zero AC
HLT             / Else halt at end of message
JMS OUT1        / Write out one character
JMP LOOP        / And loop back for more
OUT1,   0               / Will be replaced by caller's updated PC
TSF             / Skip if printer ready
JMP .-1         / Wait for flag
TLS             / Send the character in the AC
CLA CLL         / Clear AC and Link for next pass
JMP I OUT1      / Return to caller
DATA,  "H               / A well-known message
"e               /
"l               / NOTE:
"l               /
"o               /   Strings in PAL-8 and PAL-III were "sixbit"
",               /   To use ASCII, we'll have to spell that out, character by character
"                /
"w               /
"o               /
"r               /
"l               /
"d               /
"!               /
015              /
012              /
0                / Mark the end of our .ASCIZ string ('cause .ASCIZ hadn't been invented yet!)
リエントラント性や再帰呼び出しを実現しようとすると、プログラマは自分でコールスタックを用意し、リターンアドレスをスタックにセーブしなければならない。また、ROMを使うのも困難である(プログラムが書き換え可能でないとサブルーチンを使えないため)。ROMにプログラムを格納する場合、以下のような回避方法があった。
RAMも一部内蔵したROMを使い、各ワードにフラグを設定してRAMを代替に使用するかどうかを指定する(要するに非常に特殊なメモリを使用する)。
サブルーチンを全く使わない。またはJMS命令の代わりに次のようなコードを使い、書き換え可能なメモリにリターンアドレスを置く。
JUMPL, DCA TEMP         / Deposit the accumulator in some temporary location
TAD JUMPL+3      / Load the return address into the accumulator: hard coded
JMP SUBRO        / Go to the subroutine, and have it handle jumping back
JUMPL+4          / Return address
JMS命令を使用するとデバッグが難しくなる。例えば、リターンアドレスの書き換えによって無限ループに陥ることもあるし、サブルーチンのアドレスを間違うとサブルーチンの先頭ではないワードをリターンアドレスで書き換えてしまうこともある。こういった誤りは実行してみないとわからないこともある。
PDP-8 はスタックをハードウェアでサポートしていないが、ソフトウェアでの実装は可能である。以下はPUSHとPOPというサブルーチンの実装例だが、単純化するためスタックのオーバーフローやアンダーフローはチェックしていない。
PUSH, 0
DCA DATA
CLA CMA     / -1
TAD SP
DCA SP
TAD DATA
DCA I SP
JMP I PUSH     /Return
POP,  0
CLA CLL
TAD I SP
ISZ SP
JMP I POP
DATA, 0
SP, 0
以下は、"Hello World" を "OUT" というサブルーチンとこのスタックを使って実装したものである。
*200
MAIN,  CLA CLL         /Set the message pointer
TAD (MESSG      /To the beginning of the message (literal)
DCA SP
LOOP,  JMS POP
SNA             /Stop execution if zero
JMS OUT         /Otherwise, output a character
JMP LOOP
MESSG, "H
"e
"l
"l
"o
",
"
"w
"o
"r
"l
"d
"!
OUT,    0               / Will be replaced by caller's updated PC
TSF             / Skip if printer ready
JMP .-1         / Wait for flag
TLS             / Send the character in the AC
CLA CLL         / Clear AC and Link for next pass
JMP I OUT      / Return to caller
PDP-8の入出力バスには1本の割り込みラインがあり、割り込みが発生すると割り込み不可状態となって 0番地のサブルーチンを呼び出すように動作する。サブルーチンと同様、割り込みもリエントラント性は無く、割り込みを不可とした状態で割り込みハンドラが動作し、JMP I 0 命令で割り込まれた箇所に戻るとき割り込み可とする。
I/Oバスの割り込みラインが1本なので、割り込み発生源が何かということは分からない。そのため、割り込み処理ルーチンは順に各デバイスのステータスをポーリングしてチェックし、割り込み元を識別した。この処理は条件スキップ命令が並ぶので "skip chain" と呼ばれた。skip chain の最後まで実行しても割り込み元が見つからないことは珍しいことではなかった。相対的な割り込みの優先順位は skip chain でチェックする順番で決定され、先に見つかった割り込みの処理が優先される。