Hello World! Program for PDP-8 Using PAL Assembly Language

(all PDP-8 blog entries can be seen by clicking here)

Time to do something a little harder than adding two numbers together. For this program, I will write HELLO WORLD on the terminal. In most languages this is trivial. In assembler, it takes a bit more work.

First, I want to mention that I used the “Introduction to Programming” book to get this program running. It explains PDP-8 IO well

Click to access IntroToProgramming1969.pdf

I really had fun putting this program together. PDP-8 assembler is pretty easy and you can quickly figure out how to use it. I haven’t written anything in assembler is literally decades, yet this was pretty easy to do.

Before getting into the program here are a couple of interesting items.

C’s ++ Operator and the PDP-8

Ever wonder how the language C came to use ++ to increment a variable? The old DEC computers had an option to auto increment registers which made memory access easier – you would access, say, location 200 via a register and it would autoincrement to 201 for the next access.

It has been my understanding that when C was written (and it was first written for a DEC computer), rather than try to figure out and optimize something like


to use the hardware’s autoincrement ability, they came up with the ++ operator which was a hint to the compiler what was going on and it could more easily make use of autoincrement when a programmer wrote:


The hello world program, below, uses an autoincrement register.

BTW, I should mention I DETEST the use of ++ and NEVER use it in my own C programs. I know, I am the only one.

What is the Point to Octal?

The other thing of interest, well at least to me, is the use of octal for the PDP-8. Very shortly after I started programming professionally on a 16 bit minicomputer, I found it very clumsy to use octal yet that was the normal method, at that time, for describing binary numbers.

So the characters “AB” would fit into 16 bits as 0100000101000010. We would write this in octal as %040502. But you could not look at that octal value and see the octal values for A (%101) and B(%102). I could usually see the right half of %040502 was a B but I would have to do math to figure out the left half.

Years later, hexadecimal became more widespread and that made sense. “AB” in hex is 0x4142. You can quickly look hex 41 up (if you don’t already have it memorized) and see it is an A.

I always wondered why we were forced to use octal in the early days of my career. Then one day it hit me like a bolt of lightening. The old systems’ memory sizes were based on multiples of 6 bits, not 8. the PDP-8 was a 12 bit architecture. The DEC-10 was 36 bits. Octal makes perfect sense in those systems (hence the old SIXBIT character encodings of the DEC-10).

So on the PDP-8, AB (in SIXBIT, not ASCII) is binary 000001 000002 or %0102 which is easy to look at and determine the actual characters.

Hello World Program

OK enough digression. Let’s get on to the program. Here it is:


        *200                    /LOCATE PROGRAM STARTING AT ADDR 200
        AIX1=10                 /SETUP AUTOINDEX REGISTER 1

        CLA                     /CLEAR ACCUMULATOR
        CLL                     /CLEAR AC LINK
                                /THE ADDR OF CHRSTR)
        DCA AIX1                /STORE THAT IN AUTOINDEX REG 1

                                /I USE A NOP JUST TO MAKE IT EASIER TO
                                /INSERT CODE BELOW THE LABEL.
        SNA                     /IF AC IS NOT ZERO, SKIP NEXT INSTRUCTION
        JMP I [7600             /EXIT PROGRAM (BACK TO MONITOR)
        JMS TTYO                /CALL OUTPUT ROUTINE
        JMP LOOP                /REPEAT LOOP

TTYO,   0                       /TTY OUTPUT ROUTINE. THE FIRST WORD OF
                                /A SUBROUTINE MUST BE EMPTY (0) BECAUSE
                                /THE JMS INSTRUCTION INSERTS THE RETURN
                                /ADDR IN THIS WORD.
        TLS                     /WRITE AC TO THE OUTPUT DEVICE (TTY)
        TSF                     /IF TTY IS READY, SKIP NEXT INSTRUCTION.
        JMP .-1                 /TTY IS NOT READY, SO CHECK AGAIN
        CLA                     /CLEAR AC
        JMP I TTYO              /RETURN TO CALLER

CHRSTR, .                       /1ST WORD IS ADDR OF STRING
        110                     /H
        105                     /E
        114                     /L
        114                     /L
        117                     /O
        040                     /
        127                     /W
        117                     /O
        122                     /R
        114                     /L
        104                     /D
        041                     /!
        000                     /<EOT>

This is a pretty straight forward program and I commented every line to help explain what is hapening. The first section initializes everything. AIX1 is the first autoincrement register and will contain the address of the string to print.

The loop simply loads each character from memory into the accumulator and calls the TTYO subroutine to print it.

TAD I AIX1 increments the address in AIX1, then uses that address to load the next character to print from memory.

Calling a subroutine is a bit interesting as there is no return stack. Instead, the first word of the subroutine is left unused. When it is called, the JMS instruction writes the return address into that word. To return, you jump back to that address. NO RECURSION IS POSSIBLE!! Well, not unless you implement your own stack.

Note that to make life simpler, I encoded the HELLO WORLD! string in memory using ASCII NOT SIXBIT.

Normally, to encode a character string into memory you would use the instruction


which could create the string in memory in SIXBIT. For this simple program, it was easier to hand encode the table in ASCII.

As each character is read, it is tested to see if it is zero. If it is, then the program exits.

The TTYO procedure is interesting in as much as you cannot write a character until the terminal is ready. So this subroutine writes a character, then waits until it has been processed before returning control to the caller.

Here is the compile, load, and execution of the program:


Feb 2015 update:

Here is a video someone else created of entering and running this little program:

This entry was posted in c-retro and tagged . Bookmark the permalink.

4 Responses to Hello World! Program for PDP-8 Using PAL Assembly Language

  1. Pingback: Hello, world! | Mainframes and minis and micros, oh my!

  2. Robert Smith says:

    Big Dan, Your post is a few years old, so this may not be of interest to you. I ran your Hello World assembly code on the PiDP-8 and it worked fine. But the code you listed for adding 3 and 4 did not work as expected. Instead of returning to OS/8, OS/8 hung up, although with CRTL-E I could get back to SimH. The only reason I could see this might happen is the instruction JMP I [7600, but that same code works fine in the Hello World code. Any ideas?
    Thanks for posting these great instructions on using PAL and for any help you can provide.

    Bob Smith

    • Dan TheMan says:

      Hmmm, it’s been a long time, but I redid the 3+4 example and ran it as I documented it, and it worked for me:

      .LOAD PROG1


      HALT instruction, PC: 00204 (JMP I 177)
      sim> e 200-206
      200: 7200
      201: 1205
      202: 1206
      203: 7402
      204: 5577
      205: 0003
      206: 0004
      sim> e ac
      AC: 0007
      sim> go


      does your memory dump look like mine (above). If so, my only guess is the address in 7600 is wrong for you.

      I have 4207:
      sim> e 7600
      7600: 4207

      The instruction jmp i [7600 should (if I’m getting this right), jump to the address contained in 7600. In other words it will jump to addr 4207.

      I would expect your emulator to be exactly the same and want to jump to the same location. If this doesn’t contain 4207, maybe something is corrupting memory (this program is so simple I don’t see how though).

      The other thing you could do is put a hlt instruction before the jmp i instruction in the hello world program and see what 7600 contains in a program known to work.

      This isn’t much, but perhaps it will help you figure out the problem. Good luck!

      • Robert Smith says:

        Big Dan,
        You were right, the problem was with the HLT command, not the JMP I [7600. The 4+3=7 code stopped at HLT, but simply pressing the Start switch on my PiDP-8 console re-started the CPU and the JMP command returned me to OS/8. Sorry to bother you with this, but Thanks!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.