Jump to content
  • entries
    45
  • comments
    10
  • views
    10,381

APX Pascal Architecture, part one


Atari_Ace

1,051 views

Bill Lange has been blogging about Atari Pascal since early February at https://insideataripascal.blogspot.com/, so here's my own small contribution after spending an afternoon poking around in APX Pascal and looking for the core interpreter.

If we look at the PASCAL runtime on the APX Pascal disk, it's a simple enough image. It loads itself from disk to $3300-$59ff and then starts running from $3300. So what does that initial bootstrap code do? Here's the preamble:

3300: A2 00             LDX #0
3302: A9 0C             LDA #$0C
3304: 9D 42 03          STA ICCMD,X
3307: 20 56 E4          JSR CIOV
330A: AD A7 33          LDA $33A7
330D: 85 F0             STA $F0
330F: AD A8 33          LDA $33A7+1
3312: 85 F1             STA $F0+1
3314: AD A9 33          LDA $33A9
3317: 85 F2             STA $F2
3319: AD AA 33          LDA $33A9+1
331C: 85 F3             STA $F2+1
331E: AD AB 33          LDA $33AB
3321: 85 F4             STA $F4
3323: AD AC 33          LDA $33AB+1
3326: 85 F5             STA $F4+1
3328: 20 73 33          JSR $3373

This code closes IOCB #0, then sets up $F0-F5 using values at $33A7-$33AC and then calls a subroutine. Those values are:

33A7: 00 3A             .WORD $3A00 ; source
33A9: 00 A0             .WORD $A000 ; destination
33AB: 00 20             .WORD $2000 ; count
33AD: 00 1D             .WORD $1D00

And the subroutine looks like:

3373: A0 00             LDY #0
3375: B1 F0             LDA ($F0),Y
3377: 91 F2             STA ($F2),Y
3379: A5 F0             LDA $F0
337B: 18                CLC
337C: 69 01             ADC #1
337E: 85 F0             STA $F0
3380: A5 F1             LDA $F0+1
3382: 69 00             ADC #0
3384: 85 F1             STA $F0+1
3386: A5 F2             LDA $F2
3388: 18                CLC
3389: 69 01             ADC #1
338B: 85 F2             STA $F2
338D: A5 F3             LDA $F2+1
338F: 69 00             ADC #0
3391: 85 F3             STA $F2+1
3393: A5 F4             LDA $F4
3395: 38                SEC
3396: E9 01             SBC #1
3398: 85 F4             STA $F4
339A: A5 F5             LDA $F4+1
339C: E9 00             SBC #0
339E: 85 F5             STA $F4+1
33A0: A5 F4             LDA $F4
33A2: 05 F5             ORA $F4+1
33A4: D0 CF             BNE $3375
33A6: 60                RTS

This is just a block copy routine, which relocates all the code at $3A00-$59FF to $A000-$BFFF. This block of code (which is most of the PASCAL executable), is the actual runtime. A simpler way to do this would have been to use a multi-segment load file, but this works well enough. $A000-$BFFF is the cartridge address space for an 8k cart, so clearly this was intended at one point to be shipped as a cartridge.

What happens next:

332B: AD AD 33          LDA $33AD
332E: 85 80             STA $80
3330: AD AE 33          LDA $33AE
3333: 85 81             STA $81
3335: A9 00             LDA #0
3337: 85 82             STA $82
3339: 85 83             STA $83
333B: 20 00 A2          JSR $A200
...
A200: 4C 12 B8          JMP $B812

This copies the word in $33AD ($1D00) to $80,$81 and zeros $82,$83 before invoking a routine at $A200, which vectors to $B812.

That routine does several things, including:

B834: A5 80             LDA $80
B836: 85 D0             STA $D0
B838: A5 81             LDA $81
B83A: 85 D1             STA $D1
B83C: AD 78 A2          LDA $A278
B83F: 85 CE             STA $CE
B841: AD 79 A2          LDA $A278+1
B844: 85 CF             STA $CE+1
B846: AD 7A A2          LDA $A27A
B849: 85 D2             STA $D2
B84B: AD 7B A2          LDA $A27A+1
B84E: 85 D3             STA $D2+1
B850: 20 6B AE          JSR $AE6B

where:

A278: 00 A0             .WORD $A000
A27A: 78 02             .WORD $0278

So we move the word at $80,$81 ($1D00) to $D0,D1, and set $CE,$CF to $A000 and $D2,D3 to $0278, before calling another block copier.

AE6B: A0 00             LDY #0
AE6D: A6 D3             LDX $D3
AE6F: F0 0E             BEQ $AE7F
AE71: B1 CE             LDA ($CE),Y
AE73: 91 D0             STA ($D0),Y
AE75: C8                INY
AE76: D0 F9             BNE $AE71
AE78: E6 CF             INC $CF
AE7A: E6 D1             INC $D1
AE7C: CA                DEX
AE7D: D0 F2             BNE $AE71
AE7F: A6 D2             LDX $D2
AE81: F0 08             BEQ $AE8B
AE83: B1 CE             LDA ($CE),Y
AE85: 91 D0             STA ($D0),Y
AE87: C8                INY
AE88: CA                DEX
AE89: D0 F8             BNE $AE83
AE8B: 60                RTS

So we relocate the first $0278 bytes of the "cartridge" to address $1D00-$1F77. The first $200 bytes are just a series of addresses (more on those soon), the next $78 bytes are a set of JMP vectors, e.g.

1F00: 4C 12 B8          JMP $B812
1F03: 4C B1 AB          JMP $ABB1
1F06: 4C B6 AB          JMP $ABB6
...
1F72: 4C 87 B8          JMP $B887
1F75: 4C 5F BC          JMP $BC5F

After we return from this the code continues with:

B853: A5 80             LDA $80
B855: 85 82             STA $82
B857: A5 81             LDA $81
B859: 85 83             STA $83
B85B: E6 83             INC $83
B85D: E6 83             INC $83
B85F: 20 EB B9          JSR $B9EB

The word at $80,$81 gets moved to $82,$83 and incremented by $200, so the word at $82,$83 is now $1F00. The subroutine called looks like:

B9EB: A2 21             LDX #$21
B9ED: A0 00             LDY #0
B9EF: B9 CA B9          LDA $B9CA,Y
B9F2: 99 92 00          STA $0092,Y
B9F5: C8                INY
B9F6: CA                DEX
B9F7: D0 F6             BNE $B9EF
B9F9: A5 81             LDA $81
B9FB: 85 AD             STA $AD
B9FD: 85 B2             STA $B2
B9FF: E6 B2             INC $B2
BA01: 60                RTS

This copies the code at $B9CA into page zero, and patches the value at $81 ($1D) into $AD and the $B2 and then increments $B2, so we end up with the following:

0092: 18                CLC
0093: 65 A4             ADC $A4
0095: 85 A4             STA $A4
0097: 90 0A             BCC $00A3
0099: E6 A5             INC $A5
009B: B0 06             BCS $00A3
009D: E6 A4             INC $A4
009F: D0 02             BNE $00A3
00A1: E6 A5             INC $A5
00A3: AD FF FF          LDA $FFFF
00A6: 0A                ASL A
00A7: B0 05             BCS $00AE
00A9: 85 AC             STA $AC
00AB: 6C 00 1D          JMP ($1D00)
00AE: 85 B1             STA $B1
00B0: 6C 00 1E          JMP ($1E00)

This is the core of the Pascal interpreter, similar to the Forth NEXT routine I discussed in http://atariage.com/forums/blog/734/entry-15007-dealer-demo-part-4-some-forth-at-last/. It has three parts, and self-modifies its code as it runs. If you enter at $0092, it increments the current p-code pointer (located at $A4,$A5) by the accumulator. If you enter at $009D, it increments the current p-code pointer by 1. In both cases, it then proceeds to the third part (which can be called directly as well) which reads the p-code value, multiplies the value by two and then patches one of two jump vectors with that value depending on whether the multiply overflowed or not. This allows us to dispatch all 256 possible p-codes, and each code will then jump back into this routine, keeping the interpreter running forever.

Of course, we haven't actually gotten into the interpreter yet, only set it up. We'll discuss that in a future post, but we've made decent progress towards separating the runtime from the monitor. In particular, it's clear we could move the 8K runtime in $A000-$BFFF into a cartridge image and modify the PASCAL file to skip the initial relocation and rely on the cartridge. That focuses our attention on the remaining 1.8K of PASCAL to isolate the code that sets up the runtime and loads the MON program. Hopefully we can adapt that code to load another program directly, and thus produce binaries that can run without loading the monitor.
 

  • Like 5

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...