Setting up the Stack Pointer
As I was developing the code for the PDP-11 Line Clock post yesterday, I ran into an issue where the interrupt servicing wasn't working properly. Eventually I tracked this down to the fact that the stack pointer had a value of zero, meaning that pushing values onto the stack wasn't working. As in interim fix I picked a memory address of 2000 and set the stack pointer to this value. This made the example code in the line clock post work properly but it is a bit unsatisfactory because I didn't understand why the stack wasn't working the way I expected. Now I do, so I am writing an update to clarify my new understanding and provide updated code.
It was my understanding that the stack immediately precedes the first instruction of the main program, which is at memory address 1000. It turns out, however, that the programmer needs to manually assign a value to the stack pointer in order to indicate the location of the stack.
When values are pushed onto the stack, for example when an interrupt is being serviced, the stack pointer is decremented and then the value is placed into the memory address pointed to by the new value of the stack pointer. Therefore, the first instruction of any program that needs to use the stack must set the stack pointer to the appropriate value.
Since the stack pointer will be decremented before use, the value of 1000 should be used as an initial value. I have updated the line clock sample code to reflect this change:
set cpu 11/70,4M ;set realcons=localhost set realcons panel=11/70 set realcons interval=8 set realcons connected set clk 50HZ ; line clock interrupt vector D 100 001200 D 102 000340 ; main application D 1000 MOV #1000, SP D 1004 MOV #100, @#177546 D 1012 NOP D 1014 CMP R0, #62 D 1020 BNE 1012 D 1022 MOV #0, R0 D 1026 INC R1 D 1030 CMP R1, #200 D 1034 BEQ 1044 D 1036 MOV R1, #177570 D 1042 BR 1012 D 1044 MOV #0, R1 D 1050 BR 1012 ; line clock interrupt handler D 1200 INC R0 D 1202 RTI RESET ALL SET CPU IDLE ; CPU priority is 5 D PSW 000240 D PC 001000
The key change to this code is the addition of the line:
D 1000 MOV #1000, SP
This moves the value 1000 into the stack pointer. Note that the first value to be placed on the stack will be stored at memory address 776, because the stack pointer will be decremented before it is used.
Other minor changes;
The memory addresses of the other instructions have been updated to accommodate the new instruction at the beginning of the code.
The "D SP 002000" instruction that loads the value 2000 into the stack pointer, which was my temporary fix from yesterday, is removed.
Apart from that the code works exactly the same as the line clock sample code from the post yesterday.