• Please review our updated Terms and Rules here

Tektronix 4052 DDT

Monty:

I have done some work on the 4051 BASIC ROMs, if you have some ROM Calls you are chasing, I may have decoded them.

Vermithrax
 
Monty:

I have done some work on the 4051 BASIC ROMs, if you have some ROM Calls you are chasing, I may have decoded them.

Vermithrax
Thank you!

I have been making progress with identifying 4051 DDT disassembly code and memory references - using the 4051 Emulator to run DDT v51.8 from a 4051 "DEBUG" ROM and cross-referencing that disassembly with the 4051 Assembler documentation and the 4051 microfiche BASIC ROM source code.

I have been working backwards from MFFFF through the memory references and ZFEB0 code references and gotten this far with adding comments on the following references in the DDT DEBUG option ROM disassembly.

I feel good about these references being used in the DDT code, based on the DDT commands listed in the 4051 Assembler document.

Code:
Z83B8   EQU     $83B8 'PRTERR PRINT ERROR - THE ERROR MESSAGE WRITER
M878C   EQU     $878C '4051 Y-AXIS D/A/MAGTAPE PIA
M878D   EQU     $878D ' "
M878E   EQU     $878E ' "
M878F   EQU     $878F ' "
M8794   EQU     $8794 '4051 X-AXIS D/A/MAGTAPE PIA
M8796   EQU     $8796 ' "
M87A9   EQU     $87A9 '4051 KEYBOARD/STATUS LIGHTS  PIA "
M87AA   EQU     $87AA ' "
M87AB   EQU     $87AB ' "
M87C0   EQU     $87C0 '4051 BANK SWITCH PIA
M87C6   EQU     $87C6 '4051 OPTION 01 COMM
M87C7   EQU     $87C7 ' "
M87C8   EQU     $87C8 '4051 XPC2 PIA
M87C9   EQU     $87C9 ' "
M87CA   EQU     $87CA ' "
M87CB   EQU     $87CB ' "
M88D0   EQU     $88D0 'DEBUG ROM IN BANK SWITCH AREA - contains 0086 (ONE BYTE BEFORE ZBEGIN IN DEBUG ROM)
MA000   EQU     $A000 'contains 0005 (DIS)
ZA9D4   EQU     $A9D4 'one byte IN FRONT OF A9D5; SET BANK REGISTER, disassembly shows IT IS 4F=CLR A
ZAA3E   EQU     $AA3E 'A5X  - ADD 5 TO X REGISTER
ZAA46   EQU     $AA46 'D11X - SUBTRACT 11 FROM X REGISTER
ZB6EB   EQU     $B6EB 'PSHFPN - PUSH FP NUMBER ONTO STACK
ZB853   EQU     $B853 'FPNASC - REDUCE A FP NUMBER TO A FRACTION FROM 0.1 TO 1.0 FOR CONVERSION TO ASCII LATER
ZC64A   EQU     $C64A 'KBQOUT - FETCH A KEY FROM TYPE-AHEAD QUEUE
ZC65C   EQU     $C65C 'CIDLE  - DISPLAYS THE CURSOR WHILE WAITING FOR KEYBOARD I/O TO COME TO A LOGICAL END
ZC6EF   EQU     $C6EF 'LF (microfiche+DIS) - CHECK WHETHER LINEFEED WILL RESULT IN PAGE FULL - 4051 Microfiche ADBANK-DIMSUB pdf pgs 164-165, CRTDRV pg 2
ZCBBF   EQU     $CBBF 'CRTRST - RESTORE THE DISPLAY AFTER A MAGTAPE OPERATION
ZCBEE   EQU     $CBEE 'PCHAR  - SEND SINGLE CHAR TO DISPLAY
ZD607   EQU     $D607 'ROUND (microfiche+DIS) - PREPARES DECIMAL BCD STRING FOR OUTPUT - MTCTL-RAMMAP pdf pg 118
ZDBC8   EQU     $DBC8 'NFR8 (microfiche+DIS) - SLOW SEARCH FOR FILE MARK - MTCTL pdf pg 176
ZDBDD   EQU     $DBDD 'MTAFIN - LOCATE AND OPEN A MAGTAPE FILE
ZDCA8   EQU     $DCA8 'MTREAD - READ A MAGTAPE FILE
ZDD3F   EQU     $DD3F 'MTWRIT - WRITE A MAGTAPE BUFFER
ZE00C   EQU     $E00C 'INITMT (microfiche+DIS) - INITIALIZE MAGTAPE PIAS - MTCTL pdf pg 197
ME42C   EQU     $E42C 'contains D01F (DIS)
MEFB8   EQU     $EFB8 'contains 967C (DIS)
ZF2C2   EQU     $F2C2 'FULSCN - BLINKING 'F' WAITING FOR PAGE KEY
ZF36F   EQU     $F36F 'GENCUR - GENERATE BLINKING CURSOR
ZFB90   EQU     $FB90 'MTDRV  - MAGTAPE HARDWARE CONTROL DRIVER
ZFE81   EQU     $FE81 'BAKARS - MAGTAPE ROUTINE TO BACK UP ONE PHYSICAL RECORD - 4051 ASSEMBLER pdf pg 31
ZFEB0   EQU     $FEB0 'DELY1S - WAIT SOME TIME IN 40usec INCREMENTS
MFF2C   EQU     $FF2C 'contains 879B
MFFF8   EQU     $FFF8 'contains EFB8 'TRAPS  - BASE ADDRESS FOR SYSTEM TRAPS - 4051 ASSEMBLER pdf pg 78
MFFFA   EQU     $FFFA 'contains B2CE
MFFFC   EQU     $FFFC 'contains FDBC
MFFFF   EQU     $FFFF 'contains 4B, FFFE contains BC4B

The 4051 DEBUG option ROM loads DDT into RAM in a string variable DIMensioned to length 5632 bytes as shown in this 4051 Emulator screenshot:

4051 DDT is loaded from DEBUG ROM into A$.png

I got this information on how to access the 4051 DEBUG ROM with DDT and the 4051 Enhanced BASIC commands in an email from Micheal D Cranford - author of the 4051 Fast Graphics ROM, which was used by the 4050 firmware team to develop the 4052R12 Enhanced Graphics ROM Pack. The R12 demo tape files I recovered and posted were created by MDC for his Fast Graphics ROM. MDC also created the 4051 MAXIROM Pack and 4051 RAMPACK for the 4051 that had been offered by VintageTek museum a couple of years ago.

The major difference between the 4051 Fast Graphics ROM Pack and 4052R12 Graphics Enhancement ROM Pack was the change of the Fast Graphics ROM Pack MUZAKT command to MUSIC in the 4052R12. I accommodate that difference in a couple of my latest programs by differentiating whether the program is running on a 4051 and using MUZAKT as the CALL versus all the 4052/4054 will use MUSIC. Micheal designed his 4051 RAMPACK to support accessing large ASCII string variables (~28KB) differently than 4050 BASIC. I finally worked around the 4050 BASIC limitation by using BINARY strings instead of ASCII strings - which support strings up to 8KB on both 4051 and 4052/4054. My programs with images larger than 8KB R12 strings, simply break the image into BINARY chunks that can be displayed separately, and then the next 'chunk' or block is then loaded from the Flash Drive until the "|EOG|" string is read. In fact most of my R12 programs use much smaller strings - down to 256 bytes in size to smooth the display of large images to minimize the GPIB transfer delay affect of larger GPIB block sizes.

Examining my disassembly of the 4051 DEBUG ROM, it appears to not only relocate DDT v51.8 to RAM, but also does a couple of checks to make sure the DEBUG ROM is bank switched into 8800h and the 4051 BASIC ROM is also present.

My f9dasm disassembly of the DEBUG ROM has not been edited to properly ignore disassembly of data sections like the table with 6800 opcodes - so there are a lot of memory references and code references in those data areas based on f9dasm attempting to disassemble those data sections that I need to remove from the list of EQU statements and relabel the bytes as FCB.

I am working to correct those references now.

My plan for a 4052A/4054A DDT is to create a 4052 DEBUG ROM with ROM references updated with 4052 BASIC ROM entry points from the 4052A Assembler document.

I do see a CALL "EXEC" command in the 4052 v5.1 ROM, however when I type CALL "EXEC",A$ into my 4052 I get a parameter error. I would bet the 4052/4054 CALL "EXEC" is more similar to the 4051 CALL "EXEC" which used a short LOADER string that had 16 7-bit ASCII HEX characters 0-? for the loader as the original 4052/4054 BASIC was restricted to only support 7-bit ASCII characters - just like the 4051.

The A-Series BASIC added 8-bit ASCII character support and used 8-bit ASCII for CALL "EXEC",code$,rel$ parameters. I do think the 4052A Assembler documentation of the BASIC ROM entry points will also work on the 4052/4054 since most of the 4052 option ROMs work in both my 4052 and 4054A. Only the 4052R14 and 4052R14-1A GPIB Enhancement option ROMs are specifically marked for 4052 or 4052A -which makes sense as the A-Series GPIB hardware was based on the TI9914 GPIB IC and the original 4052/4054 GPIB was the same discrete logic design as the 4051.
 
Last edited:
Monty:

I took your text file and looked for addresses in the 8700 - FFFF range.
Your list is pretty complete, found a couple of entries that I could add.

Your first entry (PRTERR) helped me fill in some of my own 4051 ROM disassembly.

Vermithrax
 

Attachments

Monty:

I took your text file and looked for addresses in the 8700 - FFFF range.
Your list is pretty complete, found a couple of entries that I could add.

Your first entry (PRTERR) helped me fill in some of my own 4051 ROM disassembly.

Vermithrax
I like your spreadsheet.

Looks like cut and paste errors on these two lines:

M8796EQU$8794"* PIA_DDRB_DATA
M8797EQU$8795"* PIA_U565_CRB
 
I restarted the 4051 Emulator to clear all memory and loaded DEBUG with my BASIC program and inserted PRI @32,26:3 to attempt to change the environment setting for FULL SCREEN to COPY then PAGE, but I suspect that was setting was overwritten when DDT ran. I was hoping to automatically capture the entire DDT disassembly with a single DDT slash command.

Here is my 4051 BASIC listing to run DDT (lines 100-130), then when I quit DDT with F5 it returns to the program line 140 and does a memory dump for a block of RAM near the DDT version message string.

Code:
1 REMARK  4051 DDT 51.8 - loaded from MAXIROM option ROM
2 REM     works in 4051 with MAXIROM and 4051 Emulator
100 INIT
110 PAGE
120 DIM D$(5632),A$(2)
130 CALL "DEBUG",D$
140 PRINT "USBELnow in BASIC !USwith CALL ""PEEK"" and ""POKE"" !"  (first two control chr are US and BEL, third is US)
150 PRINT "US09A9:  ";                                              (US control char for new line)
160 FOR I=2473 TO 2473+15
170 CALL "DECHEX",I,B$
180 CALL "PEEK",B$,A$
190 IF INT(I/2)=I/2 THEN 220
200 PRINT A$;" ";
210 GO TO 230
220 PRINT A$;
230 NEXT I
240 PRINT "   ";
250 FOR I=2473 TO 2473+15
260 CALL "DECHEX",I,B$
270 CALL "PEEK",B$,A$
280 CALL "HEXDEC",A$,A
290 IF A<32 OR A>127 THEN 330
300 A$=CHR(A)
310 PRINT A$;
320 GO TO 340
330 PRINT ".";
340 NEXT I
350 PRINT "Again (Y)?";
360 INPUT A$
370 IF A$<>"Y" THEN 400
380 FIND@5:1
390 OLD@5:
400 END

So I manually captured DDT disassembling itself starting at its entry point at 0940h after resetting the emulator. I couldn't get the DDT / command to display but 3 1/2 pages or so of doubled lines of disassembly, so I would manually reenter a disassembly command on the first line on that partial page and copied starting with that page.

I then combined all those disassembly screenshots into one pdf with Acrobat and OCRed the whole thing.

I am now editing the OCR output to make it single line of disassembly and fixing a couple of OCR errors - and moving the first column of address/byte to the last column and marking it as a comment. Then I will attempt to use A09 to assemble the result and compare that to a DDT dump of the code in RAM - which is in the A$ memory location.

I see the CC34 in my new OCR output at 1E7D (with DDT 0940 start address) - but when I dumped that area again - I see different data. I suspect that area is a DDT stack.
 
Last edited:
Monty:

Good catch, I made those errors in my source so I fixed them there as well.

Thanks,

Vermithrax
 
I found a latent bug in the 4051 DEBUG (DDT) ROM while reformatting the DDT disassembly opcode table:

I found a "BLO" opcode line in the table - there is no 6800 BLO opcode.
But this bug is latent as I expect the disassembly code to search the table from the beginning, and the table is organized alphabetically based on mnemonic spelling.
Opcode 25h is BCS, which would be found before BLO.

I decided to spend the time manually reorganizing the f9dasm disassembly of the table into six bytes per line per @daver2 's disassembly comments for the Board Bucket DDT ROM.

This format will be easier to add the 4052/4054 new opcodes and the 4052A/4054A additional new opcodes to a 4052 DDT.

But I will need to do more digging into the nine operand types.

The 4052A Assembler BASIC program should also support the nine operand types as it assembles both 6800 opcodes and all the added 4052A opcodes.

Code:
; 6800 OPCODE TABLE - see Dave Roberts ddt_der.txt disassembly comments for 6800 Board Bucket DDT below
;
; * The first byte appears to be the 'base' opcode for the mnemonic. It is also the 'compare' byte for disassembly.
; * The second byte is a 'mask' byte for disassembly.
; * The next three bytes are the 6800 mnemonic.
; * The next byte appears to be an operand 'type' as follows:
; *
; * 1 e.g. 'ABA'
; * 2 e.g. 'BCC'
; * 3 e.g. 'ASL'
; * 4 e.g. 'ADC'
; * 5 e.g. 'STA'
; * 6 e.g. 'CPX'
; * 7 e.g. 'JMP'
; * 8 e.g. 'PSH'
; * 9 e.g. 'STS'
; *

        FCB     $1B,$FF,$41,$42,$41,$01  ;0B98: 1B FF 'ABA' 01 '..ABA.'
        FCB     $89,$8F,$41,$44,$43,$04  ;0B9E: 89 8F 'ADC' 04 '..ADC.'
        FCB     $8B,$8F,$41,$44,$44,$04  ;0BA4: 8B 8F 'ADD' 04 '..ADD.'
        FCB     $84,$8F,$41,$4E,$44,$41  ;0BAA: 84 8F 'AND' 04 '..AND.'
        FCB     $48,$CF,$41,$53,$4C,$03  ;0BB0: 48 CF 'ASL' 03 '..ASL.'
        FCB     $47,$CF,$41,$53,$52,$03  ;0BB6: 47 CF 'ASR' 03 '..ASR.'
        FCB     $24,$FF,$42,$43,$43,$02  ;0BBC: 24 FF 'BCC' 02 '..BCC.'
        FCB     $25,$FF,$42,$43,$53,$02  ;0BC2: 25 FF 'BCS' 02 '..BCS.'
        FCB     $27,$FF,$42,$45,$51,$02  ;0BC8: 27 FF 'BEQ' 02 '..BEQ.'
        FCB     $2C,$FF,$42,$47,$45,$02  ;0BCE: 2C FF 'BGE' 02 '..BGE.'
        FCB     $2E,$FF,$42,$47,$54,$02  ;0BD4: 2E FF 'BGT' 02 '..BGT.'
        FCB     $22,$FF,$42,$48,$49,$02  ;0BDA: 22 FF 'BHI' 02 '..BHI.'
        FCB     $24,$FF,$42,$48,$53,$02  ;0BE0: 24 FF 'BHS' 02 '..BHS.'
        FCB     $85,$8F,$42,$49,$54,$04  ;0BE6: 85 8F 'BIT' 04 '..BIT.'
        FCB     $2F,$FF,$42,$4C,$45,$02  ;0BEC: 2F FF 'BLE' 02 '..BLE.'
        FCB     $25,$FF,$42,$4C,$4F,$02  ;0BF2: 25 FF 'BLO' 02 '..BLO.' ? opcode 25 is BCS - THIS IS A MISTAKE, BUT LIKELY WAS NOT CAUGHT BECAUSE BCS IS FOUND FIRST?
        FCB     $23,$FF,$42,$4C,$53,$02  ;0BF8: 23 FF 'BLS' 02 '..BLS.'
        FCB     $2D,$FF,$42,$4C,$54,$02  ;0BFE: 2D FF 'BLT' 02 '..BLT.'
        FCB     $2B,$FF,$42,$4D,$49,$02  ;0C04: 2B FF 'BMI' 02 '..BMI.'
        FCB     $26,$FF,$42,$4E,$45,$02  ;0C0A: 26 FF 'BNE' 02 '..BNE.'
        FCB     $2A,$FF,$42,$50,$4C,$02  ;0C10: 2A FF 'BPL' 02 '..BPL.'
        FCB     $20,$FF,$42,$52,$41,$02  ;0C16: 20 FF 'BRA' 02 '..BRA.'
        FCB     $8D,$FF,$42,$53,$52,$02  ;0C1A: 8D FF 'BSR' 02 '..BSR.'
        FCB     $28,$FF,$42,$56,$43,$02  ;0C22: 28 FF 'BVC' 02 '..BVC.'
        FCB     $29,$FF,$42,$56,$53,$02  ;0C28: 29 FF 'BVS' 02 '..BVS.'
        FCB     $11,$FF,$43,$42,$41,$01  ;0C2E: 11 FF 'CBA' 01 '..CBA.'
        FCB     $0C,$FF,$43,$4C,$43,$01  ;0C34: 0C FF 'CLC' 01 '..CLC.'
        FCB     $0E,$FF,$43,$4C,$49,$01  ;0C3A: 0E FF 'CLI' 01 '..CLI.'
        FCB     $4F,$CF,$43,$4C,$52,$03  ;0C40: 4F CF 'CLR' 03 '..CLR.'
        FCB     $0A,$FF,$43,$4C,$56,$01  ;0C46: 0A FF 'CLV' 01 '..CLV.'
        FCB     $81,$8F,$43,$4D,$50,$04  ;0C4C: 81 8F 'CMP' 04 '..CMP.'
        FCB     $43,$CF,$43,$4F,$4D,$03  ;0C52: 43 CF 'COM' 03 '..COM.'
        FCB     $8C,$8F,$43,$50,$58,$06  ;0C58: 8C 8F 'CPX' 06 '..CPX.'
        FCB     $19,$FF,$44,$41,$41,$01  ;0C5E: 19 FF 'DAA' 01 '..DAA.'
        FCB     $4A,$CF,$44,$45,$43,$03  ;0C64: 4A CF 'DEC' 03 '..DEC.'
        FCB     $34,$FF,$44,$45,$53,$01  ;0C6A: 34 FF 'DES' 01 '..DES.'
        FCB     $09,$FF,$44,$45,$58,$01  ;0C70: 09 FF 'DEX' 01 '..DEX.'
        FCB     $88,$8F,$45,$4F,$52,$04  ;0C76: 88 FF 'EOR' 04 '..EOF.'
        FCB     $4C,$CF,$49,$4E,$43,$03  ;0C7C: 4C CF 'INC' 03 '..INC.'
        FCB     $31,$FF,$49,$4E,$53,$01  ;0C82: 31 FF 'INS' 01 '..INS.'
        FCB     $08,$FF,$49,$4E,$58,$01  ;0C88: 08 FF 'INX' 01 '..INX.'
        FCB     $6E,$EF,$4A,$4D,$50,$07  ;0C8E: 6E EF 'JMP' 07 '..JMP.'
        FCB     $AD,$EF,$4A,$53,$52,$07  ;0C94: AD EF 'JSR' 07 '..JSR.'
        FCB     $86,$8F,$4C,$44,$41,$04  ;0C9A: 86 8F 'LDA' 04 '..LDA.'
        FCB     $8E,$CF,$4C,$44,$53,$06  ;0CA0: 8E CF 'LDS' 06 '..LDS.'
        FCB     $CE,$CF,$4C,$44,$58,$06  ;0CA6: CE CF 'LDX' 06 '..LDX.'
        FCB     $44,$CF,$4C,$53,$52,$03  ;0CAC: 44 CF 'LSR' 03 '..LSR.'
        FCB     $40,$CF,$4E,$45,$47,$03  ;0CB2: 40 CF 'NEG' 03 '..NEG.'
        FCB     $01,$FF,$4E,$4F,$50,$01  ;0CB8: 01 FF 'NOP' 01 '..NOP.'
        FCB     $8A,$8F,$4F,$52,$41,$04  ;0CBE: 8A 8F 'ORA' 04 '..ORA.'
        FCB     $36,$FE,$50,$53,$48,$08  ;0CC4: 36 FE 'PSH' 08 '..PSH.'
        FCB     $32,$FE,$50,$55,$4C,$08  ;0CCA: 32 FE 'PUL' 08 '..PUL.'
        FCB     $49,$CF,$52,$4F,$4C,$03  ;0CD0: 49 CF 'ROL' 03 '..ROL.'
        FCB     $46,$CF,$52,$4F,$52,$03  ;0CD6: 46 CF 'ROR' 03 '..ROR.'
        FCB     $3B,$FF,$52,$54,$49,$01  ;0CDC: 3B FF 'RTI' 01 '..RTI.'
        FCB     $39,$FF,$52,$54,$53,$01  ;0CE2: 39 FF 'RTS' 01 '..RTS.'
        FCB     $10,$FF,$53,$42,$41,$01  ;0CE8: 10 FF 'SBA' 01 '..SBA.'
        FCB     $82,$8F,$53,$42,$43,$04  ;0CEE: 82 8F 'SBC' 04 '..SBC.'
        FCB     $0D,$FF,$53,$45,$43,$01  ;0CF4: 0D FF 'SEC' 01 '..SEC.'
        FCB     $0F,$FF,$53,$45,$49,$01  ;0CFA: 0F FF 'SEI' 01 '..SEI.'
        FCB     $0B,$FF,$53,$45,$56,$01  ;0D00: 0B FF 'SEV' 01 '..SEV.'
        FCB     $87,$8F,$53,$54,$41,$05  ;0D06: 87 8F 'STA' 05 '..STA.'
        FCB     $8F,$CF,$53,$54,$53,$09  ;0D0C: 8F CF 'STS' 09 '..STS.'
        FCB     $CF,$CF,$53,$54,$58,$09  ;0D12: CF CF 'STX' 09 '..STX.'
        FCB     $80,$8F,$53,$55,$42,$04  ;0D18: 80 8F 'SUB' 04 '..SUB.'
        FCB     $3F,$FF,$53,$57,$49,$01  ;0D1E: 3F FF 'SWI' 01 '..SWI.'
        FCB     $16,$FF,$54,$41,$42,$01  ;0D24: 16 FF 'TAB' 01 '..TAB.'
        FCB     $06,$FF,$54,$41,$50,$01  ;0D2A: 06 FF 'TAP' 01 '..TAP.'
        FCB     $17,$FF,$54,$42,$41,$01  ;0D30: 17 FF 'TBA' 01 '..TBA.'
        FCB     $07,$FF,$54,$50,$41,$01  ;0D36: 07 FF 'TPA' 01 '..TPA.'
        FCB     $4D,$CF,$54,$53,$54,$03  ;0D3C: 4D CF 'TST' 03 '..TST.'
        FCB     $30,$FF,$54,$53,$58,$01  ;0D42: 30 FF 'TSX' 01 '..TSX.'
        FCB     $35,$FF,$54,$58,$53,$01  ;0D48: 35 FF 'TXS' 01 '..TXS.'
        FCB     $3E,$FF,$57,$41,$49,$01  ;0D4E: 3E FF 'WAI' 01 '..WAI.'
        FCB     $00,$00,$FF,$FF,$FF,$01  ;0D54: 00 00 FF FF FF 01 '......'
;
; END of OPCODE TABLE
;

I wonder if Dave has had a chance to do any more development on his 4052 emulator?
 
Last edited:
I am continuing to study 4051 DDT and I believe I am making progress on understanding how the 4051 DEBUG ROM relocates DDT into a string variable in RAM with CALL "DEBUG",A$.

  1. DDT requires 5632 bytes of RAM = 1600h bytes of RAM.
    • Since DDT starts at address 88D1h in the DEBUG ROM (which is bank-switched into 8800h when CALL "DEBUG",A$ is executed), the last byte of DDT in DEBUG ROM is at 88D1+15FF=9ED0
  2. CALL "DEBUG" executes starting at address 882E and ends at 88CE.
    • CALL "DEBUG" copies DDT from DEBUG ROM to A$ in RAM, then uses the address relocation table starting at A000h to change the addresses at the matching offset from the first byte of A$ to their current value plus the address of the first byte in A$
  3. Then CALL "DEBUG" jumps to the first byte in A$
My goal is to port 4051 DDT to the 4052A/4054A by creating a 4052 DEBUG ROM which will do the steps above - and uses the 4052/4054 ROM entry points that match the 4051 BASIC ROM entry points.

It is likely that I will be adding or removing DDT code to port it to the 4052A/4054A - which means I will also have to modify the address relocation table to ensure that the DDT code relocation is maintained.

My previous attempts to disassemble 4051 DEBUG ROM with f9dasm have many references to addresses outside the range of DDT. Most of those are memory addresses - and f9dasm assumes Mxxxx and Zxxxx addresses outside the assembly code address range must NOT be relocated, but DDT has reserved areas for the DDT stack and other tables within 5632 byte DDT address range. This explains why a special relocation table is needed in the DEBUG ROM. This relocation table is outside the range of DDT bytes and therefore is NOT copied into RAM.

It occurred to me yesterday that I should study which bytes of DDT are relocated - as they might also help identify ALL the DATA areas in DDT - so these data areas can be marked as FCB in the 4052 DDT source code I need to create.

I used HxD to export the DDT bytes from the DEBUG ROM as an S19 ASCII HEX file, and export the relocation table as an S19 ASCII HEX file.

Then I extracted the relocation table and created a 4051 BASIC program with that table stored in DATA statements. My program BASIC reads the DDT S19 code file, one line at a time and reads the relocation HEX byte table one line at a time and searches the 32 S19 HEX bytes for a match with the relocation table HEX offset - using 4051 Extended BASIC CALL "HEXDEC" to convert the code and relocation offset address to decimal for the logic.

The zip file attached to this post includes my BASIC program - which I ran on the 4051 Emulator after adding a second Flash Drive @6: for the output of the program.

The program reads the code file on Flash Drive @5: and writes each line of code to the output on Flash Drive @6: and if relocation matches are found prints the relocation offset below the address in the code that needs to be offset.

I haven't had a chance to study the entire output file, but here is the beginning of the output file:

Code:
S00600004844521B
 
S11288D1861536200200007F15A4BD06C3BF150F
                  0005  0008  000B  000E
S12388E0A730BDAA46FF15668619A70886FFB715A6BD00EC8602B715958E154BBF1568CEA7
                    0015              001E  0021      0026  0029  002C
S123890087C8BD06B56F016F0386FFA700A7028634A701A7037F156A860FA702E60211266E
              0032                                  0045        
S12389200373156ACEEFB8FFFFF8CE0F5FFFFFFACE10C8FFFFFCCE87C8A600A602863EA729
            0051              005A        0060                  
S1238940018637A703BD06BE7F159BBD083ECE15E6FF154EFF1550BD063D444454205635E2
                    0075  0078  007B  007E  0081  0084  0087    
S1238960312E38204C4F41444544204154200700FE0005BD061BBD05477E06FDBD0FE37F1E
                                          00A0  00A3  00A6  00A9  00AC
S1238980156CB6159BB7159CCE0963FF154CB6154D36B6154C36BD06C37F15A68D1FBF150F
        00AF  00B2  00B5  00B8  00BB  00BE    00C2    00C6  00C9      00CE
S12389A0687D15A42707BE1566BD06D93BBE15A7BDA9D486FFB715A4BD06D93239CE15A99B
            00D1      00D6  00D9    00DD            00E5  00E8      00ED
S12389C0FF15A0CE01A1FF15A27D15A62717FE15A20808FF15A2EE00271F7D15A62704A68B
          00F0  00F3  00F6  00F9      00FE      0103          010A
S12389E0002002A700FE15A07D15A62704A7002002A60008FF15A020D57D15A62756C627D2
                    0115  0118                    0124      0129
S1238A00F787A97F87ABCEE42CFF87AA96712A287F00717F878D7F878FCEFF2CFF878CFFF1
                                                                 
S1238A20878E96A8B7878C96A9B7878E96AA8AFCB7879496ABB78796CE0568FF046D967CA0
                                                          0168  
S1238A40B7159DB6046F8A40B7046FCE0000DF4D7F047539B6159DBD069496712A15C68610
          0170                                    0184  0187

And here is the beginning of 4051 DEBUG ROM f9dasm disassembly (relocating the starting address of ZBEGIN to 0940 also in the zipped attachment) with my current comments:

Code:
ZBEGIN  LDAA    #$15                     ;0940: 86 15          '..' ;START OF DDT LOADED INTO A$ in RAM FROM CALL "DEBUG",A$
        PSHA                             ;0942: 36             '6'
        BRA     Z0947                    ;0943: 20 02          ' .'
        FCB     $00                      ;0945: 00             '.'
        FCB     $00                      ;0946: 00             '.'
Z0947   CLR     M15A4                    ;0947: 7F 15 A4       '...'
        JSR     Z06C3                    ;094A: BD 06 C3       '...'
        STS     M15A7                    ;094D: BF 15 A7       '...'
        TSX                              ;0950: 30             '0'
        JSR     ZAA46                    ;0951: BD AA 46       '..F'
        STX     M1566                    ;0954: FF 15 66       '..f'
        LDAA    #$19                     ;0957: 86 19          '..'
        STAA    $08,X                    ;0959: A7 08          '..'
        LDAA    #$FF                     ;095B: 86 FF          '..'
        STAA    M15A6                    ;095D: B7 15 A6       '...'
        JSR     >Z00EC                   ;0960: BD 00 EC       '...'
M0963   LDAA    #$02                     ;0963: 86 02          '..'
        STAA    M1595                    ;0965: B7 15 95       '...'
        LDS     #M154B                   ;0968: 8E 15 4B       '..K'
        STS     M1568                    ;096B: BF 15 68       '..h'
        LDX     #M87C8                   ;096E: CE 87 C8       '...'
        JSR     Z06B5                    ;0971: BD 06 B5       '...'
        CLR     $01,X                    ;0974: 6F 01          'o.'
        CLR     $03,X                    ;0976: 6F 03          'o.'
        LDAA    #$FF                     ;0978: 86 FF          '..'
        STAA    ,X                       ;097A: A7 00          '..'
        STAA    $02,X                    ;097C: A7 02          '..'
        LDAA    #$34                     ;097E: 86 34          '.4'
        STAA    $01,X                    ;0980: A7 01          '..'
        STAA    $03,X                    ;0982: A7 03          '..'
        CLR     M156A                    ;0984: 7F 15 6A       '..j'
        LDAA    #$0F                     ;0987: 86 0F          '..'
        STAA    $02,X                    ;0989: A7 02          '..'
        LDAB    $02,X                    ;098B: E6 02          '..'
        CBA                              ;098D: 11             '.'
        BNE     Z0993                    ;098E: 26 03          '&.'
        COM     M156A                    ;0990: 73 15 6A       's.j'
Z0993   LDX     #MEFB8                   ;0993: CE EF B8       '...'

Looking at the first relocation offset of 0005h in the code - you can see that location is marked FCB $00, FCB $00, and will be relocated to 0000 + 0940=0940 which is the start address of DDT in RAM in that listing.

These two bytes will be used to print the starting address of DDT.

Second offset is 0008h and the code shows CLR M15A4. However 15A4 in the code is BEQ Z15AB - which is a relative branch and is NOT OK to be modified!
If we add 0940h to 15A4h we get 1EE4h which is in the middle of an area I marked as DDT Stack Area - and makes more sense for a CLR operation.

Examining the output file offset 0032 indicates that 06BE address needs to be relocated to 0940+06B5=0FF5 which in the disassembly listing would be LDAA M007C - which I don't think gets relocated, but I need to compare my DDT loaded into 0940 binary data with my disassembly - taking into account the relocation table.

Here is the first 'page' of DDT at 0940 disassembling itself (screenshot from the 4051 Emulator).

You can see the 0940 starting at 0945! and the JMP 0947 to jump around the two FCB data bytes.

I now have a lot of work to do to compare the binary bytes of DDT with my f9dasm disassembly - updated with the relocation table.

1 0940.png
 

Attachments

Last edited:
I found a latent bug in the 4051 DEBUG (DDT) ROM while reformatting the DDT disassembly opcode table:

I found a "BLO" opcode line in the table - there is no 6800 BLO opcode.
But this bug is latent as I expect the disassembly code to search the table from the beginning, and the table is organized alphabetically based on mnemonic spelling.
Opcode 25h is BCS, which would be found before BLO.

I decided to spend the time manually reorganizing the f9dasm disassembly of the table into six bytes per line per @daver2 's disassembly comments for the Board Bucket DDT ROM.

This format will be easier to add the 4052/4054 new opcodes and the 4052A/4054A additional new opcodes to a 4052 DDT.

But I will need to do more digging into the nine operand types.

The 4052A Assembler BASIC program should also support the nine operand types as it assembles both 6800 opcodes and all the added 4052A opcodes.

Code:
; 6800 OPCODE TABLE - see Dave Roberts ddt_der.txt disassembly comments for 6800 Board Bucket DDT below
;
; * The first byte appears to be the 'base' opcode for the mnemonic. It is also the 'compare' byte for disassembly.
; * The second byte is a 'mask' byte for disassembly.
; * The next three bytes are the 6800 mnemonic.
; * The next byte appears to be an operand 'type' as follows:
; *
; * 1 e.g. 'ABA'
; * 2 e.g. 'BCC'
; * 3 e.g. 'ASL'
; * 4 e.g. 'ADC'
; * 5 e.g. 'STA'
; * 6 e.g. 'CPX'
; * 7 e.g. 'JMP'
; * 8 e.g. 'PSH'
; * 9 e.g. 'STS'
; *

        FCB     $1B,$FF,$41,$42,$41,$01  ;0B98: 1B FF 'ABA' 01 '..ABA.'
        FCB     $89,$8F,$41,$44,$43,$04  ;0B9E: 89 8F 'ADC' 04 '..ADC.'
        FCB     $8B,$8F,$41,$44,$44,$04  ;0BA4: 8B 8F 'ADD' 04 '..ADD.'
        FCB     $84,$8F,$41,$4E,$44,$41  ;0BAA: 84 8F 'AND' 04 '..AND.'
        FCB     $48,$CF,$41,$53,$4C,$03  ;0BB0: 48 CF 'ASL' 03 '..ASL.'
        FCB     $47,$CF,$41,$53,$52,$03  ;0BB6: 47 CF 'ASR' 03 '..ASR.'
        FCB     $24,$FF,$42,$43,$43,$02  ;0BBC: 24 FF 'BCC' 02 '..BCC.'
        FCB     $25,$FF,$42,$43,$53,$02  ;0BC2: 25 FF 'BCS' 02 '..BCS.'
        FCB     $27,$FF,$42,$45,$51,$02  ;0BC8: 27 FF 'BEQ' 02 '..BEQ.'
        FCB     $2C,$FF,$42,$47,$45,$02  ;0BCE: 2C FF 'BGE' 02 '..BGE.'
        FCB     $2E,$FF,$42,$47,$54,$02  ;0BD4: 2E FF 'BGT' 02 '..BGT.'
        FCB     $22,$FF,$42,$48,$49,$02  ;0BDA: 22 FF 'BHI' 02 '..BHI.'
        FCB     $24,$FF,$42,$48,$53,$02  ;0BE0: 24 FF 'BHS' 02 '..BHS.'
        FCB     $85,$8F,$42,$49,$54,$04  ;0BE6: 85 8F 'BIT' 04 '..BIT.'
        FCB     $2F,$FF,$42,$4C,$45,$02  ;0BEC: 2F FF 'BLE' 02 '..BLE.'
        FCB     $25,$FF,$42,$4C,$4F,$02  ;0BF2: 25 FF 'BLO' 02 '..BLO.' ? opcode 25 is BCS - THIS IS A MISTAKE, BUT LIKELY WAS NOT CAUGHT BECAUSE BCS IS FOUND FIRST?
        FCB     $23,$FF,$42,$4C,$53,$02  ;0BF8: 23 FF 'BLS' 02 '..BLS.'
        FCB     $2D,$FF,$42,$4C,$54,$02  ;0BFE: 2D FF 'BLT' 02 '..BLT.'
        FCB     $2B,$FF,$42,$4D,$49,$02  ;0C04: 2B FF 'BMI' 02 '..BMI.'
        FCB     $26,$FF,$42,$4E,$45,$02  ;0C0A: 26 FF 'BNE' 02 '..BNE.'
        FCB     $2A,$FF,$42,$50,$4C,$02  ;0C10: 2A FF 'BPL' 02 '..BPL.'
        FCB     $20,$FF,$42,$52,$41,$02  ;0C16: 20 FF 'BRA' 02 '..BRA.'
        FCB     $8D,$FF,$42,$53,$52,$02  ;0C1A: 8D FF 'BSR' 02 '..BSR.'
        FCB     $28,$FF,$42,$56,$43,$02  ;0C22: 28 FF 'BVC' 02 '..BVC.'
        FCB     $29,$FF,$42,$56,$53,$02  ;0C28: 29 FF 'BVS' 02 '..BVS.'
        FCB     $11,$FF,$43,$42,$41,$01  ;0C2E: 11 FF 'CBA' 01 '..CBA.'
        FCB     $0C,$FF,$43,$4C,$43,$01  ;0C34: 0C FF 'CLC' 01 '..CLC.'
        FCB     $0E,$FF,$43,$4C,$49,$01  ;0C3A: 0E FF 'CLI' 01 '..CLI.'
        FCB     $4F,$CF,$43,$4C,$52,$03  ;0C40: 4F CF 'CLR' 03 '..CLR.'
        FCB     $0A,$FF,$43,$4C,$56,$01  ;0C46: 0A FF 'CLV' 01 '..CLV.'
        FCB     $81,$8F,$43,$4D,$50,$04  ;0C4C: 81 8F 'CMP' 04 '..CMP.'
        FCB     $43,$CF,$43,$4F,$4D,$03  ;0C52: 43 CF 'COM' 03 '..COM.'
        FCB     $8C,$8F,$43,$50,$58,$06  ;0C58: 8C 8F 'CPX' 06 '..CPX.'
        FCB     $19,$FF,$44,$41,$41,$01  ;0C5E: 19 FF 'DAA' 01 '..DAA.'
        FCB     $4A,$CF,$44,$45,$43,$03  ;0C64: 4A CF 'DEC' 03 '..DEC.'
        FCB     $34,$FF,$44,$45,$53,$01  ;0C6A: 34 FF 'DES' 01 '..DES.'
        FCB     $09,$FF,$44,$45,$58,$01  ;0C70: 09 FF 'DEX' 01 '..DEX.'
        FCB     $88,$8F,$45,$4F,$52,$04  ;0C76: 88 FF 'EOR' 04 '..EOF.'
        FCB     $4C,$CF,$49,$4E,$43,$03  ;0C7C: 4C CF 'INC' 03 '..INC.'
        FCB     $31,$FF,$49,$4E,$53,$01  ;0C82: 31 FF 'INS' 01 '..INS.'
        FCB     $08,$FF,$49,$4E,$58,$01  ;0C88: 08 FF 'INX' 01 '..INX.'
        FCB     $6E,$EF,$4A,$4D,$50,$07  ;0C8E: 6E EF 'JMP' 07 '..JMP.'
        FCB     $AD,$EF,$4A,$53,$52,$07  ;0C94: AD EF 'JSR' 07 '..JSR.'
        FCB     $86,$8F,$4C,$44,$41,$04  ;0C9A: 86 8F 'LDA' 04 '..LDA.'
        FCB     $8E,$CF,$4C,$44,$53,$06  ;0CA0: 8E CF 'LDS' 06 '..LDS.'
        FCB     $CE,$CF,$4C,$44,$58,$06  ;0CA6: CE CF 'LDX' 06 '..LDX.'
        FCB     $44,$CF,$4C,$53,$52,$03  ;0CAC: 44 CF 'LSR' 03 '..LSR.'
        FCB     $40,$CF,$4E,$45,$47,$03  ;0CB2: 40 CF 'NEG' 03 '..NEG.'
        FCB     $01,$FF,$4E,$4F,$50,$01  ;0CB8: 01 FF 'NOP' 01 '..NOP.'
        FCB     $8A,$8F,$4F,$52,$41,$04  ;0CBE: 8A 8F 'ORA' 04 '..ORA.'
        FCB     $36,$FE,$50,$53,$48,$08  ;0CC4: 36 FE 'PSH' 08 '..PSH.'
        FCB     $32,$FE,$50,$55,$4C,$08  ;0CCA: 32 FE 'PUL' 08 '..PUL.'
        FCB     $49,$CF,$52,$4F,$4C,$03  ;0CD0: 49 CF 'ROL' 03 '..ROL.'
        FCB     $46,$CF,$52,$4F,$52,$03  ;0CD6: 46 CF 'ROR' 03 '..ROR.'
        FCB     $3B,$FF,$52,$54,$49,$01  ;0CDC: 3B FF 'RTI' 01 '..RTI.'
        FCB     $39,$FF,$52,$54,$53,$01  ;0CE2: 39 FF 'RTS' 01 '..RTS.'
        FCB     $10,$FF,$53,$42,$41,$01  ;0CE8: 10 FF 'SBA' 01 '..SBA.'
        FCB     $82,$8F,$53,$42,$43,$04  ;0CEE: 82 8F 'SBC' 04 '..SBC.'
        FCB     $0D,$FF,$53,$45,$43,$01  ;0CF4: 0D FF 'SEC' 01 '..SEC.'
        FCB     $0F,$FF,$53,$45,$49,$01  ;0CFA: 0F FF 'SEI' 01 '..SEI.'
        FCB     $0B,$FF,$53,$45,$56,$01  ;0D00: 0B FF 'SEV' 01 '..SEV.'
        FCB     $87,$8F,$53,$54,$41,$05  ;0D06: 87 8F 'STA' 05 '..STA.'
        FCB     $8F,$CF,$53,$54,$53,$09  ;0D0C: 8F CF 'STS' 09 '..STS.'
        FCB     $CF,$CF,$53,$54,$58,$09  ;0D12: CF CF 'STX' 09 '..STX.'
        FCB     $80,$8F,$53,$55,$42,$04  ;0D18: 80 8F 'SUB' 04 '..SUB.'
        FCB     $3F,$FF,$53,$57,$49,$01  ;0D1E: 3F FF 'SWI' 01 '..SWI.'
        FCB     $16,$FF,$54,$41,$42,$01  ;0D24: 16 FF 'TAB' 01 '..TAB.'
        FCB     $06,$FF,$54,$41,$50,$01  ;0D2A: 06 FF 'TAP' 01 '..TAP.'
        FCB     $17,$FF,$54,$42,$41,$01  ;0D30: 17 FF 'TBA' 01 '..TBA.'
        FCB     $07,$FF,$54,$50,$41,$01  ;0D36: 07 FF 'TPA' 01 '..TPA.'
        FCB     $4D,$CF,$54,$53,$54,$03  ;0D3C: 4D CF 'TST' 03 '..TST.'
        FCB     $30,$FF,$54,$53,$58,$01  ;0D42: 30 FF 'TSX' 01 '..TSX.'
        FCB     $35,$FF,$54,$58,$53,$01  ;0D48: 35 FF 'TXS' 01 '..TXS.'
        FCB     $3E,$FF,$57,$41,$49,$01  ;0D4E: 3E FF 'WAI' 01 '..WAI.'
        FCB     $00,$00,$FF,$FF,$FF,$01  ;0D54: 00 00 FF FF FF 01 '......'
;
; END of OPCODE TABLE
;

I wonder if Dave has had a chance to do any more development on his 4052 emulator?

Looks like BLO was an alias for BCS opcode in the 6801 or 6805 according to this link:
https://retrocomputing.stackexchange.com/questions/15278/what-are-the-added-opcodes-for-mc6801-mc6803

But there are other new opcodes in 6801 and 6805 not in the DDT opcode list - so not sure why BLO was added. Still not an issue running DDT, because opcode 25h should always be displayed as BCS.
 
Monty:

I studied what you did to "walk" the Name Table and Mr Cranford's comments, this has been an interest area for me because I think it is possible to call the "EXEC" function with multiple strings: one to contain the program, and others to pass information to the program. The strings should be on the call stack and the Name Table is implied.

I noticed that Arrays were not included in your example.

I looked at how they were stored based on the definitions for the Name Table format in the fische.

Here are some modifications to your program to display one and two dimensional arrays as they are defined in the Name Table. Note that the "dimensioned" field we expect for strings is used for the row, and the "used" dimension is now taken over by the column dimension definition for a array of two dimensions. A single dimension array zeroes out the column dimension rather than follow the format for a string.

This is in agreement with the SETDIM routine found at $E579 in the 4051 firmware.

I set an element in one of the defined arrays as an experiment, while the dimensions in the Name Table did not change, the pointers to the variables changed, so we may have to follow the pointer into the variable to determine which elements are defined for an array.

Not sure about the Matrix definition mentioned in the fishe yet -

Here are the changes to your program:

Add:

124 REM Add arrays
125 DIM X(15),Y(7,5)

Replace:

470 IF G$<>"1" THEN 500

With:

470 IF G$<>"1" THEN 700

Add a section to handle arrays:

700 IF G$<>"2" THEN 500
710 REM Found an Array
720 H$=" Array"
730 C$=SEG(D$,11,4)
740 CALL "HEXDEC",C$,E
750 C$=SEG(D$,15,4)
760 CALL "HEXDEC",C$,F
770 PRINT H$;" XDIM(";E;") YDIM(";F;")"
780 REM RETURN TO THE MAIN FLOW
790 GO TO 520

Regards,



Nelson
 

Attachments

  • PROG_NAMESPACE_array.png
    PROG_NAMESPACE_array.png
    112.9 KB · Views: 6
Monty:

I studied what you did to "walk" the Name Table and Mr Cranford's comments, this has been an interest area for me because I think it is possible to call the "EXEC" function with multiple strings: one to contain the program, and others to pass information to the program. The strings should be on the call stack and the Name Table is implied.

I noticed that Arrays were not included in your example.

I looked at how they were stored based on the definitions for the Name Table format in the fische.

Here are some modifications to your program to display one and two dimensional arrays as they are defined in the Name Table. Note that the "dimensioned" field we expect for strings is used for the row, and the "used" dimension is now taken over by the column dimension definition for a array of two dimensions. A single dimension array zeroes out the column dimension rather than follow the format for a string.

This is in agreement with the SETDIM routine found at $E579 in the 4051 firmware.

I set an element in one of the defined arrays as an experiment, while the dimensions in the Name Table did not change, the pointers to the variables changed, so we may have to follow the pointer into the variable to determine which elements are defined for an array.

Not sure about the Matrix definition mentioned in the fishe yet -

Here are the changes to your program:

Add:

124 REM Add arrays
125 DIM X(15),Y(7,5)

Replace:

470 IF G$<>"1" THEN 500

With:

470 IF G$<>"1" THEN 700

Add a section to handle arrays:

700 IF G$<>"2" THEN 500
710 REM Found an Array
720 H$=" Array"
730 C$=SEG(D$,11,4)
740 CALL "HEXDEC",C$,E
750 C$=SEG(D$,15,4)
760 CALL "HEXDEC",C$,F
770 PRINT H$;" XDIM(";E;") YDIM(";F;")"
780 REM RETURN TO THE MAIN FLOW
790 GO TO 520

Regards,



Nelson
Great work!

I had continued my NAMESPACE experiments back in February and added array support in the attached 'test4' program.

Here is the 4051 Emulator screenshot of it running:

screen - 2025-07-21T063050.038.png

What I did not add to my program was the dimensioned size and whether all the array elements were defined.

I cleared the display and ran the Enhanced BASIC CALL "VLIST" command and got this screenshot:

screen - 2025-07-21T063118.569.png

I will now add the display of array dimensions - and experiment with just partially filling the array and see how CALL "VLIST" displays the array.

Note that simple numeric variables are stored in the namespace - that is why 4050 BASIC reports that simple numeric variables only take 14 bytes of RAM.
 

Attachments

The Tektronix 4052A/4054A BASIC ROM includes CALL "VLIST" and CALL "CLIST" commands with the underlined CONTROL characters, but they were NOT documented in the 4052A / 4054A BASIC and GPIB Enhancements Programmers Reference Manual!

These commands were finally documented in Tekniques as I reported in my thread along with the 4052A CALL "EXEC":
https://forum.vcfed.org/index.php?threads/five-undocumented-tektronix-4052a-4054a-call-instructions-discovered.1244005/post-1328108

I can also see in the original 4052/4054 BASIC ROM a CALL "EXEC" command - but have not found how to use it.

Since the 4052 and 4054 ROM was also limited to 7-bit ASCII strings - I suspect the 4052 CALL "EXEC" may have a similar requirement to 4051 CALL "EXEC" with the assembly program stored in a HEX string similar to the 4051 CALL "EXEC".

Since all the other 4052 ROM Packs - other than the 4052R14 - run on both my 4052 and 4054A - I believe that means ALL the BASIC ROM entry points are identical to those published in the 4052A Assembler manual, and none of those 4052 ROM Packs use any of the A-Series 4052 (4050GX) additional opcodes listed on page 18 of the assembler manual, they only use the 6800 opcodes and original 4052/4054 extended opcodes on page 17 of the manual!

The CALL "VLIST" command is available for both 4052/4054 AND 4052A/4054A in the 4052R14 GPIB Enhancement ROM Pack - using the correct 4052R14 ROM for the original 4052/4054 and the 4052R14-1A ROM for the A-Series, although the 4052R14 displays an incompatible error message in my 4052 with the latest v5.1 BASIC ROMs - if you wait about 10 seconds or so, you do get the BASIC prompt and then you can use the R14 ROM CALLs including CALL "VLIST". I have found CALL "VLIST" very valuable in debugging my BASIC programs.
 
Last edited:
In my continuing quest to understand Tektronix 4051 DDT so I can port it to the 4052A and 4054A computers, I wrote another 4050 BASIC program that took my initial f9dasm INFO file data statements which I created while examining the f9dasm disassembly of the 4051 DEBUG ROM primarily identifying sections of DDT that f9dasm identified as FCB or FCC invalid 6800 code.

There were still a number of memory addresses in ranges identified by the ROM disassembly and listed in the "Used Labels" section at the beginning that made no sense - as these addresses were beyond the 0000-1FFFh range of addresses identified as SYSTEM RAM in the 4051 Service Manual Volume 1 and above the highest SYSTEM RAM address of 06D9h identified by Micheal D Cranford's "4051 assembly code documentation" that I posted on github in my 4051 Assembler directory. Since I have been able to load 4051 DDT at a starting address below 700h with a very tiny BASIC program of two lines (DIM A$(5632), CALL "DEBUG",A$) I believe 4051 SYSTEM RAM only uses less 06D9h bytes = 1753 bytes.

I have done several f9dasm disassemblies of the 4051 DEBUG ROM - one of them marked 8800-882Dh as data - beginning of DEBUG ROM to last byte before the CALL "DEBUG" entry address of 882Eh, and then marked 88D1 (beginning of DDT) to A7FFFh (end of DEBUG ROM) as data and only got six Used Labels in very low SYSTEM RAM and one ROM entry point:

Code:
;****************************************************
;* Used Labels                                      *
;****************************************************

M0000   EQU     $0000 ; R0 - 16 bit system register
M0002   EQU     $0002 ; R1
M0003   EQU     $0003 ;   2nd byte of R1
M0004   EQU     $0004 ; R2
M0005   EQU     $0005 ;   2nd byte of R2
M004B   EQU     $004B ; ERRORNUMBER - error code holding area
ZAA3E   EQU     $AA3E 'A5X  - ADD 5 TO X REGISTER

This makes sense as the CALL "DEBUG" routine simply copies DDT bytes from 88D1-9ED1 (1600h bytes=5632 decimal) into A$ and then uses the relocation table at A000-A569h to update the addresses with that offset from the first DDT byte by adding the DDT start address to the value in RAM.

Since my 4050 A-Series port of 4051 DDT might involve adding bytes of code, I think need to understand every address that is relocated and will need to modify the address relocation table from that address to the end.

So my latest BASIC program READs the offset address word from a DATA statement in the program, adds the start address of DDT in the DEBUG ROM, and compares the result against my f9dasm INFO file from the first Flash Drive @5: in the 4051 Emulator. If the address is lower than the range of that INFO data statement - the program writes the two byte range that is to be offset to the second 4051 Emulator Flash Drive @6:. If the relocation address is higher than the range of that INFO data statement - the INFO statement is written to Flash Drive @6:. If the relocation range is within the INFO data range - my BASIC program stops with an ERROR message listing the relocation range and INFO data statement range like this screenshot:

screen - 2025-07-23T075624.637.png

I then examine an f9dasm disassembly of the DEBUG ROM with NO info data file - so full disassembly of all bytes in the ROM and ensure that the flagged error bytes look like a valid memory reference for code and add a comment that those two bytes are to be relocated. I then edit the INFO file to end the data range at the byte before the relocated range and continue the INFO data range at the byte after the relocated range.

I found the relocated addresses were typically in the range of 1500h and marked as "M" for memory reference - which would have been in the BASIC user program range and therefore made no sense for a relocatable DDT program.

There were also relocated addresses in the range of 0600 marked as "Z" for code JMP, BRA, or JSR - that made sense in the disassembly when I added 88D1 to the offset.

After editing the INFO file and reloading that file into the 4051 Emulator and rerunning my BASIC program already in memory, the program would stop with the next ERROR.

I repeated this process until the BASIC program had read a relocation address of FFFF - which indicates end of relocation and got this screenshot:

The program prints a period when it writes one of my original INFO data statements to the output file and prints an "R" when it adds a new data statement for each relocated address from the table.

If the relocated address was within a section of DDT code, there was no ERROR and the program would automatically add the new data statement range to the output file.

4051 DDT all relocated addresses marked.png

I did find a lot of relocation of addresses within some of my original INFO data ranges that were obviously not code.

The disassembled output in those areas might have written those two bytes in the middle of a string of bytes, so I would edit the disassembled output to move the two relocated bytes to a separate line, making sure I changed the resulting disassembled addresses to match my change.

This effort resulted in my finding the DDT command table - located immediately prior to the DDT opcode table as shown in my edits for that range of the disassembly.

Looks like the first byte in each DDT command in the table is the ASCII character, followed by the two byte address of the DDT code that handles that character.

Code:
; START OF DDT COMMAND TABLE

        FCC     $20                      ;8ABA: 20             ' '
        FCC     $0C,$76                  ;8ABB: 0C 76          ' ' ; GETS RELOCATED
        FCB     $22                      ;8ABD: 22             '"'
        FCB     $0B,$FB                  ;8ABE: 0B FB          '..'; GETS RELOCATED
        FCC     "Z"                      ;8AC0: 5A             'Z'
        FCB     $12,$D3                  ;8AC1: 12 D3              ; GETS RELOCATED
        FCB     $26                      ;8AC3; 26             '&'
        FCB     $11,$CE                  ;8AC4  11 CE          '..'; GETS RELOCATED
        FCC     "'"                      ;8AC6: 27             '''
        FCB     $0C,$76                  ;8AC7: 0C 76          '.' ; GETS RELOCATED
        FCC     "v"                      ;8AC9: 2A             'v'
        
... table too long for this post.  I have attached the complete table to this post

; START OF OPCODE TABLE

I think there are more DDT command characters in this disassembly than are listed in the 4051 Assembler documentation, but I need to study both lists.

In addition, I have been experimenting with how to recall DDT from BASIC.

The 4051 Assembler documentation indicates you can press the UDK 1 key to reload DDT.
However the BASIC program that accompanied the Assembler documentation could only load DDT from a tape file.

When I learned how to load the 4051 DEBUG ROM from Micheal D Cranford: DIM A$(5632), CALL "DEBUG",A$ it was much simpler.

I tried to mimic the original Assembler BASIC program by adding a UDK 1 command to CALL "LOADGO" to the address printed by DDT and it would jump to the DDT address, but when you pressed UDK 5 to return to BASIC, the program would print a SYSTEM crash message at the bottom of the screen - likely because DDT was trying to patch the system interrupts but that can only be done correctly if the entire CALL "DEBUG" is exectuted.

I learned through experimentation, you simply execute CALL "DEBUG",A$ again and DDT will be loaded into A$ - and DDT will mirror the system interrupts properly and UDK 5 will return to BASIC without crashing.
 

Attachments

Here is the updated 4051 DDT v51.8 command table with notes on each command and *** not documented for commands not in the 4051 Assembler documentation of DDT v51.7.

Possibly the new commands were added in v51.8 in addition to the v51.7 commands?

Disassembly comparison of the DDT v51.7 tape file versus disassembly of the DDT v51.8 DEBUG ROM could show whether the undocumented commands in v51.8 were in the v51.7 command table.

Code:
; START OF DDT COMMAND TABLE

        FCC     $20                      ;8ABA: 20             ' ' ; SPACE character
        FCC     $0C,$76                  ;8ABB: 0C 76          ' ' ;        RELOCATED
        FCB     $22                      ;8ABD: 22             '"' ; " ENTER HEX STRING
        FCB     $0B,$FB                  ;8ABE: 0B FB          '..';        RELOCATED
        FCC     "Z"                      ;8AC0: 5A             'Z' ; Z Assembly source LABELS must begin with Z
        FCB     $12,$D3                  ;8AC1: 12 D3              ;        RELOCATED
        FCB     $26                      ;8AC3; 26             '&' ; & ENTER ASCII STRING
        FCB     $11,$CE                  ;8AC4  11 CE          '..';        RELOCATED
        FCC     "'"                      ;8AC6: 27             ''' ; ' *** not documented, same code address as SPACE chr - but error if substituted for SPACE
        FCB     $0C,$76                  ;8AC7: 0C 76          '.' ;        RELOCATED
        FCC     "*"                      ;8AC9: 2A             '*' ; * ENTER 6800 assembly instructions, and used before assembly comment
        FCB     $13,$C3                  ;8ACA: 13 C3          '..';        RELOCATED
        FCC     "K"                      ;8ACC: 4B             'K' ; K DOWNLOAD ASCII HEX into Memory using Option 1 COMM
        FCB     $13,$CB                  ;8ACD: 13 CB          '..';        RELOCATED
        FCC     "M"                      ;8ACF: 4D             'M' ; M Memory block move
        FCB     $11,$41                  ;8AD0: 11 41           '.';        RELOCATED
        FCC     "H"                      ;8AD2: 48             'H' ; H Find HEADER (mag tape only)
        FCB     $0A,$55                  ;8AD3: 0A 55          '..';        RELOCATED
        FCC     "T"                      ;8AD5: 54             'T' ; T Tape READ (mag tape only)
        FCB     $0A,$6A                  ;8AD6: 0A 6A          '.' ;        RELOCATED
        FCC     "W"                      ;8AD8: 57             'W' ; W WRITE data (mag tape only)
        FCB     $0A,$9B                  ;8AD9: 0A 9B          '..';        RELOCATED
        FCC     "!"                      ;8ADB: 21             '!' ; ! *** not documented (alternate asm source comment?)
        FCB     $0A,$AA                  ;8ADC: 0A AA          '..';        RELOCATED
        FCB     $0D                      ;8ADE  0D             '.' ; CR terminates a command
        FCB     $07,$82                  ;8ADF  07 83          '..';        RELOCATED
        FCC     "."                      ;8AE1: 2E             '.' ; PERIOD between commands to string multiple on one line
        FCB     $06,$60                  ;8AE2: 06 60          '..';        RELOCATED
        FCC     "P"                      ;8AE4: 50             'P' ; P Display PROCESSOR Registers: C,B,A,X,P,S
        FCB     $07,$88                  ;8AE5: 07 88          '..';        RELOCATED
        FCC     "I"                      ;8AE7: 49             'I' ; I used with CTRL key on page 9 HT likely passed to line editor
        FCB     $08,$2B                  ;8AE8: 08 2B          '.' ;        RELOCATED
        FCC     "Q"                      ;8AEA: 51             'Q' ; Q Quick DUMP memory in HEX and ASCII
        FCB     $08,$BE                  ;8AEB: 08 BE          '..';        RELOCATED
        FCC     "X"                      ;8AED: 58             'X' ; X used as ,X INDEXED opcode indicator
        FCB     $09,$13                  ;8AEE: 09 13          '..';        RELOCATED
        FCC     "L"                      ;8AF0: 4C             'L' ; L SEARCH (Look) searches memory for bit pattern in ONES register under mask in MASK register
        FCB     $09,$F5                  ;8AF1: 09 F5          '..';        RELOCATED
        FCC     "G"                      ;8AF3: 47             'G' ; G *** not documented
        FCB     $09,$4C                  ;8AF4: 09 4C          '.' ;        RELOCATED
        FCC     "J"                      ;8AF6: 4A             'J' ; J JUMP to Subroutine
        FCB     $09,$90                  ;8AF7: 09 90          '..';        RELOCATED
        FCC     "S"                      ;8AF9: 53             'S' ; S MOVE blocks of memory
        FCB     $09$6B                   ;8AFA: 09 6B          '.' ;        RELOCATED
        FCC     "["                      ;8AFC: 5B             '[' ; [ Start of a Repeat loop definition or optional data entry parameters
        FCB     $0A,$2D                  ;8AFD: 0A 2D          '.' ;        RELOCATED
        FCC     "]"                      ;8AFF: 5D             ']' ; ] End of a Repeat loop definition or optional data entry parameters
        FCB     $0A                      ;8B00: 0A 45          '.' ;        RELOCATED
        FCC     "R"                      ;8B02: 52             'R' ; R DISPLAY SINGLE REGISTER
        FCB     $08,$1E                  ;8B03: 08 1E          '..';        RELOCATED
        FCC     "="                      ;8B05: 3D             '=' ; = SET REGISTER including debug MASK (M) and debug ONES (O)
        FCB     $08,$04                  ;8B06: 08 04          '..';        RELOCATED
        FCC     "/"                      ;8B08: 2F             '/' ; / DISASSEMBLE memory in mnemonic form
        FCB     $0B,$8F                  ;8B09: 0B 8F          '..';        RELOCATED
        FCC     "<"                      ;8B0B: 3C             '<' ; < BACK UP to last instruction examined
        FCB     $0B,$D0                  ;8B0C: 0B D0          '..';        RELOCATED
        FCC     ">"                      ;8B0E: 3E             '>' ; > DISPLAY referenced address in instruction format
        FCB     $0B,$AB                  ;8B0F: 0B AB          '..';        RELOCATED
        FCC     "}"                      ;8B11: 7D             '}' ; } use before CR to run DDT MACRO command string from mag tape file that has been found
        FCB     $06,$70                  ;8B12: 06 70          '..';        RELOCATED
        FCC     "N"                      ;8B14: 4E             'N' ; N Back up to beginning of file (mag tape only)
        FCB     $0A,$B6                  ;8B15: 0A B6          '..';        RELOCATED
        FCB     $02                      ;8B17: 02             '.' ; STX (Ctrl-") *** not documented
        FCB     $06,$86                  ;8B18: 06 86          '..';        RELOCATED
        FCB     $09                      ;8B1A: 09             '.' ; HT  (Ctrl-I) likely passed to line editor
        FCB     $06,$A6                  ;8B1B: 06 A6          '..';        RELOCATED
        FCB     $FF                      ;8B1D: FF             '.' ; End of mag tape file mark for MACROS on mag tape - page 8
        FCB     $00,$AB                  ;8B1E: 00 AB          '..';        RELOCATED
        FCC     "U"                      ;8B20: 55             'U' ; U PRINT a FLOATING POINT value converting 8-byte FP number to ASCII DECIMAL
        FCB     $0A,$C9                  ;8B21: 0A C9          '..';        RELOCATED
        FCC     "+"                      ;8B23: 2B             '+' ; + *** not documented but same address as MINUS command
        FCB     $0B,$47                  ;8B24: 0B 47          '..';        RELOCATED
        FCB     $2D                      ;8B26: 2D             '-' ; - BACK UP one tape record (mag tape only)
        FCB     $0B,$47                  ;8B27: 0B 47          '..';        RELOCATED

; START OF OPCODE TABLE
 
Last edited:
I just did some experiments with the 4051 Emulator running CALL "DEBUG" to get DDT v51.8 loaded and test the undocumented commands in my last post.

screen - 2025-07-24T113711.644.png
  1. ' I tested this as a substitute for the SPACE character in assembly code and got a WHAT error - so definitely undocumented command
  2. * I mistakenly marked ASTERISK as undocumented, but it is the DDT command to start entering assembly source code and is also used to add assembly comments (which are ignored by DDT, but may be in your assembly source file).
  3. ! Tried EXPLANATION as a command and got "MAG TAPE CARTRIDGE REQUIRED - MESSAGE NUMBER 57" so this must be a new command or undocumented command.
  4. G When I typed G I got a "HARDWARE BREAK REQUIRED - MESSAGE 57" which has this documentation: "An attempt has been made to read or write to a nonexistent tape cartridge. Insert a tape cartridge into the tape slot and try the operation again." Maybe G would load and run an assembly program that had been previously written to tape?
  5. STX Typing CTRL-B into DDT displayed a B with ctrl underline but didn't do anything. CTRL-B is listed on page 9 along with CTRL-I and CTRL-Y but no explanation of what they do.
  6. + When I typed +3000 into DDT after I had typed 2000;* to begin entering assembly code at 2000, DDT displayed 5000. So + is used to change the current assembly address. I then typed -3000 and DDT returned the assembly address of 2000.
Now we are left with only three undocumented DDT v51.8 commands: ', !, and G.

Here are my updated DDT v51.8 command table comments - the addresses are from the DEBUG ROM disassembly before they get copied into RAM and then relocated in RAM.

The code for each DDT command in ROM is at 88D1+address value for that DDT command).
Example for *
88D1+13C3 = 9C94h which is: JSR Z049A
and of course Z094A is relocated to 88d1+094A=8D6Bh which is TST M155B which M155B is relocated...

Code:
; START OF DDT COMMAND TABLE

        FCC     $20                      ;8ABA: 20             ' ' ; SPACE character
        FCC     $0C,$76                  ;8ABB: 0C 76          ' ' ;        RELOCATED
        FCB     $22                      ;8ABD: 22             '"' ; " ENTER HEX STRING
        FCB     $0B,$FB                  ;8ABE: 0B FB          '..';        RELOCATED
        FCC     "Z"                      ;8AC0: 5A             'Z' ; Z Assembly source LABELS must begin with Z
        FCB     $12,$D3                  ;8AC1: 12 D3              ;        RELOCATED
        FCB     $26                      ;8AC3; 26             '&' ; & ENTER ASCII STRING
        FCB     $11,$CE                  ;8AC4  11 CE          '..';        RELOCATED
        FCC     "'"                      ;8AC6: 27             ''' ; ' *** not documented, NOT a substitute for SPACE although same DDT code address
        FCB     $0C,$76                  ;8AC7: 0C 76          '.' ;        RELOCATED
        FCC     "*"                      ;8AC9: 2A             '*' ; * ENTER 6800 assembly instructions
        FCB     $13,$C3                  ;8ACA: 13 C3          '..';        RELOCATED
        FCC     "K"                      ;8ACC: 4B             'K' ; K DOWNLOAD ASCII HEX into Memory using Option 1 COMM
        FCB     $13,$CB                  ;8ACD: 13 CB          '..';        RELOCATED
        FCC     "M"                      ;8ACF: 4D             'M' ; M Memory block move
        FCB     $11,$41                  ;8AD0: 11 41           '.';        RELOCATED
        FCC     "H"                      ;8AD2: 48             'H' ; H Find HEADER (mag tape only)
        FCB     $0A,$55                  ;8AD3: 0A 55          '..';        RELOCATED
        FCC     "T"                      ;8AD5: 54             'T' ; T Tape READ into RAM at HEX address specified or std tape buffer if no address (mag tape only)
        FCB     $0A,$6A                  ;8AD6: 0A 6A          '.' ;        RELOCATED
        FCC     "W"                      ;8AD8: 57             'W' ; W WRITE data (mag tape only)
        FCB     $0A,$9B                  ;8AD9: 0A 9B          '..';        RELOCATED
        FCC     "!"                      ;8ADB: 21             '!' ; ! *** not documented - got MAG TAPE CARTRIDGE REQUIRED - MESSAGE NUMBER 57
        FCB     $0A,$AA                  ;8ADC: 0A AA          '..';        RELOCATED
        FCB     $0D                      ;8ADE  0D             '.' ; CR terminates a command
        FCB     $07,$82                  ;8ADF  07 83          '..';        RELOCATED
        FCC     "."                      ;8AE1: 2E             '.' ; PERIOD between commands to string multiple on one line
        FCB     $06,$60                  ;8AE2: 06 60          '..';        RELOCATED
        FCC     "P"                      ;8AE4: 50             'P' ; P Display PROCESSOR Registers: C,B,A,X,P,S
        FCB     $07,$88                  ;8AE5: 07 88          '..';        RELOCATED
        FCC     "I"                      ;8AE7: 49             'I' ; I used with CTRL key on page 9 HT likely passed to line editor
        FCB     $08,$2B                  ;8AE8: 08 2B          '.' ;        RELOCATED
        FCC     "Q"                      ;8AEA: 51             'Q' ; Q Quick DUMP memory in HEX and ASCII
        FCB     $08,$BE                  ;8AEB: 08 BE          '..';        RELOCATED
        FCC     "X"                      ;8AED: 58             'X' ; X used as ,X INDEXED opcode indicator
        FCB     $09,$13                  ;8AEE: 09 13          '..';        RELOCATED
        FCC     "L"                      ;8AF0: 4C             'L' ; L SEARCH (Look) searches memory for bit pattern in ONES register under mask in MASK register
        FCB     $09,$F5                  ;8AF1: 09 F5          '..';        RELOCATED
        FCC     "G"                      ;8AF3: 47             'G' ; G *** not documented - HARDWARE BREAK REQUIRED - MESSAGE 57 for mag tape error
        FCB     $09,$4C                  ;8AF4: 09 4C          '.' ;        RELOCATED
        FCC     "J"                      ;8AF6: 4A             'J' ; J JUMP to Subroutine
        FCB     $09,$90                  ;8AF7: 09 90          '..';        RELOCATED
        FCC     "S"                      ;8AF9: 53             'S' ; S MOVE blocks of memory
        FCB     $09$6B                   ;8AFA: 09 6B          '.' ;        RELOCATED
        FCC     "["                      ;8AFC: 5B             '[' ; [ Start of a Repeat loop definition or optional data entry parameters
        FCB     $0A,$2D                  ;8AFD: 0A 2D          '.' ;        RELOCATED
        FCC     "]"                      ;8AFF: 5D             ']' ; ] End of a Repeat loop definition or optional data entry parameters
        FCB     $0A                      ;8B00: 0A 45          '.' ;        RELOCATED
        FCC     "R"                      ;8B02: 52             'R' ; R DISPLAY SINGLE REGISTER
        FCB     $08,$1E                  ;8B03: 08 1E          '..';        RELOCATED
        FCC     "="                      ;8B05: 3D             '=' ; = SET REGISTER including debug MASK (M) and debug ONES (O)
        FCB     $08,$04                  ;8B06: 08 04          '..';        RELOCATED
        FCC     "/"                      ;8B08: 2F             '/' ; / DISASSEMBLE memory in mnemonic form
        FCB     $0B,$8F                  ;8B09: 0B 8F          '..';        RELOCATED
        FCC     "<"                      ;8B0B: 3C             '<' ; < BACK UP to last instruction examined
        FCB     $0B,$D0                  ;8B0C: 0B D0          '..';        RELOCATED
        FCC     ">"                      ;8B0E: 3E             '>' ; > DISPLAY referenced address in instruction format
        FCB     $0B,$AB                  ;8B0F: 0B AB          '..';        RELOCATED
        FCC     "}"                      ;8B11: 7D             '}' ; } use before CR to run DDT MACRO command string from mag tape file that has been found
        FCB     $06,$70                  ;8B12: 06 70          '..';        RELOCATED
        FCC     "N"                      ;8B14: 4E             'N' ; N Back up to beginning of file, to allow rewriting headers (mag tape only)
        FCB     $0A,$B6                  ;8B15: 0A B6          '..';        RELOCATED
        FCB     $02                      ;8B17: 02             '.' ; STX (Ctrl-B") listed on page 9 but no explanation of what it does. Ctrl-I and Ctrl-Y also listed on page 9
        FCB     $06,$86                  ;8B18: 06 86          '..';        RELOCATED
        FCB     $09                      ;8B1A: 09             '.' ; HT  (Ctrl-I) See STX comment above
        FCB     $06,$A6                  ;8B1B: 06 A6          '..';        RELOCATED
        FCB     $FF                      ;8B1D: FF             '.' ; End of mag tape file mark for MACROS on mag tape (placed on mag tape by BASIC CLOSE statement) - page 8
        FCB     $00,$AB                  ;8B1E: 00 AB          '..';        RELOCATED
        FCC     "U"                      ;8B20: 55             'U' ; U PRINT a FLOATING POINT value converting 8-byte FP number to ASCII DECIMAL
        FCB     $0A,$C9                  ;8B21: 0A C9          '..';        RELOCATED
        FCC     "+"                      ;8B23: 2B             '+' ; + ADDs to current assembly address pointer: +2000. -1000 would subtract 1000h from address pointer.
        FCB     $0B,$47                  ;8B24: 0B 47          '..';        RELOCATED
        FCB     $2D                      ;8B26: 2D             '-' ; - BACK UP one tape record (mag tape only).  Also used to subtract from address pointer if in assembly mode
        FCB     $0B,$47                  ;8B27: 0B 47          '..';        RELOCATED

; START OF OPCODE TABLE
 
Last edited:
Looks like I skipped over another unknown DDT v51.8 command "I".

I had not marked it as unknown because I had found the CTRL-I comment in the 4051 Assembler doc on page 9 and thought since the CTRL key is handled separately from the regular keys that might explain it.

However - since the CTRL-I key and CTRL-B keys are in the ASCII command table - I just checked the I key and it doesn't return an error in assembly mode, so it may be mode specific to a different mode - like tape?

@daver2 listed an I command in his Board Bucket DDT disassembly but didn't describe what that command does.
 
Monty:

I think it is related to handling a breakpoint table. I am coming to the conclusion that there are only a couple of variants of DDT, and they are assembled with different memory locations for the ACIA(s), PIA(s) and other hardware.

Even though a stock 4051 does not have a hardware breakpoint handler, the code is still there. You can confirm this by scanning the ROM that holds DEBUG for the following string:

"HARDWARE BREAK REQUIRED"

Here is what I found when I looked at the I Command for Board Bucket DDT, note that the I Command depends on memory switches set or unset by other commands. These switches are also entangled with the G Command.

* Board Bucket DDT
* *** **********************************
* ***
* *** I Command
* ***
* *** Multiple functions.
* *** DF6B DF6C DF6D Action
* *** 0 X 0 F528: Print breakpoint table
* *** 1 X 0 F54C: Load the X REG with #$DF7A, then advance X REG [$DF71] times 3
* Clear the three bytes starting at the X REG location
* *** X 0 1 F50B: Clear buffer located at $DF7A through $DF97 ($1E bytes)
* *** X 1 1 F54C: Reposition X REG by [$DF71] times 3 in buffer starting at $DF7A
* Clear the three bytes starting at the X REG location
* Copy [$DF6E] (hi byte) to the current X REG position
* Copy [$DF6F] to [XREG + 1]
* *** $DF6E, $DF6F are working storage for X REG,
* *** and also hold a new breakpoint to be added.
* ***
* **************************************
*
ZF4FB TST MDF6D
BNE ZF517 * If not zero, and $DF6C is clear, clear the buffer at $DF7A
TST MDF6B * Clear if T Command, Set if V Command
BEQ ZF528 * T Command: Print ten hexadecimal pairs from the buffer at $DF79
BSR ZF54C * Load the X REG with $DF7A, then advance it by [$DF71] times 3
LDAA #$03 * Clear next three bytes pointed to by X REG
BRA ZF510
*
******************************************************
* *** *** *
* *** Clear buffer located at $DF7A *** *
* *** through $DF97 ($1E bytes) *** *
* *** This includes the breakpoint table *** *
* *** *** *
******************************************************
*
ZF50B LDAA #$1E * Load ACCA with LEN(buf) (dec 30)
LDX #MDF7A * Point to buf[
ZF510 CLR $00,X * Clear buf[ACCA]
INX * X++
DECA * ACC--
BNE ZF510 * If ACCA NOT zero, loop
RTS * done
*
* *** ************************************************
* *** *** *
* *** Insert new breakpoint in table. *** *
* *** *** *
* *** $DF6C: Clear breakpoint table flag *** *
* *** (if zero, clear table before *** *
* *** adding new breakpoint) *** *
* *** $DF71: Current number of breakpoints *** *
* *** $DF6E: Hi byte of new breakpoint *** *
* *** $DF6F: Lo byte of new breakpoint *** *
* *** *** *
* *** Test flag at $DF6C, if zero, clear the *** *
* *** breakpoint table. Otherwise, move the *** *
* *** X REG to the next empty slot and copy the *** *
* *** address located in $DF6E and $DF6F *** *
* *** *** *
* *** ************************************************
*
ZF517 TST MDF6C * Test expected character count
BEQ ZF50B * If zero, first clear character buffer from $DF7A to $DF98
BSR ZF54C * Reposition X REG by [$DF71] times 3 in buffer starting at $DF7A
LDAA MDF6E * Copy [$DF6E] (hi byte) to the current X REG position
STAA $00,X
LDAA MDF6F * Copy [$DF6F] to [XREG + 1]
BRA ZF4EC * STAA $01,X and RTS
*
* *** ****************************************
* *** Print breakpoint table
* *** Start by setting counter in ACC B to zero (0).
* *** Position X REG to point one byte prior to the
* *** start of the breakpoint table starting at $DF7A.
* *** Examine each byte at [X]+1 and [X]+2.
* *** A NULL (0) pointer means the breakpoint is
* *** disabled. If not, print the counter (ACC B)
* *** followed by the hex representation
* *** of bytes two and three followed by a CR,
* *** then advance the index register by three.
* *** If the two bytes are each NULL (0), skip that line
* *** and advance the index register by three.
* *** end when the counter reaches $0A.
* *** This routine sets each triplet to NULL when done.
* *** ****************************************
*
ZF528 CLRB * Zero breakpoint address index counter
LDX #MDF79 * X REG starts 1 byte shy of the breakpoint table (see BSR F560)
ZF52C LDAA $01,X * See if the hi byte of the address following is 0000
BNE ZF534 * Continue until the character is NULL (0)
LDAA $02,X * See if the hi byte of the address following is 0000
BEQ ZF543 * NULL (disabled) entry. Skip to next entry
ZF534 TBA * Non zero address, print the index, space, and the address
JSR ZF344 * Output the low nibble (4 bits) of ACC A hexadecimal digit.
JSR ZF302 * Output a SPACE
BSR ZF560 * JMP ZF47F INC X REG and output byte pointed to by [X REG] as hex digits
BSR ZF560 * JMP ZF47F INC X REG and output byte pointed to by [X REG] as hex digits
BSR ZF4F8 * Output a <CR> <LF> and increment $DFAB
BRA ZF545 * Bump X REG one byte and return if ACC B is zero
ZF543 INX * Increment X REG three times if a table entry is skipped
INX
ZF545 INX * Increment X REG once if the entry was printed
INCB * Advance breakpoint address index counter
CMPB #$0A * Maximum entries?
BNE ZF52C * No, examine the next one.
RTS
*
* *** ******************************************** *** *
* *** *** *
* *** Test to see if we can add a new breakpoint. *** *
* *** If we already have 10 entries, exit the *** *
* *** routine, dump this subroutine call and *** *
* *** fail over to $F433. *** *
* *** If we have room, move the X REG to the next *** *
* *** empty slot and return. *** *
* *** *** *
* *** ******************************************** *** *
*
ZF54C LDX #MDF7A * Point X to line buffer
LDAA MDF71 * Load the number found at $DF71
CMPA #$0A * Is it decimal 10?
BCS ZF55C * If ACC A is less than 10, we can point to the next empty slot
JMP ZF489 * Otherwise, dump the return address on the stack and BRA ZF433
ZF559 INX * Increment X REG by the number found in $DF71 times 3
INX
INX
ZF55C DECA
BPL ZF559
RTS
 
Monty:

I think it is related to handling a breakpoint table. I am coming to the conclusion that there are only a couple of variants of DDT, and they are assembled with different memory locations for the ACIA(s), PIA(s) and other hardware.

Even though a stock 4051 does not have a hardware breakpoint handler, the code is still there. You can confirm this by scanning the ROM that holds DEBUG for the following string:

"HARDWARE BREAK REQUIRED"

Here is what I found when I looked at the I Command for Board Bucket DDT, note that the I Command depends on memory switches set or unset by other commands. These switches are also entangled with the G Command.

* Board Bucket DDT
* *** **********************************
* ***
* *** I Command
* ***
* *** Multiple functions.
* *** DF6B DF6C DF6D Action
* *** 0 X 0 F528: Print breakpoint table
* *** 1 X 0 F54C: Load the X REG with #$DF7A, then advance X REG [$DF71] times 3
* Clear the three bytes starting at the X REG location
* *** X 0 1 F50B: Clear buffer located at $DF7A through $DF97 ($1E bytes)
* *** X 1 1 F54C: Reposition X REG by [$DF71] times 3 in buffer starting at $DF7A
* Clear the three bytes starting at the X REG location
* Copy [$DF6E] (hi byte) to the current X REG position
* Copy [$DF6F] to [XREG + 1]
* *** $DF6E, $DF6F are working storage for X REG,
* *** and also hold a new breakpoint to be added.
* ***
* **************************************
*
ZF4FB TST MDF6D
BNE ZF517 * If not zero, and $DF6C is clear, clear the buffer at $DF7A
TST MDF6B * Clear if T Command, Set if V Command
BEQ ZF528 * T Command: Print ten hexadecimal pairs from the buffer at $DF79
BSR ZF54C * Load the X REG with $DF7A, then advance it by [$DF71] times 3
LDAA #$03 * Clear next three bytes pointed to by X REG
BRA ZF510
*
******************************************************
* *** *** *
* *** Clear buffer located at $DF7A *** *
* *** through $DF97 ($1E bytes) *** *
* *** This includes the breakpoint table *** *
* *** *** *
******************************************************
*
ZF50B LDAA #$1E * Load ACCA with LEN(buf) (dec 30)
LDX #MDF7A * Point to buf[
ZF510 CLR $00,X * Clear buf[ACCA]
INX * X++
DECA * ACC--
BNE ZF510 * If ACCA NOT zero, loop
RTS * done
*
* *** ************************************************
* *** *** *
* *** Insert new breakpoint in table. *** *
* *** *** *
* *** $DF6C: Clear breakpoint table flag *** *
* *** (if zero, clear table before *** *
* *** adding new breakpoint) *** *
* *** $DF71: Current number of breakpoints *** *
* *** $DF6E: Hi byte of new breakpoint *** *
* *** $DF6F: Lo byte of new breakpoint *** *
* *** *** *
* *** Test flag at $DF6C, if zero, clear the *** *
* *** breakpoint table. Otherwise, move the *** *
* *** X REG to the next empty slot and copy the *** *
* *** address located in $DF6E and $DF6F *** *
* *** *** *
* *** ************************************************
*
ZF517 TST MDF6C * Test expected character count
BEQ ZF50B * If zero, first clear character buffer from $DF7A to $DF98
BSR ZF54C * Reposition X REG by [$DF71] times 3 in buffer starting at $DF7A
LDAA MDF6E * Copy [$DF6E] (hi byte) to the current X REG position
STAA $00,X
LDAA MDF6F * Copy [$DF6F] to [XREG + 1]
BRA ZF4EC * STAA $01,X and RTS
*
* *** ****************************************
* *** Print breakpoint table
* *** Start by setting counter in ACC B to zero (0).
* *** Position X REG to point one byte prior to the
* *** start of the breakpoint table starting at $DF7A.
* *** Examine each byte at [X]+1 and [X]+2.
* *** A NULL (0) pointer means the breakpoint is
* *** disabled. If not, print the counter (ACC B)
* *** followed by the hex representation
* *** of bytes two and three followed by a CR,
* *** then advance the index register by three.
* *** If the two bytes are each NULL (0), skip that line
* *** and advance the index register by three.
* *** end when the counter reaches $0A.
* *** This routine sets each triplet to NULL when done.
* *** ****************************************
*
ZF528 CLRB * Zero breakpoint address index counter
LDX #MDF79 * X REG starts 1 byte shy of the breakpoint table (see BSR F560)
ZF52C LDAA $01,X * See if the hi byte of the address following is 0000
BNE ZF534 * Continue until the character is NULL (0)
LDAA $02,X * See if the hi byte of the address following is 0000
BEQ ZF543 * NULL (disabled) entry. Skip to next entry
ZF534 TBA * Non zero address, print the index, space, and the address
JSR ZF344 * Output the low nibble (4 bits) of ACC A hexadecimal digit.
JSR ZF302 * Output a SPACE
BSR ZF560 * JMP ZF47F INC X REG and output byte pointed to by [X REG] as hex digits
BSR ZF560 * JMP ZF47F INC X REG and output byte pointed to by [X REG] as hex digits
BSR ZF4F8 * Output a <CR> <LF> and increment $DFAB
BRA ZF545 * Bump X REG one byte and return if ACC B is zero
ZF543 INX * Increment X REG three times if a table entry is skipped
INX
ZF545 INX * Increment X REG once if the entry was printed
INCB * Advance breakpoint address index counter
CMPB #$0A * Maximum entries?
BNE ZF52C * No, examine the next one.
RTS
*
* *** ******************************************** *** *
* *** *** *
* *** Test to see if we can add a new breakpoint. *** *
* *** If we already have 10 entries, exit the *** *
* *** routine, dump this subroutine call and *** *
* *** fail over to $F433. *** *
* *** If we have room, move the X REG to the next *** *
* *** empty slot and return. *** *
* *** *** *
* *** ******************************************** *** *
*
ZF54C LDX #MDF7A * Point X to line buffer
LDAA MDF71 * Load the number found at $DF71
CMPA #$0A * Is it decimal 10?
BCS ZF55C * If ACC A is less than 10, we can point to the next empty slot
JMP ZF489 * Otherwise, dump the return address on the stack and BRA ZF433
ZF559 INX * Increment X REG by the number found in $DF71 times 3
INX
INX
ZF55C DECA
BPL ZF559
RTS

Nice find!
 
Monty:

Based on your work on the Name Table, I know that the 4051 EXEC call is not officially documented, however, between the 4051 firmware and the CALL EXEC document you have identified before, I think I have an understanding of the code used for the call.

The code only considers one string placed on the stack by the calling program, but the CALL EXEC document hints that additional strings can be stacked to allow the small program in the scratch pad area to then locate a second string variable and call a larger program by chaining to it.

The CALL "HEXEC",<String> function call might be a bit simpler, I need to look at that code.

Attached are my comments on the disassembled code, along with a diagram to follow the pointers.
 

Attachments

  • CALL EXEC STRING LINKS IN 4051 MEMORY.png
    CALL EXEC STRING LINKS IN 4051 MEMORY.png
    68.5 KB · Views: 2
  • EXEC_FUNCTION.zip
    EXEC_FUNCTION.zip
    1.6 KB · Views: 4
Monty:

Based on your work on the Name Table, I know that the 4051 EXEC call is not officially documented, however, between the 4051 firmware and the CALL EXEC document you have identified before, I think I have an understanding of the code used for the call.

The code only considers one string placed on the stack by the calling program, but the CALL EXEC document hints that additional strings can be stacked to allow the small program in the scratch pad area to then locate a second string variable and call a larger program by chaining to it.

The CALL "HEXEC",<String> function call might be a bit simpler, I need to look at that code.

Attached are my comments on the disassembled code, along with a diagram to follow the pointers.
Great disassembly work!

I am going to compare your 4051 CALL "EXEC" disassembly to the 4054A CALL "EXEC" that I see in my 4054A ROM CODE (E000 Constant ROM in the RAM space) with an entry point of 18FA in the BASIC ROM 0000-FFFF.

My search of the 4052 v5.1 ROMs does NOT find an "EXEC" or "EXEC" CALL, but I just get a hang when I type CALL "EXEC" on my 4052 and an error message after CALL "EXEC".

I have disassembled my 4054A BASIC ROM and here are the first set of bytes at address 18FA:

Code:
ZEXEC   FCB     $62                      ;18FA: 62             'b'
        ROLA                             ;18FB: 49             'I'
        STS     M0000                    ;18FC: 9F 00          '..'
        LDAA    M0055                    ;18FE: 96 55          '.U'
        BMI     Z1906                    ;1900: 2B 04          '+.'
        LDAA    M0080                    ;1902: 96 80          '..'
        BNE     Z195C                    ;1904: 26 56          '&V'
Z1906   LDX     M0000                    ;1906: DE 00          '..'
        LDAA    $01,X                    ;1908: A6 01          '..'
        CMPA    #$19                     ;190A: 81 19          '..'
        BNE     Z1911                    ;190C: 26 03          '&.'
        JSR     Z7111                    ;190E: BD 71 11       '.q.'
Z1911   CMPA    #$11                     ;1911: 81 11          '..'
        BEQ     Z1921                    ;1913: 27 0C          ''.'
        CMPA    #$17                     ;1915: 81 17          '..'
        BEQ     Z191E                    ;1917: 27 05          ''.'
        JSR     Z92BE                    ;1919: BD 92 BE       '...'
        BRA     Z1906                    ;191C: 20 E8          ' .'
Z191E   LDAA    #$11                     ;191E: 86 11          '..'
        PSHA                             ;1920: 36             '6'
Z1921   STS     M0000                    ;1921: 9F 00          '..'
        LDAA    #$11                     ;1923: 86 11          '..'

I did a search for these same bytes and found them in the 4052 v5.1 Constant ROM starting at address F8FA - of course some of the extended addresses are different but the Memory addresses look like a match!

Code:
ZEXEC   FCB     $62                      ;F8FA: 62             'b'
        ROLA                             ;F8FB: 49             'I'
        STS     M0000                    ;F8FC: 9F 00          '..'
        LDAA    M0055                    ;F8FE: 96 55          '.U'
        BMI     ZF906                    ;F900: 2B 04          '+.'
        LDAA    M0080                    ;F902: 96 80          '..'
        BNE     ZF95C                    ;F904: 26 56          '&V'
ZF906   LDX     M0000                    ;F906: DE 00          '..'
        LDAA    $01,X                    ;F908: A6 01          '..'
        CMPA    #$19                     ;F90A: 81 19          '..'
        BNE     ZF911                    ;F90C: 26 03          '&.'
        JSR     Z7111                    ;F90E: BD 71 11       '.q.'
ZF911   CMPA    #$11                     ;F911: 81 11          '..'
        BEQ     ZF921                    ;F913: 27 0C          ''.'
        CMPA    #$17                     ;F915: 81 17          '..'
        BEQ     ZF91E                    ;F917: 27 05          ''.'
        JSR     Z92BE                    ;F919: BD 92 BE       '...'
        BRA     ZF906                    ;F91C: 20 E8          ' .'
ZF91E   LDAA    #$11                     ;F91E: 86 11          '..'
        PSHA                             ;F920: 36             '6'
ZF921   STS     M0000                    ;F921: 9F 00          '..'
        LDAA    #$11                     ;F923: 86 11          '..'

The first opcode in both listings is $62 followed by 49h which is a 4052/4054 PSHRET (direct) opcode with the following description in the 4052A Assembler doc:

PSHRET - Push Return Address on Special Stack:

1754054079522.png

This 62 49 opcode is also used as the first instruction in the STACK DUMPER example in that document to store the RETURN ADDRESS at page zero 0049 and 0050:

1754054273323.png

Now I need to compare the 4054A CALL "EXEC" and 4052 CALL "EXEC" to your disassembly of the 4051 CALL "EXEC".

One difference should be the 4054A CALL "EXEC" does not have to copy two HEX characters into each byte since A-Series BASIC added support for 8-bit ASCII characters.

The 4052 CALL "EXEC" is limited to 7-bit ASCII characters and the only 4052 BASIC program I have found in my collection of tapes so far is this listing - and I did not recover the file 4 DATA file: :cry:

Code:
1 REM  4052 DEBUGGER LOADER   (F IS DEBUGGER DATA FILE #)
2 GO TO 100
4 REM DEBUGGER CALL
5 GOSUB 76
6 L$="30C612EE08A60481102612EE0BA6028120260AC63B1405AC0526026E00D7"
7 L$=L$&"4B0F138AC01239"
8 RETURN
76 GOSUB 31313
77 RETURN
100 INIT
110 F=4
120 REM IF THE DESTINATION STRING IS NULL THEN THE DEBUGGER LOADS INTO
130 REM THE SPACE RESERVED FOR THE DESTINATION STRING.
140 REM IF THE DESTINATION STRING CONTAINS A LOAD ADDRESS (IN HEX)
150 REM THEN THE DEBUGGER LOADS ABSOLUTE INTO THAT ADDRESS.
160 REM BEWARE OF USING THE ABSOLUTE LOAD ADDRESS FEATURE.
180 REM L$ IS THE LOADER
190 REM D$ IS THE DESTINATION STRING
200 DIM D$(7500),L$(560)
210 D$=""
220 L$=STR(MEMORY)
230 FIND F
240 INPUT @33:L$
242 A$=CHR(5)
244 C$=A$&"XEC"
250 PRINT "    PUSH UDF KEY #1 TO RUN THE DEBUGGER"
260 PRINT "    PUSH UDF KEY #5 TO RETURN TO BASIC"
270 SET KEY
280 IF LEN(L$)>75 THEN 280
290 SET NOKEY
300 END

31313 CALL C$,D$,L$
31320 RETURN

I am certain this program is for the original 4052/4054 since the loader string is in HEX - and the HEX is NOT the same as the 4051 HEX which used ASCII characters 30h-3Fh.

The 4052A assembler uses 8-bit ASCII strings for the CODE$ and REL$

I have been searching through all the boxes of tapes I received over the years - and have yet to find the tape that contained this 4052 DEBUGGER file - but I am still looking. :cry:

Notice that the program will load the first L$ in line 240 from file 4 - similar to the 4051 loading of DDT!

I did disassemble the L$ in lines 6 and 7 and saw 4052 extended opcodes in it:

Code:
f9dasm: M6800/1/2/3/8/9 / H6309 Binary/OS9/FLEX9 Disassembler V1.82
Loaded binary file 4052_debugger_loader.bin

;****************************************************
;* Used Labels                                      *
;****************************************************

M004B   EQU     $004B

;****************************************************
;* Program Code / Data Areas                        *
;****************************************************

        ORG     $1000

        TSX                              ;1000: 30             '0'  ;move SP+1 to X to point to bottom value on the Stack
        LDAB    #$12                     ;1001: C6 12          '..' ;$12 to B IMM
        LDX     $08,X                    ;1003: EE 08          '..' ;
        LDAA    $04,X                    ;1005: A6 04          '..' ;
        CMPA    #$10                     ;1007: 81 10          '..' ;
        BNE     Z101D                    ;1009: 26 12          '&.' ;
        LDX     $0B,X                    ;100B: EE 0B          '..' ;
        LDAA    $02,X                    ;100D: A6 02          '..' ;
        CMPA    #$20                     ;100F: 81 20          '. ' ;
        BNE     Z101D                    ;1011: 26 0A          '&.' ;
        LDAB    #$3B                     ;1013: C6 3B          '.;' ;
        ADXI    #$05                     ;1015: 14 05          '.'  ;4052/4054 & A EXTENDED ADD 8-BIT SIGNED IMM TO X
        CPX     $05,X                    ;1017: AC 05          '..' ;
        BNE     Z101D                    ;1019: 26 02          '&.' ;
        JMP     ,X                       ;101B: 6E 00          'n.' ;
Z101D   STAB    M004B                    ;101D: D7 4B          '.K' ;
        SEI                              ;101F: 0F             '.'  ;
        TPAX    ...                      ;1020: 13             '.'  ;4052/4054 & A EXTENDED CC to A INCLUDING SPACE BITS
        ORAA    #$C0                     ;1021: 8A C0          '..' ;
        TAPX     ...                     ;1023: 12             '.'  ;4052/4054 & A EXTENDED A to CC INCLUDING SPACE BITS
        RTS                              ;1024: 39             '9'  ; RETURN TO BASIC

        END
 
Back
Top