$PL(86) $PW(132) $MOD52 ; 8052 CODE MODEL FOR ML-ASM ; BASIC-52 COMMAND EXPANSION SOFTWARE V.1J (ROMJ) ; (c) COPYWRITE 1985-2000 BY 'PuterWare ; Gary Drummond Richardson,TX ; ;Note: This program was developed over a period of years, using various programming methods, ; or styles. I experimented with several of both! In the case of the MOV command, I tried ; two different methods of buffering and moving a block of memory. It should not cause a ; problem except with very large programs in BASIC, meaning LOTS of variable space using ; the internal ram. If you have any problems, fix it or try to find me! Jan Axelson has ; been posting my current web page for a few years, and you may be able to find my latest ; web page from her site. www.lvr.com Another way is to search for Puterware or my name. ;Legal Stuff. Disclaimer, CYA, etc...(In plain language :^) ; This is available for anyone to use, except to make money. If you make money from this ; software I want some of it! For private use, my liability is limited to the price you ; paid to get it from ME ($0.00). For states that have other limits on software ; liabilities-YOU CANNOT USE IT, except at your own risk. My ONLY warrantee/Guarantee is ; that it works for me. ; $INCLUDE(MACRO.SRC) ; ADDED INSTRUCTIONs and MACROs ; ; for tests,relocation errors, and CASE constructs ; ; VARIABLES WHICH CONTROL THE FORMAT AND CONTENT OF THE EXPANSION ; ROM. ; SMALL_SCRN EQU 0 ; SHORTEN MOST DISPLAYS TO FIT ON 40 CHAR SCREENS DEC_HDR EQU 0 ; MODIFIES THE DISPLAY WHEN USING THE DIS. COMMAND ; SET TO 0 TO REMOVE THE DECIMAL ADDRESS COLUMN AND ; EXPAND THE NUMBER OF DISPLAYED CHARACTERS/LINE ; ; GENERAL EQUATES FOR READABILITY ; CR EQU 0DH ; C RETURN LF EQU 0AH ; LINE FEED ROM_EOM EQU 22H ; END OF DISPLAY TEXT IN ROM ; ; SELECTED OPBYTEs (See BASIC-52 Users Manual) ; D_STR EQU 6 ; DISPLAY STRING (R3:R1=POINTER) R_MSG EQU 52 ; FLAG BIT FOR ROM MSG G_STR EQU 5 ; INPUT STRING (INTO BASIC LINE BUFFER) D_CHR EQU 80H ; DISPLAY CHAR IN R5 D_HEX EQU 98H ; DISPLAY HEX N_L0 EQU 36H ; BIT WHEN SET-SUPPRESS LEADING 0'S FOR D_HEX L_CHR EQU 3FH ; LOOK AT NEXT CHAR IN BASIC BUFFER G_CHR EQU 40H ; GET NEXT CHAR IN BASIC BUFFER & ADV POINTER G_CON EQU 41H ; GET CHAR FROM CONSOLE PUT IN ACC E_ARG EQU 39H ; EVALUATE EXP (BASIC BUFFER),PUSH ON ARG STACK G_ARG EQU 1 ; POP (16BIT) VALUE FROM ARG STACK TO R3:R1 D_NL EQU 7 ; NEW LINE-SEND CR/LF TO CONSOLE ORG 2000H ; EXTENSION STARTS AT 2000H DB 00H DB 00H DB 5AH ; FLAG EXPANSION OPTION PRESENT ORG 2048H ; CALLED BY BASIC WHEN INITIALIZING SETB 45 ; FLAG EXPANSION HERE-FOR BASIC JB 21H.7,NOT_COLD_START ; FIRST TIME? SETB 21H.7 ; TO KEEP THE (c) FROM COMING UP AGAIN AJMP C_WRITE ; PRINT THE COPYWRITE THIS TIME NOT_COLD_START: RET ORG 2070H MOV DPTR,#VECTOR_TABLE ; TELL BASIC WHERE JUMP TABLE IS RET ; AND RETURN ORG 2078H MOV DPTR,#USER_TABLE ; USER TOKEN TABLE RET ; VECTOR_TABLE: DW DO_DISPLAY ; ADDRESSES MUST BE IN THE SAME ORDER DW HEX_L ; AS THE TOKENS! DW BURN_EPROM ; BASIC USES " (TOKEN-10H)*2 " DW MOV_MEM ; AS AN INDEX INTO THIS TABLE, DW HELP ; WHICH MEANS YOU SHOULD NOT HAVE DW FIL_BLK ; GAPS BETWEEN TOKEN #'S DW VER_MEM DW HEX_ERR ; GO TO AN EXIT CALL FOR DUMMY COMMAND ORG VECTOR_TABLE+(2*17) ; RESERVE SPACE FOR MAX TOKENS ; TOKEN_NUM SET 0FH ; BIAS FOR MAKE_TOKEN MACRO USER_TABLE: MAKE_TOKEN 'DIS.' ; DISPLAY CODE/DATA/EXTERNAL MEMORY MAKE_TOKEN 'HEX.' ; LOAD/SEND INTEL HEXFILE MAKE_TOKEN 'PRG.' ; PROGRAM AN EPROM/RAM MAKE_TOKEN 'MOV.' ; MOVE BLOCKS OF MEMORY AROUND MAKE_TOKEN 'HELP' ; HELP COMMAND FOR EXTENSION, NO "." MAKE_TOKEN 'FIL.' ; FILL RAM WITH A PATTERN MAKE_TOKEN 'VER.' ; VERIFY A MOVE/PRG WORKED ; ; ***** ADD NEW TOKENS HERE ***** ; LAST_TOK EQU TOKEN_NUM ; FOR USE BY HELP COMMAND/DUMMY TOKEN DB LAST_TOK+1 ; WASTE A TOKEN BECAUSE OF ERRORS IN BASIC DB 1FH,'dumy' ; DUMMY COMMAND, SEE ROMJ USER MANUAL! DB 0FFH ; FLAG END OF USER EXPANSION ; ; ORG 20E8H ; ALLOW EXPANSION OF TOKENS ; BEFORE MAKING NEW LODNGO.BAS ; ***************************************************************** ; All code from ORG 20E8H MUST remain unchanged! If it is ; changed, LODNGO.BAS must be re-created. See App. X in ; ROMJ USER'S MANUAL. ; ***************************************************************** ; HEX_L: ; LOAD AN INTEL HEX FILE LJNB 47,DUMMY ; COMMAND MODE? MOV 21H,#80H ; CLR FLAGS EXCEPT THE (C) ACALL PEEK ; CHECK FOR SEND CJNE A,#'A',$+3 ; NUMBER? JC HEX_N1 ; COULD BE CLR ACC.5 ; MAKE UPPER CASE CJNE A,#'L',$+7 ; LOAD? ACALL GCI ; YES, WASTE CHAR SJMP HEX_N CJNE A,#'S',$+5 ; SEND? ACALL GCI ; YES, WASTE CHAR AJMP HEX_S HEX_N: ACALL PEEK CLR ACC.5 CJNE A,#'P',HEX_N1 ; CHECK FOR A 'P'ROMPT ACALL GCI SETB 21H.0 ; FLAG PROMPT CHAR WANTED HEX_N1: MOV A,#E_ARG ; EVAL OFFSET EXPRESSION FROM BASIC BUFFER LCALL 30H MOV A,#G_ARG ; POP OFFSET VALUE OFF STACK LCALL 30H MOV 1FH,R3 ; SAVE OFFSET VALUE MOV 1EH,R1 ; *************** LODNGO.BAS WILL ENTER HERE ********************** ACALL S_HEXL ; MSG ON CONSOLE HEX1: JNB 21H.0,N_PMT ; PROMPT CHAR? MOV R5,#'>' ; YES, SEND ONE MOV A,#D_CHR LCALL 30H N_PMT: MOV A,#G_STR ; GET A CHAR STRING LCALL 30H MOV R1,#7 ; START OF BUFFER HEXN: MOVX A,@R1 ; GET CHAR INC R1 CJNE A,#CR,$+5 ; CR? SJMP HEX1 ; YES, GET ANOTHER STRING CJNE A,#':',HEXN ; NO COLON, NEXT CHAR ; NOW GET THE NUMBER OF BYTES OF DATA IN LINE MOV R6,#0 ;CLEAR CHECKSUM ACALL HGET_BYTE ; GET A BYTE MOV R0,A ; COUNTER ; NEED ADDRESS OF HEX BYTES FROM INPUT AND ADD OFFSET ACALL HGET_BYTE MOV DPH,A ; HI BYTE ACALL HGET_BYTE ; LO BYTE CLR C ADDC A,1EH ; LO+OFFSET MOV DPL,A MOV A,DPH ADDC A,1FH ; HI+OFFSET+C MOV DPH,A ; CHECK THE TYPE 00=DATA, 01=DONE ACALL HGET_BYTE CJNE A,#1,HEX2 ; DONE? JNB 47,$+7 ; SPECIAL ENTRY? CLR A ; YES RETURN TO COMMAND LJMP 30H MOV 1EH,#73H ; 73=OK RET HEX2: ACALL HGET_BYTE ; GET DATA BYTE MOVX @DPTR,A ; STORE IT INC DPTR DJNZ R0,HEX2 ; CONTINUE FOR COUNT IN R0 MOV A,R6 ; GET CSUM XRL A,#0FFH ; ONE'S COMPLEMENT ADD A,#1 ; TWO'S COMPLEMENT MOV R5,A ; SAVE CSUM ACALL HGET_BYTE ; GET CSUM FROM HEXFILE CJNE A,5,HEX3 ; CHECK IT AJMP HEX1 ; OK, DOIT AGAIN HEX3: ; CSUM DID NOT AGREE-ABORT MOV R3,#HIGH CK_MSG MOV R1,#LOW CK_MSG SETB R_MSG ; FLAG MSG IN ROM MOV A,#D_STR ; PRINT STRING LCALL 30H JNB 47,$+7 ; SPECIAL ENTRY? CLR A LJMP 30H MOV 1EH,37H ; FLAG ERROR RET CK_MSG: DB 'BAD CHECKSUM-ABORT"' ; HGET_BYTE: ; GET A HEXFILE BYTE R1=POINTER TO BUFFER USES R7,ACC MOVX A,@R1 ; FIRST BYTE IN BUFFER INC R1 ; POINT TO NEXT BYTE ACALL HEX_BIN ; MAKE BINARY SWAP A ; HIGH BYTE MOV R7,A ; SAVE IN R7 MOVX A,@R1 INC R1 ACALL HEX_BIN ADD A,R7 ; GOT A BYTE XCH A,R6 ; UPDATE CHECKSUM csum to a,byte to r6 ADD A,R6 ; add byte to a XCH A,R6 ; csum to r6, byte to a RET ; HEX_BIN: CLR C SUBB A,#2FH ; REMOVE CHAR BIAS (MOST OF IT) MOVC A,@A+PC ; 30H-2FH=1 [1+PC]=0 RET DB 0,1,2,3,4,5,6,7,8,9 DB 0,0,0,0,0,0,0 DB 10,11,12,13,14,15 S_HEXL: ACALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH H_MSG ; HEX LOAD MSG ADDRESS MOV R1,#LOW H_MSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H ACALL CRLF ; SEND CRLF TO CONSOLE RET H_MSG: DB 'READY TO PROGRAM...SEND HEX FILE',ROM_EOM ; CRLF: MOV A,#D_NL ;SEND CR/LF TO CONSOLE LCALL 30H RET PEEK: MOV A,#L_CHR ; GET CHAR FROM BASIC AND DON'T INC POINTER LCALL 30H RET GCI: MOV A,#G_CHR ; GET CHAR FROM BASIC AND INC POINTER LCALL 30H RET ; EXP_MSG: DB CR,LF,LF,'Rom Utilities V.1J (ROMJ)',CR,LF DB ' Copywrite 1985-1995',CR,LF DB ' by ',60H,'puterWare',CR,LF,ROM_EOM C_WRITE: ; THE IRS MADE ME DO THIS! MOV R3,#HIGH EXP_MSG MOV R1,#LOW EXP_MSG SETB R_MSG MOV A,#D_STR LCALL 30H RET ; BACK TO BASICS ; ***************************************************************** ; All code before this line MUST remain unchanged! If it is ; changed, LODNGO.BAS must be re-created. See App. X in ; ROMJ USER'S MANUAL. ; ***************************************************************** HEX_ERR: CLR A LJMP 30H ; ERROR-ADD MSG LATER HEX_S: ; HEX.L[C] BEG,END[,+/-OFFSET] ACALL PEEK ; NEXT CHAR CJNE A,#'A',$+3 ; NUMBER? JC HEXS1 ; COULD BE ACALL GCI ; NO GET CHAR AND INC POINTER CLR ACC.5 ; MAKE UPPER CJNE A,#'C',HEX_ERR ; CODE? SETB 21H.1 ; YES, FLAG IT HEXS1: ACALL E2VAR ; PUT 2 VALUES ON STACK (BASIC HANDLES ERRS) ACALL G2VAR ; GET BEG,END (1CH:1DH,1AH:1BH) ACALL CRLF ; NEW LINE LCALL VAL_TWO ; CHECK END>START JNC HEX11 ; VALID ADDRESSES CLR A LJMP 30H ; NO RETURN (MSG SENT) HEX11: CLR C MOV A,R1 ; COUNT IS LOW BY 1 ADDC A,#1 ; MAKE IT GOOD MOV 18H,A ; 18H=D1,D0 MOV A,R2 ; A=D3,D2 ADDC A,#0 ; A=D3,D2 (+CARRY) MOV R0,#18H ; POINT TO LO (DIV BY 16=4 BIT SHIFT) XCHD A,@R0 ; A=D3,D0 (D0=REMAINDER)18H=D1,D2 XCH A,18H ; A=D1,D2 18H=D3,D0 SWAP A ; A=D2,D1 = LOW BYTE OF BLOCK COUNT XCH A,18H ; A=D3,D0 18H=D2,D1 MOV 19H,#0 ; 0 TO HIGH BYTE INC R0 ; POINT TO 19H SWAP A ; A=D0,D3 XCHD A,@R0 ; 19H=HIGH BYTE BLOCK COUNT, A=D0,0 SWAP A MOV 1AH,A ; 1AH=REMAINDER-DON'T NEED END ANY MORE JZ NO_REM ; ANY REMAINDER? SETB 21H.0 ; FLAG REMAINDER NO_REM: MOV 20H,#16 ; START WITH 16 BYTE RECORD MOV A,18H ; GET LO BLOCK COUNT JNZ S_BLK ; ANY LEFT? MOV A,19H ; HI BYTE JNZ S_BLK ; ANY LEFT? MOV 20H,1AH ; REMAINDER=COUNT JNB 21H.0,S_DON ; IS THERE A REMAINDER? SETB 21H.2 ; YES, FLAG NO MORE BYTES S_BLK: ACALL SEND_BLK ; SEND HEXFILE RECORD CLR C MOV A,18H ; GET BLOCK COUNTER SUBB A,#1 ; -1 MOV 18H,A MOV A,19H SUBB A,#0 ; CARRY MOV 19H,A JNB 21H.2,NO_REM ; IF NOT DONE, TRY ANOTHER BLOCK S_DON: ; DONE, SEND CANNED MSG MOV R3,#HIGH EOF_MSG MOV R1,#LOW EOF_MSG SETB R_MSG MOV A,#D_STR LCALL 30H CLR A LJMP 30H EOF_MSG: DB ':00000001FF',CR,LF,ROM_EOM ; END-OF-FILE FOR HEXFILE SEND_BLK: MOV A,20H ; START CHECKSUM WITH COUNT ADD A,1CH ; +START ADD A,1DH ; ADDRESS BYTES MOV 1BH,A ; SAVE CHECKSUM MOV R5,#':' ; FIRST BYTE IS COLON MOV A,#D_CHR ; PRINT CHAR IN R5 LCALL 30H MOV A,20H ; NEXT BYTE TO SEND IS COUNT ACALL HEX_MAKE ; CONVERT TO HEX BYTES ACALL S_BYTES ; SEND BYTES MOV A,1DH ; MSB OF ADDRESS ACALL HEX_MAKE ACALL S_BYTES MOV A,1CH ; LSB OF ADDRESS ACALL HEX_MAKE ACALL S_BYTES MOV A,#'0' MOV B,#'0' ACALL S_BYTES MOV DPL,1CH ; START OF FILE MOV DPH,1DH MOV R0,20H ; COUNT MOV R1,#0F0H ; USE STACK AREA FOR STORAGE UP TO 16 BYTES S_GET: JNB 21H.1,M_GET ; CODE MEMORY? CLR A MOVC A,@A+DPTR ; YES, CODE MEMORY SJMP $+3 M_GET: MOVX A,@DPTR ; GET A BYTE FROM MEMORY MOV @R1,A ; SAVE IN STACK AREA ADD A,1BH ; UPDATE CHECKSUM MOV 1BH,A INC DPTR ; NEXT GET INC 1 ; NEXT PUT DJNZ R0,S_GET ; NEXT? MOV 1CH,DPL ; SAVE MOV 1DH,DPH ; POINTER MOV R0,20H ; COUNT MOV R1,#0F0H ; TOP OF SAVE IN STACK S_PUT: MOV A,@R1 ; GET ACALL HEX_MAKE ; MAKE HEX CHARS ACALL S_BYTES ; SEND THEM INC R1 ; NEXT GET DJNZ R0,S_PUT ; NEXT? MOV A,1BH ; GET CHECKSUM XRL A,#0FFH ; 1'S COMPLEMENT ADD A,#1 ; 2'S COMP ACALL HEX_MAKE ACALL S_BYTES ACALL CRLF ; END OF LINE RET ; S_BYTES: ; SEND TWO BYTES TO CONSOLE FROM A AND B W/SAVE OF R0/1 PUSH 0 ; COUNTER PUSH 1 ; POINTER PUSH B ; SAVE LSN (NOW A BYTE) MOV R5,A ; MSN MOV A,#D_CHR ; OPBYTE TO SEND (R5) LCALL 30H ; DOIT POP 5 ; LSN MOV A,#D_CHR LCALL 30H POP 1 ; POINTER POP 0 ; COUNTER RET ; D_BYTES: ; DISPLAY TWO BYTES ON CONSOLE 'AB' PUSH B ; SAVE SECOND BYTE MOV R5,A ; FIRST BYTE MOV A,#D_CHR ; OPBYTE TO SEND (R5) LCALL 30H ; DOIT POP 5 ; SECOND BYTE MOV A,#D_CHR LCALL 30H RET ; HEX_MAKE: ; MAKE A BYTE HEX FORMAT-RETURNS 2 BYTES, USES A & B MOV B,#16 DIV AB ; Q IN A,REM IN B CJNE A,#LF,$+3 ; 0 THRU 9? JC LESS_A ; A < LF? ADD A,#7 ; IF NUMBER, ADD BIAS-30 (LF+7=11H) LESS_A: ADD A,#30H ; MAKE HEX DISP FORMAT (30H+11H=41H='A') XCH A,B ; LSN IN A, MSN IN B (N=NIBBLE) CJNE A,#LF,$+3 ; < 10D? JC LESS10 ADD A,#7 LESS10: ADD A,#30H ; MAKE DISPLAY FORMAT XCH A,B ; LSN IN B, MSN IN A RET ; IF A PRINTABLE CHAR PRINT IT ELSE PRINT "." CK_PR: ; 18H:19H=START OF LINE, 1CH:1DH = END OF LINE IF (SMALL_SCRN=0) MOV 5,#' ' MOV A,#D_CHR LCALL 30H ; PRINT SPACE ENDIF PR_LP: MOV DPL,18H ; BEGINNING OF CURRENT LINE MOV DPH,19H MOVX A,@DPTR JNB 21H.2,PR_CODE ; CODE? CLR A MOVC A,@A+DPTR PR_CODE: JNB 21H.3,PR_DATA ; DATA? MOV R1,DPL ; INDIRECT FOR INTERNAL DATA MOV A,@R1 PR_DATA: INC DPTR MOV 18H,DPL ; SAVE POINTER MOV 19H,DPH TLE A,#31,PDOT ; CONTROL CHAR='.' TLE A,#126,CKOK ; PRINT IT PDOT: MOV A,#'.' ; FORCE A PERIOD CKOK: MOV 5,A MOV A,#D_CHR ; PRINT CHAR LCALL 30H MOV A,18H CJNE A,1CH,CK_PR ; NEXT LINE YET? MOV A,19H CJNE A,1DH,CK_PR RET ; ;--------------------------DO_DISPLAY---------------------------------------- ; DO_DISPLAY: ; LJNB 47,DUMMY ; CMD MODE? MOV 21H,#80H ; ZERO FLAGS ACALL PEEK ; PEEK AT NEXT CHAR CJNE A,#'A',$+3 ; COULD IT BE A NUMBER? JC NO_M ; YES, NO SPECIAL MODIFIERS ACALL GCI ; NO, GET CHAR AND BUMP POINTER CLR ACC.5 ; MAKE UPPER CASE (I HOPE) CJNE A,#'C',$+5 ; 'C' OR LESS? (CODE MEMORY) SETB 21H.2 ; YES, FLAG CODE DISPLAY CJNE A,#'D',$+5 ; DATA? SETB 21H.3 ; YES, INTERNAL DATA DISPLAY CJNE A,#'P',$+5 ; PRINT? ('M' IS OPTIONAL) SETB 21H.1 ; SETB 21H.0 ; FORCE THE M CJNE A,#'M',$+5 ; EXTERNAL MEMORY? NO_M: SETB 21H.0 ; YES, OR WE CAME HERE BY DEFAULT MOV A,21H ; GET THE BYTE ANL A,#07FH ; MASK OUT RESTART BIT JNZ $+5 ; MODS SET? D_ERR: LJMP D_ERROR ; NO, DIDN'T SET ANY FUNCTIONS JB 21H.1,NO_MOD ; SKIP IF PRINT SET ('M' ASSUMED) ACALL PEEK ; LOOK FOR A 'P' NOW CJNE A,#'A',$+3 ; COULD IT BE A NUMBER? JC NO_MOD ; YES ACALL GCI ; NO, GET CHAR AND BUMP POINTER CLR ACC.5 ; UPPER CASE CJNE A,#'P',D_ERR ; PRINT? SETB 21H.1 ; YES NO_MOD: ACALL E2VAR ; TWO VARIABLES REQUIRED, START & END ACALL G2VAR ; START 1CH:1DH, END 1AH:1BH LCALL VAL_TWO ; START < END? JNC DIS_2OK ; YES,DIS_2OK CLR A LJMP 30H ; NO, BACK TO BASIC (MSG SENT) DIS_2OK: MOV A,#0F8H ANL 1CH,A ; MAKE IT AN 8 BYTE BOUNDRY IF (SMALL_SCRN=0) JB 21H.1,LOOP1 ; IF NOT PRINTING CHAR, 16 BYTE MOV A,#0F0H ANL 1CH,A ENDIF LOOP1: CLR C ; CHECK IF STARTING ADDRESS <= END MOV A,1AH SUBB A,1CH ; SUBTRACT IT AND CHECK FOR CARRY MOV A,1BH ; IS EASIER SUBB A,1DH JNC LOOP2 ; START <= END? CLR A ; YES! GO BACK TO COMMAND MODE LJMP 30H LOOP2: ACALL CRLF ; SEND CRLF TO CONSOLE IF (DEC_HDR) MOV R2,1DH ; STARTING ADDR MOV R0,1CH MOV A,#154 ; CONVERT TO FP AND PUT TOS LCALL 30H MOV A,#144 ; PRINT FP FROM TOS LCALL 30H MOV A,16H ; CONSOLE OUTPUT POSITION CJNE A,#6,$+3 ; POS 7? JNC SPCOK ; = OR > LCALL SPCIT ; PRINT SPACES UNTIL 7 SPCOK: ENDIF IF (SMALL_SCRN=0) MOV R1,1CH ; DISPLAY STARTING ADDRESS MOV R3,1DH ; ON CONSOLE MOV 18H,R1 ; SAVE START FOR PRINT MOV 19H,R3 CLR N_L0 ; USE LEADING ZEROES MOV A,#D_HEX LCALL 30H ELSE MOV 18H,1CH ; SAVE START FOR PRINT MOV 19H,1DH MOV A,1DH ; MSD OF ADDR ACALL HEX_MAKE ; MAKE HEX ACALL D_BYTES ; PUT IT ON CONSOLE MOV A,1CH ; LSD ACALL HEX_MAKE ACALL D_BYTES MOV R5,#' ' ; SPACE SEP MOV A,#D_CHR LCALL 30H ENDIF LOOP3: MOV DPL,1CH ; SETUP TO READ 8/16 BYTES MOV DPH,1DH ; ADDRESS TO DPTR JNB 21H.0,NO_MEM ; IF NOT MEM MOVX A,@DPTR ; READ THE BYTE NO_MEM: JNB 21H.2,NO_COD ; IF NOT CODE DISPLAY CLR A MOVC A,@A+DPTR NO_COD: JNB 21H.3,NO_DAT ; NOT DATA MOV R1,DPL ; INDIRECT ADDRESSING FOR INTERNAL DATA MOV A,@R1 NO_DAT: INC DPTR ; POINT TO NEXT BYTE MOV 1CH,DPL ; SAVE THE ADDRESS MOV 1DH,DPH IF (SMALL_SCRN>0) ACALL HEX_MAKE ; MAKE HEX ACALL D_BYTES ; AND PUT ON CONSOLE MOV R5,#' ' MOV A,#D_CHR LCALL 30H ; OUTPUT SPACE MOV A,1CH ELSE MOV R1,A ; OUTPUT THE BYTE! THE OPBYTE MOV R3,#0 ; WANTS 16 BITS IN R3:R1 SETB N_L0 ; SUPPRESS LEADING ZEROES MOV A,#D_HEX LCALL 30H ; DOIT! MOV A,1CH JB 21H.1,CK_LOOP ; IF PRINT CHECK FOR 8 BYTE BOUNDRY ANL A,#0FH ; 16 BYTE BOUNDRY? JNZ LOOP3 ; NO, GOTO LOOP3 SJMP LOOP1 ; YES, START NEW LINE ENDIF CK_LOOP: ANL A,#07H ; 8 BYTE BOUNDRY? JNZ LOOP3 ; NO, CONTINUE ACALL CK_PR ; YES, PRINT THE CHARS NEXT SJMP LOOP1 ; BURN_EPROM: ; PROGRAM EPROM-CMD=PRG.[F] RAM-START,END,EPROM-START JB 47,$+6 LJMP DUMMY ; NOT IN CMD MODE MOV 21H,#80H ; CLEAR FLAGS LCALL PEEK CJNE A,#'A',$+3 ; NUMBER? JC NO_FAST ; YES, NOT FAST CLR ACC.5 ; MAKE UPPER CASE CJNE A,#'I',NO_INTEL ; 'INTELligent?' ACALL GCI ; GET CHAR AND INC BASIC POINTER SETB 33H ; INTELLIGENT MOV DPTR,#298 ; INTELLIGENT TIMING SJMP DO_BURN NO_INTEL: CJNE A,#'E',NO_FAST ; EEPROM/RAM? ACALL GCI ; GET CHAR AND INCR BASIC POINTER MOV 40H,#0FEH ; .5ms TIMING MOV 41H,#033H ; DITTO SJMP DO_BURN1 NO_FAST: MOV DPTR,#296 ; PROG WIDTH NORMAL CLR 33H ; NORMAL WIDTH DO_BURN: MOVX A,@DPTR MOV 40H,A ; HIGH BYTE INC DPTR MOVX A,@DPTR MOV 41H,A ; LOW BYTE-TIMING PULSE WIDTH DO_BURN1: ACALL E3VAR ; PUT NEXT 3 EXP ON STACK ACALL G3VAR ; POP AND PUT IN USER AREA LCALL VAL_THREE ; CHECK FOR VALID ADDRESSES JNC BURN_3OK CLR A LJMP 30H BURN_3OK: MOV A,18H ; GET LSB (EPROM START ADDRESS) JNZ DEC_1 ; LSB>1, LSB=LSB-1 DEC 19H ; LSB=0, MSB=MSB-1 DEC_1: DEC 18H ; LSB=LSB-1 ; NOW SETUP COUNT (END-START+1) CLR C ; CHECK FOR END>START AND COMPUTE # BYTES MOV A,1AH ; LSB END SUBB A,1CH ; END-START (LSB) XCH A,1BH ; SAVE LSB, GET MSB SUBB A,1DH ; END-START (MSB W/C) JNC OK_END LJMP ADDBAD ; START >END OK_END: XCH A,1BH ; A=LO,1BH=HI COUNT CLR C ADDC A,#1 ; FOR COUNT JNC UPLO ; NO CARRY TO MSB INC 1BH ; CARRY+MSB=MSB UPLO: MOV 1AH,A ; LSB TO 1EH ; NOW ALERT USER TO INSERT EPROM AND APPLY POWER ACALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH P_MSG ; POWER MSG ADDRESS MOV R1,#LOW P_MSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H ACALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH RMSG ; READY MSG MOV R1,#LOW RMSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H MOV A,#G_CON ; GET CHAR LCALL 30H ACALL CRLF MOV R3,#HIGH IF_MSG ; IFERR MSG ADDRESS MOV R1,#LOW IF_MSG SETB R_MSG MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H ; NOW SETUP REGS FOR LCALL AND TURN ON VPP CLR P1.5 ; POWER ON MOV R3,1DH ; RAM START HI MOV R1,1CH ; RAM START LOW MOV R2,19H ; EPROM START-1 HI BYTE MOV R0,18H ; LO MOV R7,1BH ; COUNT HI MOV R6,1AH ; LO MOV A,#4 ; BURN-BABY-BURN, BASIC WILL HANDLE ERRORS! LCALL 30H SETB P1.5 ; TURN OFF POWER ACALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH O_MSG ; POWER OFF MSG ADDRESS MOV R1,#LOW O_MSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H CLR A LJMP 30H ; DONE ; ;-------------------------------MOV_MEM-------------------------------------- ; MOV_MEM: ; MOVE DATA OR CODE MEMORY M.[C] SOURCE,END,TARGET LJNB 47,DUMMY ; COMMAND MODE? MOV 20H,#0 ; CLR REMAINDER MOV 21H,#80H ; CLR FLAGS ACALL PEEK ; SEE IF IT'S CODE CJNE A,#'A',$+3 ; NUMBER? JC N_MC ; YES, NOT MOVE CODE ACALL GCI ; GET CHAR AND BUMP POINTER CLR ACC.5 ; MAKE UPPER CASE CJNE A,#'C',$+5 ; CODE MEMORY? SETB 21H.0 ; YES,CODE MEMORY IS SOURCE N_MC: ACALL E3VAR ; 3 NUMBERS IN ACALL G3VAR ; FROM 1CH:1DH,END 1AH:1BH, TO 18H:19H ; CHECK FOR INVALID START,END & MEM WRAP LCALL VAL_THREE ; CHECK ALL THREE VARIABLES MOV 1EH,R1 ; SAVE LO COUNT-1 MOV 1FH,R2 ; HI COUNT-1 JNC $+6 ; IF START <= END & NO WRAP CLR A ; PARAM ERROR LJMP 30H ; QUIT! ; COMPUTE SIZE IN 16 BYTE BLOCKS W/REMAINDER (SHIFT RIGHT A NIBBLE) ; THE LOWEST BYTE COUNT NIBBLE WILL BE THE REMAINDER (#BYTES/16) CLR C ; HAVE TO MAKE COUNT RIGHT MOV A,#1 ; ADD 1 ADDC A,1EH ; TO LOW BYTE MOV R7,A ; SAVE LOW BYTE COUNT MOV A,#0 ; ADD CARRY TO HI BYTE ADDC A,1FH ; HI IN ACC (BYTE COUNT IS NOW OK) MOV R0,#7 ; POINT TO R7 XCHD A,@R0 ; A=HI,REM R7=LO,MED (NIBBLES) XCH A,R7 ; EXCHANGE BYTES:A=LO,MED R7=HI,REM SWAP A ; A=MED,LO NIBBLES MOV R5,A ; SAVE LOW BLOCK-COUNT BYTE MOV A,R7 ; HI,REM ANL A,#0F0H ; LOSE THE REM SWAP A ; NOW HAVE HIGH BLOCK-COUNT BYTE MOV R6,A ; SAVE IT ANL 7,#0FH ; LOSE HIGH NIBBLE R7=0,REMAINDER MOV A,R7 JZ CKOVER ; REMAINDER IS 0! SETB 21H.2 ; PARTIAL BLOCK TO MOVE MOV 20H,R7 ; SAVE COUNT ; CHECK FOR TARGET BLOCK WITHIN SOURCE BLOCK (OVERLAPPING BLOCKS) ; FIRST CHECK FOR SOURCE HEAD > TARGET HEAD CKOVER: AJB 21H.0,MOVH ; IF CODE MOVE, CAN'T OVERLAP CLR C MOV A,18H ; TARGET LOW SUBB A,1CH ; SOURCE LOW MOV A,19H ; TARGET HI SUBB A,1DH ; SOURCE HI JNC $+4 ; SOURCE HEAD < TARGET, CHECK FURTHER AJMP MOVH ; SOURCE > TARGET, OVERLAP IS OK! ; CHECK FOR 1ST BYTE .LE. (< OR =) END, CLR C ; CHECK FOR TARGET START <= SOURCE END MOV A,1AH ; SOURCE END SUBB A,18H ; END-TARGET START MOV A,1BH SUBB A,19H JC MOVH ; TARGET START > SOURCE ENDING ADDR, OK! SETB 21H.1 ; FLAG TAIL-TO-TAIL MOVE-OVERLAPPING ADDR ; NOW SETUP PARAMS FOR TAIL-TO-TAIL MOVE CLR C ; COMPUTE TARGET END BYTE (TAIL) MOV A,18H ; TARGET HEAD ADDC A,1EH ; THE OFFSET VALUE WE SAVED MOV 18H,A ; TARGET END LOW BYTE MOV A,19H ; HI BYTE ADDC A,1FH MOV 19H,A ; TARGET END HI BYTE SJMP RDYMOV MOVH: ; HEAD-TO-HEAD COPY MOV 1AH,1CH ; SOURCE POINTER LO MOV 1BH,1DH ; HI, TARGET IN 18H:19H RDYMOV: MOV 1CH,R5 ; BLOCK COUNT MOV 1DH,R6 ; HI BYTE PUSH 8 ; BORROW SOME REGS FROM BASIC PUSH 9 PUSH 0AH PUSH 10H PUSH 12H ; DON'T FORGET TO PUT THEM BACK MOV 12H,#16 ; SETUP FOR BLOCK MOVE MOV A,1CH ; BLOCK COUNT JNZ DO_MOV ; NOT 0? MOV A,1DH ; HI BYTE JNZ DO_MOV ; NOT 0? SJMP BY_MOV ; YES, JUST REMAINDER TO MOVE DO_MOV: ACALL MOVBLK BY_MOV: JNB 21H.2,M_DON ; REMAINDER? MOV 12H,20H ; YES SET SIZE MOV 1CH,#1 ; AND BLOCK COUNT=1 ACALL MOVBLK M_DON: POP 12H ; RESTORE BASIC'S REGS POP 10H POP 0AH POP 9 POP 8 CLR A LJMP 30H ; MOVBLK: ; MOVE BLOCK OF DATA ; 12H=SIZE, 1AH:1BH=SOURCE,18H:19H=TARGET,1CH:1DH=#BLOCKS ; BLOCKS MAY BE 1=16 BYTES AND HEAD-TO-HEAD OR ; TAIL-TO-TAIL (OVERLAPPING BLOCKS) MOV R0,12H ; BLOCK SIZE JNB 21H.1,MRTL ; TAIL TO TAIL MOVE? MOV R1,12H ; YES, WE ARE POINTING AT THE END! DEC R1 ; BACKUP POINTER SIZE-1 CLR C MOV A,1AH ; LO POINTER SUBB A,R1 MOV 1AH,A PUSH 1AH ; SAVE FOR LATER (NEW END) MOV A,1BH ; HI POINTER SUBB A,#0 MOV 1BH,A PUSH 1BH ; SAVE FOR LATER MRTL: MOV DPL,1AH ; FROM LO MOV DPH,1BH ; FROM HI MRLP: JB 21H.0,$+7 ; CODE? MOVX A,@DPTR ; GET A BYTE JNB 21H.0,$+5 ; NO CODE? CLR A MOVC A,@A+DPTR INC DPTR MOV @R0,A ; SAVE IN A REG DJNZ R0,MRLP ; DO [R0] TIMES JB 21H.1,$+12 ; TAIL COPY? MOV 1AH,DPL ; SAVE POINTER MOV 1BH,DPH JNB 21H.1,RMTL ; NO TAIL COPY? POP 1BH ; END POINTER FOR MEM TO REG MOVE IS +1 OFF! POP ACC ; LO BYTE CLR C SUBB A,#1 ; ONE LESS MOV 1AH,A ; SAVE IT JNC $+4 ; CARRY GENERATED? DEC 1BH ; YES, DEC HI BYTE MOV R0,12H ; COUNT DEC R0 ; BACKUP POINTER SIZE-1 CLR C MOV A,18H ; LO POINTER SUBB A,R0 MOV 18H,A PUSH 18H ; SAVE FOR LATER (NEW END) MOV A,19H ; HI POINTER SUBB A,#0 MOV 19H,A PUSH 19H ; SAVE FOR LATER RMTL: MOV DPL,18H ; "TO" POINTER MOV DPH,19H MOV R0,12H ; COUNT/INDEX RMLP: MOV A,@R0 ; GET BYTE MOVX @DPTR,A ; STORE IT INC DPTR DJNZ R0,RMLP ; DO [R0] TIMES JB 21H.1,$+12 ;TAIL COPY? MOV 18H,DPL ; SAVE POINTER MOV 19H,DPH JNB 21H.1,UPDC ; NO TAIL COPY? POP 19H ; SAVE END POINTER HI ( +1 OFF TOO!) POP ACC ; LO CLR C SUBB A,#1 ; ONE LESS MOV 18H,A ;SAVE IT JNC $+4 ; CARRY? DEC 19H ; YES, DEC HI BYTE ; NOW UPDATE THE BLOCK COUNTER UPDC: CLR C MOV A,1CH ; BLOCK CNT LO SUBB A,#1 ; DEC MOV 1CH,A MOV A,1DH ; HI SUBB A,#0 MOV 1DH,A JNZ AGAIN ; HI = 0? MOV A,1CH ; YES JNZ AGAIN ; LOW TOO? RET ; YES, WE ARE DONE AGAIN: AJMP MOVBLK ; NEXT BLOCK ; ; ---------------------------------FIL_BLK-------------------------------- ; FIL_BLK: ; FILL A BLOCK OF RAM PARAM= START,END,FILL_BYTE ACALL E3VAR ; GET 3 PARAMS ACALL G3VAR ; PUT IN REGS LCALL VAL_TWO ; CHECK END>START JNC FIL_2OK ; VALID? CLR A LJMP 30H ; NO, RETURN (MSG SENT) FIL_2OK: MOV DPH,1DH ; HI TO ADDRESS MOV DPL,1CH ; LO F_LOOP1: CLR C ; CHECK FOR DONE OR START>END MOV A,1AH ; END ADDRESS SUBB A,DPL ; -CURRENT LO BYTE MOV A,1BH SUBB A,DPH ; -HI BYTE JNC F_LOOP ; DONE? (DPTR>END) CLR A ; YES, RETURN TO BASIC LJMP 30H ; F_LOOP: MOV A,18H ; FILL BYTE MOVX @DPTR,A ; STORE IT INC DPTR ; NEXT BYTE SJMP F_LOOP1 ; ; ;-----------------------------VER_MEM---------------------------------------- ; VER_MEM: ; VERIFY A BLOCK OF MEMORY VER.[C] SOURCE-START,S-END,TARGET-START LJNB 47,DUMMY ; COMMAND MODE? MOV 21H,#80H ; CLR FLAGS ACALL PEEK ; SEE IF IT'S CODE CJNE A,#'A',$+3 ; NUMBER? JC N_VC ; YES, NOT VERIFY CODE ACALL GCI ; GET CHAR AND BUMP POINTER CLR ACC.5 ; MAKE UPPER CASE CJNE A,#'C',$+5 ; CODE MEMORY? SETB 21H.0 ; YES,CODE MEMORY IS SOURCE N_VC: LCALL E3VAR ; 3 NUMBERS IN LCALL G3VAR ; SOURCE 1DH:1CH,END 1BH:1AH, TARGET 19H:18H LCALL VAL_THREE ; SOURCE END JNC VER_CONT CLR A LJMP 30H ; DONE, BACK TO BASIC VER_CONT: MOV DPL,1CH ; S-LO BYTE MOV DPH,1DH ; S-HI MOVX A,@DPTR ; GET BYTE TO COMPARE JNB 21H.0,VER_M ; IS CODE SOURCE? CLR A ; YES, CLR A FOR POINTER MOVC A,@A+DPTR ; GET BYTE TO COMPARE VER_M: MOV R0,A ; SAVE IT MOV DPH,19H ; TARGET HI MOV DPL,18H ; LO MOVX A,@DPTR ; GET BYTE CJNE A,0,VER_BAD ; =? VER_OK: INC DPTR ; INC TARGET ADDR MOV 18H,DPL MOV 19H,DPH ; AND SAVE IT MOV DPL,1CH ; INC SOURCE TOO MOV DPH,1DH INC DPTR MOV 1CH,DPL ; AND SAVE IT MOV 1DH,DPH SJMP VER_LOOP ; DO IT AGAIN VER_BAD: ACALL VER_NOT ; NO, PRINT ERROR MSG SJMP VER_OK VER_NOT: ; VERIFY ERROR-PRINT MSG THEN RESTORE DPTR FOR RETURN ; NORMALLY WE WOULD EXPECT ONLY A FEW BYTES TO DIFFER ; WHEN VERIFYING A COPY, SO DUMP 8 BYTES FROM THE SOURCE ; AND TARGET BLOCKS WHEN AN ERROR OCCURS LCALL CRLF MOV A,1DH ; S-HI LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV A,1CH ; S-LO LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV R5,#' ' ; SPACE MOV A,#D_CHR LCALL 30H MOV R0,#8 ; NUMBER BYTES TO DUMP S_DMP: PUSH 0 ; SAVE COUNT MOV DPH,1DH ; HI MOV DPL,1CH ; LO JB 21H.0,S_COD ; CODE? MOVX A,@DPTR ; GET BYTE SJMP N_COD S_COD: CLR A MOVC A,@A+DPTR ; CODE BYTE N_COD: MOV 1DH,DPH ; SAVE HI MOV 1CH,DPL ; SAVE LO LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV R5,#' ' ; SPACE MOV A,#D_CHR LCALL 30H POP 0 ; COUNT DJNZ R0,S_DMP1 ; DONE? SJMP T_DMP ; YES S_DMP1: MOV DPL,1CH ; LO MOV DPH,1DH ; HI INC DPTR ; NEXT BYTE MOV 1DH,DPH MOV 1CH,DPL SJMP S_DMP ; AGAIN T_DMP: LCALL CRLF MOV R0,#8 ; COUNT PUSH 0 ; SAVE COUNT MOV A,19H ; T-HI LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV A,18H ; T-LO LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV R5,#' ' MOV A,#D_CHR LCALL 30H ; OUTPUT SPACE MOV DPL,18H ; TARGET LO MOV DPH,19H ; HI SJMP T_SKP ; SKIP FIRST TIME INC (SET UP FOR RET) T_DMP1: MOV DPL,18H ; TARGET LO MOV DPH,19H ; HI INC DPTR T_SKP: MOVX A,@DPTR ; GET BYTE MOV 18H,DPL ; SAVE CURRENT LO MOV 19H,DPH ; SAVE CURRENT HI LCALL HEX_MAKE ; CONVERT TO HEX LCALL D_BYTES ; PRINT IT MOV R5,#' ' MOV A,#D_CHR LCALL 30H ; OUTPUT SPACE POP 0 ; COUNT DJNZ R0,T_DMP2 ; DONE? SJMP T_DMP3 ; YES,DONE T_DMP2: PUSH 0 ; NO, SAVE COUNT SJMP T_DMP1 ; DOIT AGAIN T_DMP3: MOV DPL,18H MOV DPH,19H RET ; ; C_ERROR: ; FORGOT COMMA BETWEEN VALUES! LCALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH C_MSG ; ERROR MSG ADDRESS MOV R1,#LOW C_MSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H CLR A ; GO BACK TO COMMAND MODE LJMP 30H ; ; GET ONE TO THREE VARIABLES FROM BUFFER AND PLACE ON TOP-OF-STACK (TOS) COMMA EQU ',' ; MACRO CAN'T PASS AS PARAM E3VAR: ACALL E1VAR ; EVALUATE 1ST EXPRESSION=>TOS ACALL GCI ; GET CHAR AND INC BASIC POINTER ACJNE A,#COMMA,C_ERROR ; MUST BE A COMMA, OR ERROR E2VAR: ACALL E1VAR ; EVAL EXP=>TOS (ENTRY FOR 2 VARS) ACALL GCI ; GET CHAR AND INC BASIC POINTER ACJNE A,#COMMA,C_ERROR E1VAR: MOV A,#E_ARG ; EVAL EXP=>TOS (JUST 1 VAR) LCALL 30H RET ; ; POP VARS OFF STACK (REVERSE ORDER OF INPUT!) G3VAR: MOV A,#G_ARG ; POP STACK TOS=>R3:R1 (HI:LO) LCALL 30H MOV 18H,R1 ; LO BYTE OF THIRD EXPRESSION IN INPUT MOV 19H,R3 ; HI OF SAME G2VAR: MOV A,#G_ARG ; ENTER HER IF YOU NEED TWO VARS LCALL 30H MOV 1AH,R1 ; LO BYTE OF SECOND EXP IN INPUT MOV 1BH,R3 ; HI OF SAME G1VAR: MOV A,#G_ARG LCALL 30H MOV 1CH,R1 ; LO BYTE OF 1ST EXP IN INPUT MOV 1DH,R3 ; HI RET ; ; ; VAL_TWO: ; CHECK FOR START 0 JNC VER_OVF ; OK, NOW CHECK TARGET+COUNT<=0FFFFH RET ; DON'T BOTHER VAL_TWO DIED VER_OVF: MOV A,18H ; GET TARGET LO ADDC A,R1 ; PLUS COUNT LO MOV R3,A ; TARGET END LO MOV A,19H ; TARGET HI ADDC A,R2 ; PLUS COUNT HI MOV R4,A ; TARGET END HI JNC OVF_END ; NO CARRY = NO WRAP LCALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH BADEND ; BADEND MSG ADDRESS MOV R1,#LOW BADEND SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H SETB C OVF_END: RET ; ; SPCIT: ; PRINT UNTIL PHEAD (16H) =7 MOV 5,#' ' ; SPACE MOV A,#D_CHR ; PRINT IT LCALL 30H MOV A,16H TLE A,#5,SPCIT ; PRINT ANOTHER RET ; ; ; D_ERROR: ; INVALID DISPLAY MODIFIER LCALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH MSG_D ; ERROR MSG ADDRESS MOV R1,#LOW MSG_D SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H CLR A ; GO BACK TO COMMAND MODE LJMP 30H ; RESULT IS NEG, START>END! ADDBAD: LCALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH BADADD ; BADADD MSG ADDRESS MOV R1,#LOW BADADD SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H CLR A ; ABORT LJMP 30H ; DUMMY: ; TRYING TO USE COMMAND IN RUN MODE-ERROR MSG TO CONSOLE LCALL CRLF ; SEND CRLF TO CONSOLE MOV R3,#HIGH D_MSG ; ERROR MSG ADDRESS MOV R1,#LOW D_MSG SETB R_MSG ; MSG IS IN ROM MOV A,#D_STR ; OPBYTE TO DISPLAY MSG LCALL 30H CLR A ; GO BACK TO COMMAND MODE LJMP 30H ; MSG_D: DB 'INVALID MODIFIER"' D_MSG: DB 'COMMAND MODE ONLY"' C_MSG: DB 'COMMA NEEDED BETWEEN VALUES',ROM_EOM P_MSG: DB 'INSERT EPROM,',CR,LF DB 'AND APPLY PROGRAMMING VOLTAGE',CR,LF,ROM_EOM RMSG: DB 'PRESS ANY KEY WHEN READY...',CR,LF,ROM_EOM IF_MSG: DB 'IF PROGRAMMING ERRORS,THEN REMOVE VOLTAGE',CR,LF,ROM_EOM O_MSG: DB 'REMOVE PROGRAMMING VOLTAGE!',CR,LF,ROM_EOM BADADD: DB 'START > END...ABORT!',CR,LF,ROM_EOM BADEND: DB 'TARGET + COUNT > 0FFFFH...ABORT',CR,LF,ROM_EOM ; HELP: LJNB 47,DUMMY ; COMMAND MODE ONLY LCALL PEEK ; NEXT CHAR CJNE A,#CR,$+5 ; CR? (NO PARAM OR JUST H ON 2ND TIME) SJMP H_HELP ; YES, I'M LOST! CJNE A,#LAST_TOK+1,$+3 ; IS IT A ROMJ (USER) COMMAND? JNC H_HELP ; NO, STILL LOST! ; LCALL GCI ; GET BYTE AND INCR POINTER ANL A,#0FH ; STRIP 10H BIT RL A ; MULTIPLY BY 2 MOV DPTR,#HELP_TAB PUSH ACC ; SAVE INDEX MOVC A,@A+DPTR ; GET HIGH BYTE OF MSG MOV R3,A POP ACC INC A MOVC A,@A+DPTR ; GET LO BYTE MOV R1,A HLP_MSG: SETB R_MSG ; MSG IN ROM MOV A,#D_STR ; DISPLAY OPBYTE LCALL 30H CLR A LJMP 30H H_HELP: MOV R3,#HIGH HLP_HLP MOV R1,#LOW HLP_HLP SJMP HLP_MSG HELP_TAB: DW DIS_HLP DW HEX_HLP DW PRG_HLP DW MOV_HLP DW HLP_HLP DW FIL_HLP DW VER_HLP ; HLP_HLP: DB 'HELP [command]',CR,LF DB 'command = DIS. HEX. MOV.',CR,LF DB ' PRG. FIL. VER.',CR,LF,ROM_EOM DIS_HLP: DB 'DIS.[[M][P],C[P],D[P]] START,END [x]=OPT',CR,LF DB 'M=RAM(OPTIONAL), C=CODE, D=DATA, P=PRINT',CR,LF DB 'DIS.[M]P DISPLAY RAM MEMORY AND PRINT',CR,LF DB 'DIS.CP DISPLAY CODE MEMORY AND PRINT',CR,LF,ROM_EOM HEX_HLP: DB 'HEX.L[P] n LOAD HEXFILE AT OFFSET n',CR,LF DB ' OFFSET = n + HEX-IMAGE ADDRESS',CR,LF DB ' P=PROMPT (>) FOR EACH LINE',CR,LF DB 'HEX.S[C] BEG,END SEND HEXFILE',CR,LF DB ' FROM BEG TO END INCLUSIVE',CR,LF DB ' C=CODE IS SOURCE',CR,LF,ROM_EOM MOV_HLP: DB 'MOV. SOURCE,END,TARGET SMART MOVE',CR,LF DB 'WILL MOVE MEMORY FROM SOURCE TO END',CR,LF DB 'INCLUSIVE, TO TARGET ADDRESS',CR,LF,ROM_EOM PRG_HLP: DB 'PRG.[I],[E] SOURCE,END,EPROM-ADDRESS',CR,LF DB 'PROGRAM AN EPROM WITH RAM DATA',CR,LF DB 'FROM SOURCE TO END INCLUSIVE.',CR,LF DB '(I=INTELLIGENT, E=RAM/EEPROM)',CR,LF,ROM_EOM FIL_HLP: DB 'FIL. START,END,8-BIT-PATTERN',CR,LF DB 'FILLS MEMORY WITH PATTERN',CR,LF,ROM_EOM VER_HLP: DB 'VER.[C] SOURCE-START,END,TARGET-START',CR,LF DB 'VERIFY SOURCE BLOCK=TARGET BLOCK',CR,LF DB 'IF ERROR OCCURS, DISPLAYS:',CR,LF DB 'SOURCE ADDR+8 BYTES ',CR,LF DB 'TARGET ADDR+8 BYTES AND CONTINUES',CR,LF,ROM_EOM ; END