84 lines
2.8 KiB
Markdown
84 lines
2.8 KiB
Markdown
---
|
|
layout: page
|
|
title: DEC PDP-11 BASIC
|
|
permalink: /apps/pdp11/tapes/basic/
|
|
---
|
|
|
|
DEC PDP-11 BASIC
|
|
----------------
|
|
|
|
Try the [DEC BASIC Demo](/devices/pdp11/machine/1120/basic/debugger/).
|
|
|
|
PCjs has archived the following DEC resources:
|
|
|
|
- [BASIC (Single User) Tape Image](DEC-11-AJPB-PB.json)
|
|
- [PDP-11 BASIC PROGRAMMING MANUAL (December 1970)](http://archive.pcjs.org/pubs/dec/pdp11/basic/DEC-11-AJPB-D_PDP-11_BASIC_Programming_Manual_Dec70.pdf)
|
|
|
|
Third-party resources include:
|
|
|
|
- "[PDP-11 Paper Tape BASIC](http://www.avitech.com.au/ptb/ptb.html)", written March 24, 2013
|
|
|
|
---
|
|
|
|
Debugging Notes
|
|
---------------
|
|
|
|
### TRAP Handling
|
|
|
|
One of the first things I noticed when debugging PDP-11 BASIC was its heavy reliance on TRAP instructions.
|
|
For example, `TRAP 000` is used to output the character in R2 to the terminal. Let's take a closer look at how
|
|
its TRAP handler works.
|
|
|
|
First, if you check the table of PDP-11 trap vectors, you'll see that the vector for TRAP instructions is 000034.
|
|
So let's dump the contents of the two-word vector at 000034:
|
|
|
|
>> dw 034 l2
|
|
000034 000100 000000
|
|
|
|
The BASIC TRAP handler is at 000100, and here's that code:
|
|
|
|
>> u 000100
|
|
000100: 011666 000002 MOV @SP,2(SP)
|
|
000104: 162716 000002 SUB #2,@SP
|
|
000110: 013646 MOV @(SP)+,-(SP)
|
|
000112: 006216 ASR @SP
|
|
000114: 103404 BCS 000126
|
|
000116: 006316 ASL @SP
|
|
000120: 062716 073654 ADD #73654,@SP
|
|
000124: 013607 MOV @(SP)+,PC
|
|
|
|
When the code starts, the TRAP instruction has already pushed two words onto the stack:
|
|
|
|
0(SP): previous PC
|
|
2(SP): previous PSW
|
|
|
|
The first instruction, `MOV @SP,2(SP)`, copies the *previous PC* onto the *previous PSW*, which is where we'll eventually want
|
|
*previous PC*, so that the handler can eventually return with a simple `RTS PC`.
|
|
|
|
The next instruction, `SUB #2,@SP`, subtracts 2 from the original *previous PC*, so that it now points to the TRAP instruction.
|
|
|
|
Then `@(SP)+,-(SP)` fetches the TRAP instruction while also "popping" the original *previous PC* and then "pushing" TRAP
|
|
instruction onto the stack, overwriting the original *previous PC*.
|
|
|
|
The next few instructions shift the TRAP right to see if bit 0 is set, and if it is not, then the TRAP instruction is restored
|
|
by shifting it left again, and then a large offset is added to it, transforming the TRAP instruction (which is now known to be
|
|
an *even* value) into a jump table index.
|
|
|
|
The final instruction, `MOV @(SP)+,PC`, moves the address at the jump table index into PC, while also removing the TRAP
|
|
instruction from the stack, leaving only the *previous PC* on the stack.
|
|
|
|
### Comparing to SIMH
|
|
|
|
How to set (and display) a breakpoint in PDPjs:
|
|
|
|
>> bp 016220
|
|
bp 016220 set
|
|
>> bl
|
|
bp 016220
|
|
|
|
How to set (and display) the same breakpoint in SIMH:
|
|
|
|
sim> break -e 016220
|
|
sim> show break
|
|
16220: E
|
|
|