; ; 8051 monitor ; ; Completed Fri Dec 13, 1996 -- J Zbiciak ; Main System Equates 0000: .equ CR , 0x0dh 0000: .equ LF , 0x0ah 0000: .equ FF , 0x0ch 0000: .equ NULL , 0x00h 0000: .equ MAXCHAR , 0x40h ; Maximum line input length 0000: .equ BS , 0x08h 0000: .equ BELL , 0x07h 0000: .equ SPC , 0x20h 0000: .equ ESC , 0x1bh 0000: .equ EOT , 0xffh 0000: .equ BKPT , 0x3fh ; my preference ;.equ TERMESC , 0x14h ; Terminal Mode escape (^T) ;.equ TERMDL , 0x12h ; Terminal Mode download re ; standard 0000: .equ TERMESC , 0x03h ; Terminal Mode escape (^C) 0000: .equ TERMDL , 0x01h ; Terminal Mode download re 0000: .equ TSTAT , 0xff25h 0000: .equ TDATA , 0xff24h 0000: .equ USTAT , 0xff27h 0000: .equ UDATA , 0xff26h 0000: .equ BAUDS , 0xff1fh 0000: .equ BAUD , 0x3fh 0000: .equ IE0V , 0x1003h 0000: .equ TF0V , 0x100bh 0000: .equ IE1V , 0x1013h 0000: .equ TF1V , 0x101bh 0000: .equ RIVTIV , 0x1023h 0000: .equ TF2V , 0x102bh 0000: .equ T2MOD , 0xC9h 0000: .equ SADEN , 0xB9h 0000: .equ SADDR , 0xA9h ; initialize program variables to upper 256 bytes of RAM onb 0000: .equ MSTART , 0x0000h ; Where to start monitor in 0000: .equ MONSTK , 0xE0h ; where to start monitor's 0000: .equ SVSTART , 0xE0h ; start of memory a 0000: .equ SVEND , 0x20h ; byte after last location 0000: .equ MPG , MSTART+0x0f00h ; page holding the 0000: .equ SVDBLK , MPG+0 ; internal-RAM save area 0000: .equ SVDCNT , (SVEND-SVSTART)&0xFF ; count of 0000: .equ SVDREG , SVDBLK+SVDCNT ; register 0000: .equ REGSTK , 0x10h ; where to "stack" register 0000: .equ ASAVE , MPG+0xF0h ; A-register save location 0000: .equ BSAVE , ASAVE+1 ; B-register " " 0000: .equ R0SAVE , BSAVE+1 ; B-register " " 0000: .equ PCVAL , R0SAVE+1 ; PC " " 0000: .equ BPAD , PCVAL+2 ; Breakpoint address 0000: .equ ISBKP , BPAD+2 ; Is Breakpoint? flag 0000: .equ DEBUG , ISBKP+1 ; Excerpted code for breakp 0000: .equ DBGE , (DEBUG+3)&0xFFh ; LSB of end-of-exc 0000: .equ DBGL , DEBUG&0xFFh ; LSB of DEBUG addr 0000: .equ DBGH , DEBUG/256 ; MSB of DEBUG addr 0000: .equ QUIET , DEBUG+3 ; Quiet-mode flag 0000: .equ ARGV1L , 0x0004h ; R4 0000: .equ ARGV1H , 0x0005h ; R5 0000: .equ ARGV2L , 0x0006h ; R6 0000: .equ ARGV2H , 0x0007h ; R7 0000: .equ CKSUM , 0x0006h ; R6 0000: .equ CKERR , 0x0007h ; R7 0000: .equ COUNT , 0x0002h ; R2 0000: .equ TEMP , 0x0003h ; R3 0000: .equ BUFF , 0x80h ; 0x80h - 0xDBh char buffer 0000: .equ SLFMOD , 0x1000h ; location where self-modif 0000: .equ P2SAVE , 0x30h ; location user should save 0000: .org MSTART 0000: 02 08 20 ljmp main ; special function register addresses 0030: .org MSTART+0x0030h 0030: C0 82 enter: push DPL ; save DPTR 0032: C0 83 push DPH 0034: C0 D0 push PSW ; save PSW 0036: C2 D5 clr 0xD5h ; clear "check for bkpt" fl 0038: 80 08 sjmp cont 003A: C0 82 benter: push DPL ; entry point for breakpoin 003C: C0 83 push DPH 003E: C0 D0 push PSW 0040: D2 D5 setb 0xD5h ; set "check for bkpt" flag 0042: C2 D3 cont: clr 0xD3h ; set PSW for Bank 0 0044: C2 D4 clr 0xD4h ; Bank 0 --> R0-R7 are in 0 0046: 90 0F F0 mov DPTR,#ASAVE 0049: F0 movx @DPTR,A ; save A 004A: A3 inc DPTR 004B: E5 F0 mov A,B 004D: F0 movx @DPTR,A ; save B 004E: A3 inc DPTR 004F: E8 mov A,R0 0050: F0 movx @DPTR,A ; save R0 0051: 90 0F 00 mov DPTR,#SVDBLK ; point to memory-save aren 0054: 78 E0 mov R0,#SVSTART ; Point R0 to start of save 0056: E6 ent0: mov A,@R0 ; grab a byte from internal 0057: F0 movx @DPTR,A ; write byte to sav 0058: A3 inc DPTR 0059: 08 inc R0 005A: B8 20 F9 cjne R0,#SVEND,ent0 ; loop until all are saved ; move the 6 SFRs that the monitor modifies into internal RA 005D: A8 D0 mov R0,PSW 005F: D0 D0 pop PSW ; restore saved PSW 0061: D0 83 pop DPH ; restore saved DPTR 0063: D0 82 pop DPL 0065: D0 F0 pop 0xf0h ; get PC value from 'lcall 0067: D0 E0 pop 0xe0h ; if this is a breakpoint, 0069: 85 81 10 mov REGSTK,SP ; save SP 006C: 75 81 10 mov SP,#REGSTK ; point stack to lower RAM 006F: C0 D0 push PSW 0071: C0 82 push DPL 0073: C0 83 push DPH 0075: C0 A8 push IE 0077: C0 B8 push IP ; Note: a race condition ex ; I should probably clear t 0079: 75 A8 00 mov IE,#0x00h ; clear interrupt-enable 007C: 88 D0 mov PSW,R0 007E: C0 E0 push ACC ; save 'A' for the moment 0080: 90 0F 40 mov DPTR,#SVDREG 0083: 78 10 mov R0,#REGSTK ; initialize R0 to point to 0085: E6 entCP: mov A,@R0 0086: F0 movx @DPTR,A ; save register @R0 0087: 08 inc R0 0088: A3 inc DPTR 0089: B8 17 F9 cjne R0,#REGSTK+7,entCP ; saves all 6 SFRs 008C: D0 E0 pop ACC ; restore 'A' 008E: 20 D5 05 jb 0xD5h,bk1 ; if clear, no breakpt, els 0091: 74 03 mov A,#0x03 ; If not bkpt, put 0093: 75 F0 10 mov B,#0x10 ; (1003-3=1000) ; now, we've managed to save almost everything ; still to save is the PC value. The PC is in B:A 0096: 90 0F F3 bk1: mov DPTR,#PCVAL 0099: 24 FD add A,#-3 ; adjust PC value down by 3 009B: FA mov R2,A ; save adjusted LSB in R2 009C: F0 movx @DPTR,A ; write adjusted LS 009D: E5 F0 mov A,B 009F: 34 FF addc A,#-1 ; finish adjustment 00A1: FB mov R3,A ; save adjusted MSB in R3 00A2: A3 inc DPTR 00A3: F0 movx @DPTR,A ; write adjusted MS ; start normal routine here 00A4: 75 F0 00 mov B,#0 ; B is used for "Is Breakpo 00A7: 30 D5 1A jnb 0xD5h,entrNB ; Don't even compare if not 00AA: 90 0F F5 mov DPTR,#BPAD ; check PC for breakpoint m 00AD: E0 movx A,@DPTR ; load LSB of break 00AE: B5 02 13 cjne A,002h,entrNB ; No match, not a breakpoin 00B1: A3 inc DPTR 00B2: E0 movx A,@DPTR ; load MSB of break 00B3: B5 03 0E cjne A,003h,entrNB ; No match, not a breakpoin 00B6: 51 AB acall clrbkp ; clear the breakpoint 00B8: 90 0B D7 mov DPTR,#BRSTOP ; let user know we've stope 00BB: 91 2D acall printc ; 00BD: 91 AA acall cC ; clear bkpoint address 00BF: 75 F0 01 mov B,#1 00C2: 80 10 sjmp entrFN ; finish up entry code 00C4: 90 0F 40 entrNB: mov DPTR,#SVDREG ; Wasn't a breakpoint, fix 00C7: E0 movx A,@DPTR 00C8: 24 02 add A,#2 00CA: F0 movx @DPTR,A 00CB: E4 clr A ; Point PCVAL to 0x1000h 00CC: 90 0F F3 mov DPTR,#PCVAL 00CF: F0 movx @DPTR,A 00D0: A3 inc DPTR 00D1: 74 10 mov A,#0x10h 00D3: F0 movx @DPTR,A 00D4: 90 0F F7 entrFN: mov DPTR,#ISBKP ; point to "Is Breakpoint" 00D7: E5 F0 mov A,B 00D9: F0 movx @DPTR,A 00DA: 75 81 E0 mov SP,#0xe0h ; initialize stack pointer 00DD: 90 00 DD parser: mov DPTR,#parser ; push parser's address 00E0: C0 82 push DPL ; so that internal routines 00E2: C0 83 push DPH 00E4: 90 0F FB parse: mov DPTR,#QUIET 00E7: E0 movx A,@DPTR 00E8: F5 10 mov 0x10h,A 00EA: 90 08 61 mov DPTR,#PROMPT 00ED: 91 2D acall printc ; print the prompt 00EF: 75 A0 0F mov P2,#0x0Fh ; point P2 to monitor scrat 00F2: 31 4A acall readln ; get an input line 00F4: 79 80 mov R1,#BUFF ; point R1 to buffer 00F6: 7A FC mov R2,#-4 ; clear command count 00F8: E3 movx A,@R1 ; grab input byte into R3 00F9: 91 4C acall upcase ; make command uppercase 00FB: FB mov R3,A 00FC: 09 inc R1 00FD: E3 movx A,@R1 00FE: 91 4C acall upcase ; make command uppercase 0100: FC mov R4,A 0101: 90 0C B9 parse0: mov DPTR,#clt ; point DPTR to command loo 0104: EA parse1: mov A,R2 0105: 24 04 add A,#4 0107: FA mov R2,A 0108: 93 movc A,@DPTR+A ; grab byte from lookup tbl 0109: 60 38 jz parseE ; end of table 010B: B5 03 F6 cjne A,3,parse1 ; not equal, keep looking ; ok, I've found a match if I'm here. Offset into ; time to check for second letter: 010E: A3 inc DPTR 010F: EA mov A,R2 0110: 93 movc A,@DPTR+A ; get second byte from look 0111: 60 04 jz parse2 ; no second letter, done pa 0113: B5 04 EB cjne A,4,parse0 ; doesn't match, keep looki ; found a double-letter command 0116: 09 inc R1 ; found a single-letter command 0117: 0A parse2: inc R2 0118: EA mov A,R2 0119: 93 movc A,@DPTR+A 011A: C0 E0 push ACC 011C: 0A inc R2 011D: EA mov A,R2 011E: 93 movc A,@DPTR+A 011F: C0 E0 push ACC 0121: 91 44 acall skipsp ; skip blanks 0123: 31 D5 acall getPC ; set default ARGV1 to be P 0125: 31 A1 acall atoh ; convert ARGV1 to hex 0127: F5 05 mov ARGV1H,A ; store ARGV1 0129: 85 F0 04 mov ARGV1L,B ; 012C: 91 44 acall skipsp ; get to next arguement 012E: 74 00 mov A,#0x00h ; 0130: 75 F0 10 mov B,#0x10h ; load a default ARGV2 0133: 31 A1 parse3: acall atoh ; 0135: F5 07 mov ARGV2H,A 0137: 85 F0 06 mov ARGV2L,B ; store argv2 013A: E5 05 mov A,ARGV1H 013C: E5 04 mov A,ARGV1L 013E: E5 07 mov A,ARGV2H 0140: E5 06 mov A,ARGV2L 0142: 22 ret ; this should jump to the s 0143: 90 09 14 parseE: mov DPTR,#ERROR 0146: 91 2D acall printc 0148: 80 9A sjmp parse ; readln ; ; uses R7 as free counter ; does not call routt until done with R7 014A: C0 83 readln: push DPH 014C: C0 82 push DPL 014E: C0 00 push 0 0150: 79 80 mov R1,#BUFF ; load buffer start locatio 0152: 78 FF mov R0,#0xFFh 0154: 90 FF FF mov DPTR,#0xFFFFh 0157: 71 AD rd3: acall gett ; wait for input from term 0159: 40 12 jc got 015B: D5 82 F9 djnz DPL,rd3 015E: D5 83 F6 djnz DPH,rd3 0161: 02 0E 76 ljmp lrd4 0164: D8 F1 rd4: djnz R0,rd3 0166: 12 0E 90 ss: lcall scrsave 0169: 79 80 mov R1,#BUFF 016B: 74 0D mov A,#CR 016D: B4 08 0E got: cjne A,#BS,rd2 ; backspace hit? 0170: B9 80 02 cjne R1,#BUFF,rd0 0173: 80 E2 sjmp rd3 0175: 19 rd0: dec R1 ; backtrack pointer 0176: 91 1A acall bsoutt ; backspace onscreen 0178: 91 10 acall soutt 017A: 91 1A acall bsoutt 017C: 80 D9 sjmp rd3 ; get next character 017E: B4 0D 0D rd2: cjne A,#CR,rd1 ; check for CR 0181: F3 movx @R1,A ; store CR 0182: 09 inc R1 0183: 91 1E acall routt ; print CR and LF 0185: E4 clr A 0186: F3 movx @R1,A ; append NULL 0187: D0 00 pop 0 0189: D0 82 pop DPL 018B: D0 83 pop DPH 018D: 22 ret 018E: 24 E0 rd1: add A,#-0x20h 0190: 50 C5 jnc rd3 ; ignore control characters 0192: 24 20 add A,#0x20h 0194: B9 C0 04 cjne R1,#(BUFF+MAXCHAR),rd5 ; check for end of buffer 0197: 91 14 acall beloutt 0199: 80 BC sjmp rd3 ; go back and wait for CR o 019B: 71 EE rd5: acall outt 019D: F3 movx @R1,A ; store in buffer 019E: 09 inc R1 019F: 80 B6 sjmp rd3 ; go back for more ; ; atoh converts a hex value in the input buffer into a value ; If there isn't a valid hex string at the current input buf ; A and B are left untouched. This allows presetting a defa ; 01A1: C0 04 atoh: push 0x4h ; push R4 01A3: C0 05 push 0x5h ; push R5 01A5: C0 E0 push ACC 01A7: E4 clr A 01A8: FC mov R4,A ; 01A9: FD mov R5,A ; intialize hex value 01AA: E3 movx A,@R1 ; get first character 01AB: 91 61 acall hexc ; convert to hex 01AD: 40 04 jc atoh3 ; valid character, continue 01AF: D0 E0 pop ACC ; invalid char, restore A a 01B1: 80 1D sjmp atoh2 01B3: ED atoh3: mov A,R5 ; shift MSB value left 4 bi 01B4: C4 swap A 01B5: FD mov R5,A ; store R5 01B6: EC mov A,R4 01B7: C4 swap A ; swap nibbles of LSB value 01B8: FC mov R4,A ; make a copy 01B9: 54 0F anl A,#0xFh ; this code relies on Bank 0 registers! :-/ 01BB: 42 05 orl 5,A ; complete the MSB value 01BD: 53 04 F0 anl 4,#0xf0h ; clear out lsnibble of LSB 01C0: E5 F0 mov A,B ; get saved char 01C2: 42 04 orl 4,A ; complete the LSB value 01C4: 09 inc R1 ; increment pointer 01C5: E3 movx A,@R1 01C6: 91 61 acall hexc ; convert to hex again 01C8: 40 E9 jc atoh3 ; only two byte value 01CA: ED atoh4: mov A,R5 01CB: 8C F0 mov B,R4 01CD: D3 setb C 01CE: D0 05 pop 0x5h ; pop & throw away old A va 01D0: D0 05 atoh2: pop 0x5h 01D2: D0 04 pop 0x4h 01D4: 22 ret ; return with value loaded i 01D5: C0 82 getPC: push DPL 01D7: C0 83 push DPH 01D9: 90 0F F3 mov DPTR,#PCVAL 01DC: E0 movx A,@DPTR ; get LSB of PCVAL 01DD: F5 F0 mov B,A 01DF: A3 inc DPTR 01E0: E0 movx A,@DPTR ; get MSB of PCVAL 01E1: D0 83 pop DPH 01E3: D0 82 pop DPL 01E5: 22 ret ;; ;; [H]elp command. Prints help text. ;; 01E6: 90 09 22 cH: mov DPTR,#HELPTX 01E9: 91 2D acall printc 01EB: 22 ret ;; ;; [T]erminal command. Enters into terminal mode ;; 01EC: 90 08 E4 cT: mov DPTR,#TERM 01EF: 91 2D acall printc ; print mode 01F1: 71 96 cT2: acall getu ; get unix character 01F3: 50 02 jnc cT3 ; jump if unix char not ava 01F5: 71 EE acall outt ; display character 01F7: 71 AD cT3: acall gett ; get from terminal keyboar 01F9: 50 F6 jnc cT2 ; try again if nothing 01FB: B4 03 02 cjne A,#TERMESC,cTT ; ^T --> exit Terminal mode 01FE: 80 0E sjmp cT4 0200: B4 01 07 cTT: cjne A,#TERMDL,cT5 ; ^R --> download file 0203: 51 13 acall cdl 0205: 90 08 E4 mov DPTR,#TERM 0208: 80 E7 sjmp cT2 ; begin again... 020A: 71 D7 cT5: acall outu ; send it to unix 020C: 80 E3 sjmp cT2 ; begin again 020E: 90 09 03 cT4: mov DPTR,#MON ; print "Monitor mode" 0211: 81 2D ajmp printc ; and return to commandlin ; General subroutines for monitor ; ; ; ; Download routine. ; ; This routine download a user specified Intel-HEX format fi 0213: 90 0B AF cdl: mov DPTR,#DLP 0216: 91 2D acall printc ; print "Filename: " string 0218: 75 A0 0F mov P2,#0x0Fh 021B: 31 4A acall readln ; get input 021D: 79 80 mov R1,#BUFF 021F: 91 44 acall skipsp ; skip spaces 0221: E3 movx A,@R1 ; get first character 0222: B4 0D 02 cjne A,#CR,dl9 ; check for return 0225: 80 75 sjmp dlexit ; exit, go back to unix pro 0227: 90 0B 4C dl9: mov DPTR,#DL ; load download message 022A: E4 dl3: clr A 022B: 93 movc A,@A+DPTR ; send 'cat' message 022C: 60 08 jz dl4 022E: 71 D7 acall outu ; print a letter of 'cat' 0230: A3 inc DPTR 0231: 80 F7 sjmp dl3 0233: 75 A0 0F mov P2,#0x0Fh 0236: E3 dl4: movx A,@R1 ; load filename 0237: 60 05 jz dl5 0239: 71 D7 acall outu ; print filename to monitor 023B: 09 inc R1 023C: 80 F8 sjmp dl4 023E: 71 AD dl5: acall gett 0240: B4 1B 02 cjne A,#ESC,dl10 ; escape hit? 0243: 80 57 sjmp dlexit 0245: 75 06 FF dl10: mov CKSUM,#0xffh ; set checksum 0248: 71 96 dl6: acall getu 024A: 50 F2 jnc dl5 ; wait for a character from 024C: B4 3A EF cjne A,#':',dl5 ; see if start of line 024F: 71 6D dl7: acall getbu ; get byte 0251: F5 02 mov COUNT,A ; save count 0253: 71 11 acall cks ; update checksum 0255: 71 6D acall getbu ; get MSB of address 0257: F5 05 mov ARGV1H,A ; save MSB 0259: 75 07 00 mov CKERR,#0 ; check for a code conflict 025C: B4 0F 02 cjne A,#0x0fh,noerr ; disallow writing to 0f00h 025F: 80 43 sjmp dlerr2 ; report the error 0261: 71 11 noerr: acall cks ; update cheksum 0263: 71 6D acall getbu ; get LSB of address 0265: F5 04 mov ARGV1L,A ; store it 0267: 71 11 acall cks ; update checksum 0269: 71 6D acall getbu ; get packet-type code (0=d 026B: B4 00 20 cjne A,#0x00h,dlfnis ; check for end-of- 026E: 71 11 acall cks ; update checksum 0270: 85 04 82 mov DPL,ARGV1L 0273: 85 05 83 mov DPH,ARGV1H ; load address of code into 0276: 71 6D dl8: acall getbu ; get byte 0278: F0 movx @DPTR,A ; store the byte 0279: 71 11 acall cks ; update checksum 027B: A3 inc DPTR 027C: D5 02 F7 djnz COUNT,dl8 ; if count not zero, get ne 027F: 71 6D acall getbu 0281: 05 06 inc CKSUM ; add one to checksum 0283: B5 06 17 cjne A,CKSUM,dlerr1 ; if not equal then print e 0286: 74 0D mov A,#CR 0288: 71 EE acall outt 028A: 71 35 acall avoutt ; show user where we're loa 028C: 80 B0 sjmp dl5 028E: 71 11 dlfnis: acall cks ; update checksum 0290: 71 6D acall getbu ; get checksum byte 0292: 05 06 inc CKSUM ; add one 0294: B5 06 06 cjne A,CKSUM,dlerr1 ; check for bad checksum 0297: 90 0B A5 mov DPTR,#DLDONE ; print successful message 029A: 91 2D acall printc 029C: 22 dlexit: ret 029D: 90 0B 51 dlerr1: mov DPTR,#DLERR 02A0: 91 2D acall printc 02A2: 80 F8 sjmp dlexit 02A4: 90 0B 74 dlerr2: mov DPTR,#DLROM 02A7: 91 2D acall printc 02A9: 80 F1 sjmp dlexit ; subroutine clrbkp ; ; move the program bytes stored in DEBUG back to the ; the program bytes stored in the user's program ; ; the MSB of BPAD is in R3 and the LSB of BPAD is in R2 ; 02AB: C0 00 clrbkp: push 0 ; Save R0 02AD: 75 A0 0F mov P2,#DBGH ; Point P2 to page w/ debug 02B0: 78 F8 mov R0,#DBGL ; Point P2:R0 to excerpted 02B2: 8A 82 mov DPL,R2 02B4: 8B 83 mov DPH,R3 ; Point DPTR to code addres 02B6: E2 cbkl: movx A,@R0 ; Grab excerpted code byte 02B7: F0 movx @DPTR,A ; Copy back to code 02B8: A3 inc DPTR ; move along 02B9: 08 inc R0 02BA: B8 FB F9 cjne R0,#DBGE,cbkl ; Break out when stepped pa 02BD: D0 00 pop 0 02BF: 22 ret ; subroutine setbkp ; ; copy code bytes in program to DEBUG, and move the program ; for 'lcall enter' into location pointed to DEBUG by BPAD. ; 02C0: 79 12 setbkp: mov R1,#0x12h ; opcode for 'lcall' 02C2: 7A 00 mov R2,#benter/256 ; MSB of monitor breakpoint 02C4: 7B 3A mov R3,#benter&0FFh ; LSB of monitor br 02C6: 75 A0 0F mov P2,#BPAD/256 02C9: 78 F5 mov R0,#BPAD&0FFh 02CB: E2 movx A,@R0 02CC: F5 82 mov DPL,A 02CE: 08 inc R0 02CF: E2 movx A,@R0 02D0: F5 83 mov DPH,A 02D2: 75 A0 0F docpy: mov P2,#DBGH 02D5: 78 F8 mov R0,#DBGL 02D7: 85 01 F0 mov B,1 02DA: 51 E4 acall st 02DC: 85 02 F0 mov B,2 02DF: 51 E4 acall st 02E1: 85 03 F0 mov B,3 02E4: E0 st: movx A,@DPTR ; copy code byte fr 02E5: F2 movx @R0,A ; save code byte @ DEBUG 02E6: E5 F0 mov A,B ; prepare trap code byte 02E8: F0 movx @DPTR,A ; write trap code t 02E9: A3 inc DPTR 02EA: 08 inc R0 02EB: 22 ret ; subroutines for variably-addressed direct addressing. ; ; these routines rely on writing a 3-byte piece of self-modi ; to the location SLFMOD for reading directly-addressed memo ; set/clr breakpoint routines are {re|ab}used cleverly here. ; clever--you decide.) Because breakpoint code only needs t ; in the breakpoint-save area *during external code executio ; locations may be reused for other purposes when inside the ; ; This code uses these locations to save the memory overwrit ; self-modifying code. Routines which need to use getD shou ; startD first, and stopD when done. The cDB routine does t ; calling startD at the top-of-loop, and stopD just before r ; ; startD: sets up the self-modifying code 02EC: C0 00 startD: push 0 02EE: D0 02 pop 2 ; Move R0 into R2 02F0: 79 E5 mov R1,#0xE5h ; opcode for 'mov A,direct' 02F2: 7B 22 mov R3,#0x22h ; opcode for 'ret' 02F4: 90 10 00 mov DPTR,#SLFMOD ; put self-modifying code a 02F7: 80 D9 sjmp docpy ; {re|ab}use the breakpoint ; getB: gets a bit of bit-addressed memory using the self ; written by startD. This code hijacks getD, so yo ; mix getB and getD calls. The bit is returned in 02F9: 74 A2 getB: mov A,#0xA2h ; 'mov C,bit' 02FB: 80 02 sjmp putB1 ; putB: puts a bit of bit-addressed memory using the self ; written by startD. This code hijacks getD, so yo ; mix getB and getD calls. The bit value is passed 02FD: 74 92 putB: mov A,#0x92h ; 'mov bit,C' 02FF: 90 10 00 putB1: mov DPTR,#SLFMOD 0302: F0 movx @DPTR,A ; getD: gets a byte of directly-addressed memory using th ; code written by startD. 0303: 90 10 01 getD: mov DPTR,#SLFMOD+1 ; point to "direct" byte 0306: E8 mov A,R0 0307: F0 movx @DPTR,A 0308: 02 10 00 ljmp SLFMOD ; call self-modifying code ; stopD: restores code overwritten by startD 030B: 7A 00 stopD: mov R2,#SLFMOD&0FFh ; setup pointer to 030D: 7B 10 mov R3,#SLFMOD/256 030F: 80 9A sjmp clrbkp ; {re|ab}use the breakpoint ; cks - send a value in register A and it will subtract it ; from the CKSUM ; info in register B is destroyed 0311: C3 cks: clr C ; clear borrow 0312: F5 F0 mov B,A ; save A 0314: E5 06 mov A,CKSUM 0316: 95 F0 subb A,B ; subtract A from LSB 0318: F5 06 mov CKSUM,A ; and save 031A: E5 F0 mov A,B ; get A back 031C: 22 ret ; coutt 031D: C0 E0 coutt: push 0xe0h ; push A 031F: 24 E0 add A,#0xE0h ; compare A 0321: 20 E7 0A jb 0xe7h,nota ; check for legal ascii val 0324: 24 A2 add A,#0xA2h ; subtract 7eh 0326: 30 E7 05 jnb 0xe7h,nota 0329: D0 E0 pop 0xe0h 032B: 71 EE acall outt 032D: 22 ret 032E: 74 2E nota: mov A,#0x2eh 0330: 71 EE acall outt 0332: D0 E0 pop 0xe0h 0334: 22 ret ; Note: dpoutt & avoutt trash A ; Write 4-nibble hex value in ARGV1 0335: E5 05 avoutt: mov A,ARGV1H 0337: 71 54 acall aoutt 0339: E5 04 mov A,ARGV1L 033B: 80 17 sjmp aoutt ; Write 4-nibble hex value in DPTR 033D: E5 83 dpoutt: mov A,DPH 033F: 71 54 acall aoutt 0341: E5 82 mov A,DPL 0343: 80 0F sjmp aoutt 0345: C0 E0 a1outt: push ACC 0347: EC mov A,R4 0348: 54 F0 anl A,#0xF0h 034A: 70 06 jnz ao1 034C: 91 10 acall soutt 034E: D0 E0 pop ACC 0350: 80 06 sjmp hxoutt 0352: D0 E0 ao1: pop ACC ; Write 2-nibble hex value in A 0354: C4 aoutt: swap A ; Put MS-nibble in lower ha 0355: 71 58 acall hxoutt ; Output MS-nibble 0357: C4 swap A ; Output LS-nibble of A 0358: C0 E0 hxoutt: push ACC 035A: 54 0F anl A,#0x0fh ; Output LS-nibble 035C: C0 82 push DPL 035E: C0 83 push DPH 0360: 90 0B 3C mov DPTR,#hexl 0363: 93 movc A,@DPTR+A 0364: 71 1D acall coutt 0366: D0 83 pop DPH 0368: D0 82 pop DPL 036A: D0 E0 pop ACC 036C: 22 ret ; A and B are used as free registers ; getbu returns the next byte in the hex file ; in A ; all information in A and B is destroyed 036D: 71 AD getbu: acall gett ; check for char from termi 036F: 40 1B jc buesc ; check for escape 0371: 71 96 bu1: acall getu ; get char from unix 0373: 50 F8 jnc getbu ; go back if nothing there 0375: 91 61 acall hexc ; convert to hex 0377: 50 17 jnc buabrt ; get out if error 0379: E5 F0 mov A,B ; destroy A info 037B: C4 swap A ; shift up a nibble 037C: F5 03 mov TEMP,A ; save MSnibble 037E: 71 96 bu4: acall getu ; wait for next next char 0380: 50 FC jnc bu4 0382: 91 61 acall hexc ; convert to hex 0384: 50 0A jnc buabrt ; leave if error 0386: E5 03 mov A,TEMP 0388: 45 F0 orl A,B ; form full value 038A: D3 setb C 038B: 22 bu3: ret 038C: B4 1B E2 buesc: cjne A,#ESC,bu1 038F: C3 clr C 0390: D0 E0 buabrt: pop ACC 0392: D0 E0 pop ACC 0394: 41 9C ajmp dlexit ; abort download in an unfr 0396: C0 82 getu: push DPL 0398: C0 83 push DPH 039A: 90 FF 27 mov DPTR,#USTAT ; get port status 039D: E0 movx A,@DPTR ; 039E: A2 E1 mov C,0xe1h ; use carry as fla 03A0: 30 E1 05 jnb 0xe1h,getu2 ; char ready? 03A3: 15 82 dec DPL ; DPTR = UDATA 03A5: E0 movx A,@DPTR ; 03A6: C2 E7 clr 0xE7h ; clear parity bit 03A8: D0 83 getu2: pop DPH 03AA: D0 82 pop DPL 03AC: 22 ret ; subroutine gett ; ; this subroutine looks ONCE to see if a character is ready 03AD: C0 82 gett: push DPL 03AF: C0 83 push DPH 03B1: 90 FF 25 mov DPTR,#TSTAT ; get port status 03B4: E0 movx A,@DPTR ; read port status 03B5: A2 E1 mov C,0xe1h ; C=0 means no cha 03B7: 30 E1 05 jnb 0xe1h,gett2 ; leave if char not ready 03BA: 15 82 dec DPL 03BC: E0 movx A,@DPTR ; 03BD: C2 E7 clr 0xe7h ; mask high order bit 03BF: D0 83 gett2: pop DPH 03C1: D0 82 pop DPL 03C3: 22 ret ; ; subroutine waitt ; ; this subroutine will wait until a character is hit ; 03C4: C0 82 waitt: push DPL 03C6: C0 83 push DPH 03C8: 90 FF 25 mov DPTR,#TSTAT 03CB: E0 wt2: movx A,@DPTR ; get port address 03CC: 30 E1 FC jnb 0xe1h,wt2 ; is A != 0x2h (character 03CF: 15 82 dec DPL ; 03D1: E0 movx A,@DPTR ; get char when rea 03D2: D0 83 pop DPH 03D4: D0 82 pop DPL 03D6: 22 ret ; ride, Sally. ride. 03D7: C0 82 outu: push DPL 03D9: C0 83 push DPH 03DB: C0 E0 push 0xe0h 03DD: 90 FF 27 mov DPTR,#USTAT 03E0: E0 outu2: movx A,@DPTR 03E1: 30 E0 FC jnb 0xe0h,outu2 ; jmp if unix not ready 03E4: D0 E0 pop 0xe0h 03E6: 15 82 dec DPL 03E8: F0 movx @DPTR,A ; send character to 03E9: D0 83 pop DPH 03EB: D0 82 pop DPL 03ED: 22 ret 03EE: B5 10 01 outt: cjne A,0x10h,outt0 03F1: 22 ret 03F2: C0 82 outt0: push DPL ; 0x83h ; push DP 03F4: C0 83 push DPH ; 0x82h ; push DP 03F6: C0 E0 push 0xe0h ; push A 03F8: 90 FF 25 mov DPTR,#TSTAT 03FB: E0 outt2: movx A,@DPTR 03FC: 30 E0 FC jnb 0xe0h,outt2 03FF: D0 E0 pop 0xe0h 0401: 90 FF 24 mov DPTR,#TDATA 0404: F0 movx @DPTR,A 0405: D0 83 pop DPH ; 0x82h 0407: D0 82 pop DPL ; 0x83h 0409: 22 ret ; space maker 040A: 91 10 msoutt: acall soutt ; output 4 spaces 040C: 91 10 acall soutt 040E: 91 10 acall soutt 0410: 74 20 soutt: mov A,#SPC 0412: 80 DA sjmp outt ; output space 0414: 74 07 beloutt: mov A,#BELL 0416: 80 D6 sjmp outt ; output 2 backspaces 0418: 91 1A bs2outt: acall bsoutt ; output 1 backspace 041A: 74 08 bsoutt: mov A,#8 041C: 80 D0 sjmp outt 041E: C0 E0 routt: push 0xe0h ; push A 0420: 74 0D mov A,#CR ; A is scrambled 0422: 71 EE acall outt ; load return and output it 0424: 74 0A mov A,#LF 0426: 71 EE acall outt ; load linefeed and output 0428: 91 37 acall dly ; delay for viewpoint 042A: D0 E0 pop 0xe0h 042C: 22 ret 042D: E4 printc: clr A 042E: 93 movc A,@A+DPTR ; get character 042F: 60 05 jz pt1 0431: 71 EE acall outt ; print character 0433: A3 inc DPTR 0434: 80 F7 sjmp printc 0436: 22 pt1: ret ; leave ; delay ; 0437: 75 17 06 dly: mov 0x17h,#0x06h 043A: 75 16 00 dly2: mov 0x16h,#0 043D: D5 16 FD dly1: djnz 0x16h,dly1 0440: D5 17 FA djnz 0x17h,dly1 0443: 22 ret ; ; skip spaces in input ; 0444: E3 skipsp: movx A,@R1 ; load character in buffer to 0445: B4 20 03 cjne A,#SPC,sk1 0448: 09 inc R1 0449: 80 F9 sjmp skipsp 044B: 22 sk1: ret ; ; convert characters to uppercase ; 044C: C0 E0 upcase: push 0xe0h ; push A 044E: 24 9F add A,#-97 ; check for less than 'a' 0450: 20 E7 0B jb 0xe7h,up2 ; 0453: 24 E7 add A,#-25 0455: 30 E7 06 jnb 0xe7h,up2 0458: 24 5A add A,#90 045A: 15 81 dec SP 045C: 80 02 sjmp up3 045E: D0 E0 up2: pop 0xe0h ; push A 0460: 22 up3: ret ; hexc: receives an ascii character in the accumulator (A) ; returns the converted number in the B register (B) ; ; if carry is set, the number is valid ; if carry is clear, the number is not valid 0461: 91 4C hexc: acall upcase ; 0463: 24 D0 add A,#-48 ; bring down number 0465: 20 E7 17 jb 0xe7h,hexc3 ; invalid data 0468: F5 F0 mov B,A ; 046A: 24 F6 add A,#-10 ; is it a number? 046C: 20 E7 13 jb 0xe7h,hexc2 ; if true, A is a number fr 046F: E5 F0 mov A,B 0471: 24 F9 add A,#-7 ; bring down to a letter 0473: F5 F0 mov B,A ; 0475: 24 F6 add A,#-10 ; is it too low again 0477: 20 E7 05 jb 0xe7h,hexc3 ; not a number 047A: 24 FA add A,#-6 ; 047C: 20 E7 03 jb 0xe7h,hexc2 ; a valid number from A-F 047F: C3 hexc3: clr C 0480: E4 clr A 0481: 22 ret ; done 4/17/95 0482: D3 hexc2: setb C 0483: E5 F0 mov A,B 0485: 22 ret ; ; set Breakpoint ; cB: ; 1) Check for illegal bkpt ; 2) Remove any existing bkpt ; 3) Set bkpt location 0486: E5 05 mov A,ARGV1H ; 1) check for illegal bkpt 0488: 24 F0 add A,#-0x10h ; illegal bkpt = bkpt less 048A: 40 07 jc cB1 048C: 90 0C 3A mov DPTR,#BRROM ; print error 048F: 91 2D acall printc 0491: 80 16 sjmp cB2 0493: 90 0C 27 cB1: mov DPTR,#BRSET 0496: 91 2D acall printc ; let user know what's goin 0498: 71 35 acall avoutt 049A: 90 0F F5 mov DPTR,#BPAD ; 3) Set bkpt location 049D: E5 04 mov A,ARGV1L ; get starting address LSB 049F: 91 B7 acall a2dptr 04A1: E5 05 mov A,ARGV1H ; get starting address MSB 04A3: 91 B7 acall a2dptr 04A5: E5 04 mov A,ARGV1L 04A7: 91 1E acall routt 04A9: 22 cB2: ret ; ; Clear breakpoint ; 04AA: E4 cC: clr A 04AB: 90 0C 11 mov DPTR,#BRCLR ; Tell user "Breakp 04AE: 91 2D acall printc 04B0: 90 0F F5 mov DPTR,#BPAD 04B3: 91 B7 acall a2dptr ; Clear breakpoint 04B5: 91 B7 acall a2dptr ;fall through to a2dptr ; Clear 'Is ; Store A @DPTR, inc DPTR 04B7: F0 a2dptr: movx @DPTR,A 04B8: A3 inc DPTR 04B9: 22 ret ; memory display routines ;; ;; Display eXternal memory ;; ; Display format: ; ; 3210: 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 04BA: 53 04 F0 cDarg: anl ARGV1L,#0xf0h ; start on an even address 04BD: E5 06 mov A,ARGV2L 04BF: 54 0F anl A,#0xfh ; see if count is X 04C1: 60 0A jz cDarg2 04C3: E5 06 mov A,ARGV2L ; 04C5: 24 10 add A,#0x10h ; make count XXX0xh 04C7: 50 06 jnc cDarg3 04C9: 05 07 inc ARGV2H 04CB: 80 02 sjmp cDarg3 04CD: E5 06 cDarg2: mov A,ARGV2L ; load the LSB of count int 04CF: C4 cDarg3: swap A ; swap nibbles 04D0: 54 0F anl A,#0xfh ; (shift right four 04D2: F5 06 mov ARGV2L,A ; save the shift 04D4: E5 07 mov A,ARGV2H ; 04D6: C4 swap A ; 04D7: F5 F0 mov B,A ; 04D9: 54 F0 anl A,#0xf0h ; shift ARGV2 (count) left 04DB: 42 06 orl ARGV2L,A ; 04DD: E5 F0 mov A,B ; 04DF: 54 0F anl A,#0xfh ; 04E1: F5 07 mov ARGV2H,A ; 04E3: D3 setb C ; so far, so good 04E4: 70 05 jnz cDarg0 ; 04E6: E5 06 mov A,ARGV2L 04E8: 70 01 jnz cDarg0 ; 04EA: C3 clr C 04EB: 05 07 cDarg0: inc ARGV2H ; adjust ARGV2H (since all 04ED: 22 ret 04EE: 91 BA cDX: acall cDarg 04F0: 40 01 jc cDskip 04F2: 22 ret 04F3: 71 AD cDskip: acall gett ; check for esc hit 04F5: B4 1B 01 cjne A,#ESC,cDX8 04F8: 22 ret ; esc hit, so leave 04F9: B4 0D 02 cDX8: cjne A,#CR,cDX9 ; 04FC: 71 C4 acall waitt 04FE: 91 1E cDX9: acall routt 0500: 85 04 82 cDX7: mov DPL,ARGV1L 0503: 85 05 83 mov DPH,ARGV1H 0506: B1 46 acall dispX 0508: 75 F0 10 mov B,#0x10h 050B: E0 cDX5: movx A,@DPTR ; print a line of m 050C: 71 54 acall aoutt 050E: 91 10 acall soutt 0510: E5 F0 mov A,B 0512: B4 09 02 cjne A,#0x09h,cDX10 0515: 91 10 acall soutt 0517: A3 cDX10: inc DPTR 0518: D5 F0 F0 djnz B,cDX5 051B: 91 0A acall msoutt ; four spaces 051D: 85 04 82 mov DPL,ARGV1L ; reload beginning address 0520: 85 05 83 mov DPH,ARGV1H 0523: 75 F0 10 mov B,#0x10h ; reload counter 0526: E0 cDX6: movx A,@DPTR ; print the ascii o 0527: 71 1D acall coutt 0529: A3 inc DPTR 052A: D5 F0 F9 djnz B,cDX6 052D: 91 1E acall routt ; carriage return 052F: C3 clr C 0530: E5 04 mov A,ARGV1L ; 0532: 34 10 addc A,#0x10h ; 0534: F5 04 mov ARGV1L,A ; 0536: E5 05 mov A,ARGV1H ; 0538: 34 00 addc A,#0x0h ; 053A: F5 05 mov ARGV1H,A ; add 16 to the address 053C: C3 clr C 053D: D5 06 C0 djnz ARGV2L,cDX7 ; 0540: D5 07 BD djnz ARGV2H,cDX7 ; 0543: 91 1E acall routt ; finish 0545: 22 cDX4: ret ; displays external address as "XXXX: " 0546: 71 3D dispX: acall dpoutt 0548: 74 3A mov A,#':' 054A: 71 1D acall coutt ; put a colon after address 054C: 81 10 ajmp soutt ; put space after colon ;; ;; Display Internal memory ;; ; Display format: ; ; I 10: 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 054E: C0 00 cDI: push 0 0550: 75 05 00 mov ARGV1H,#0 0553: 75 07 00 mov ARGV2H,#0 0556: 91 BA acall cDarg 0558: 40 03 jc cDIskp 055A: 75 06 10 mov ARGV2L,#0x10 ; if ARGV2 (count) is zero, 055D: 71 AD cDIskp: acall gett ; check for esc hit 055F: 50 0C jnc cDI7 0561: B4 1B 02 cjne A,#ESC,cDI8 0564: 80 3B sjmp cDI4 ; esc hit, so leave 0566: B4 0D 02 cDI8: cjne A,#CR,cDI9 ; 0569: 71 C4 acall waitt 056B: 91 1E cDI9: acall routt 056D: A8 04 cDI7: mov R0,ARGV1L 056F: B1 A8 acall dispI ; display "I xx: " 0571: 75 F0 10 mov B,#0x10h 0574: D1 4F cDI5: acall grabI ;mov A,@R0 ; print a line of memory va 0576: 71 54 acall aoutt 0578: 91 10 acall soutt 057A: E5 F0 mov A,B 057C: B4 09 02 cjne A,#0x09h,cDI10 057F: 91 10 acall soutt 0581: 08 cDI10: inc R0 0582: D5 F0 EF djnz B,cDI5 0585: 91 0A acall msoutt ; four spaces 0587: A8 04 mov R0,ARGV1L ; reload beginning address 0589: 75 F0 10 mov B,#0x10h ; reload counter 058C: D1 4F cDI6: acall grabI ;mov A,@R0 ; print the ascii of the me 058E: 71 1D acall coutt 0590: 08 inc R0 0591: D5 F0 F8 djnz B,cDI6 0594: 91 1E acall routt ; carriage return 0596: E5 04 mov A,ARGV1L ; 0598: 24 10 add A,#0x10h ; 059A: F5 04 mov ARGV1L,A ; 059C: D5 06 BE djnz ARGV2L,cDIskp ; go back if not done 059F: 91 1E acall routt ; finish 05A1: D0 00 cDI4: pop 0 05A3: 22 ret 05A4: 74 42 dispB: mov A,#'B' 05A6: 80 02 sjmp dispI0 ; display Internal address in R0 ; (trashes A) 05A8: 74 49 dispI: mov A,#'I' ; 05AA: 71 EE dispI0: acall outt ; Put "I " before addres. 05AC: 91 10 acall soutt ; 05AE: E8 mov A,R0 05AF: 71 54 acall aoutt 05B1: 74 3A mov A,#':' 05B3: 71 1D acall coutt ; put a colon after address 05B5: 81 10 ajmp soutt ; put space after colon ;; ;; Display Bit-addressable memory ;; ; Display format: ; > DB 0 20 ; B 00: 0 0 1 1 0 1 1 0 0 0 1 1 0 0 0 1 ; B 10: 0 1 0 0 0 0 0 1 0 1 1 0 0 0 0 1 05B7: C0 00 cDB: push 0 05B9: C0 01 push 1 05BB: 51 EC acall startD 05BD: 75 05 00 mov ARGV1H,#0 05C0: 75 07 00 mov ARGV2H,#0 05C3: 91 BA acall cDarg 05C5: 40 03 jc cDBskp 05C7: 75 06 10 mov ARGV2L,#0x10h ; default argv2 == 0x100 05CA: 71 AD cDBskp: acall gett ; check for esc hit 05CC: 50 0C jnc cDB7 05CE: B4 1B 02 cjne A,#ESC,cDB8 05D1: 80 45 sjmp cDB4 ; esc hit, so leave 05D3: B4 0D 02 cDB8: cjne A,#CR,cDB9 ; 05D6: 71 C4 acall waitt 05D8: 91 1E cDB9: acall routt 05DA: E5 04 cDB7: mov A,ARGV1L ; get bit address into A 05DC: F9 mov R1,A ; save bit address into R1 05DD: F8 mov R0,A 05DE: B1 A4 acall dispB 05E0: E9 mov A,R1 05E1: D1 1F acall bt2d 05E3: F8 mov R0,A ; put direct address of bit 05E4: 75 F0 10 mov B,#0x10h ;mov A,@R0 ; load a byte of bit-addres 05E7: 71 03 acall getD ; load a byte of bit-addres 05E9: 33 cDB5: rlc A ; move topmost bit of byte 05EA: C0 E0 push 0xE0h ; save rotated A 05EC: 91 10 acall soutt ; output a space 05EE: E4 clr A ; "image" a 0 or 1 into A 05EF: 34 30 addc A,#'0' 05F1: 71 1D acall coutt ; display the 0 or 1 in A 05F3: 91 10 acall soutt ; output a space 05F5: 09 inc R1 05F6: E5 F0 mov A,B 05F8: B4 09 0B cjne A,#0x09h,cDB10 ; See if we've output 8 bit 05FB: 91 10 acall soutt ; y: out another space and 05FD: D0 E0 pop 0xE0h ; throw away current saved 05FF: E9 mov A,R1 ; get current bit position 0600: D1 1F acall bt2d ; convert to valid byte add 0602: F8 mov R0,A ; save new indirect address 0603: E6 mov A,@R0 ; load a byte of bit-addres 0604: C0 E0 push 0xE0h ; push new A onto stack 0606: D0 E0 cDB10: pop 0xE0h ; pop current save A for ne 0608: D5 F0 DE djnz B,cDB5 060B: 91 1E acall routt ; carriage return 060D: E5 04 mov A,ARGV1L ; 060F: 24 10 add A,#0x10h ; 0611: F5 04 mov ARGV1L,A ; 0613: D5 06 B4 djnz ARGV2L,cDBskp ; go back if not done 0616: 91 1E acall routt ; finish 0618: 71 0B cDB4: acall stopD ; clean up after self-modif 061A: D0 01 pop 1 061C: D0 00 pop 0 061E: 22 ret ; convert a bit address into an direct address: 061F: 20 E7 08 bt2d: jb 0xE7h,b2sfr ; uhoh, trying to disp SFR 0622: 54 78 anl A,#0x78 ; mask off the bits we don' 0624: 03 rr A 0625: 03 rr A 0626: 03 rr A ; divide bit addr by 8 to g 0627: 44 20 orl A,#0x20 ; add offset 0629: 22 ret 062A: 54 F1 b2sfr: anl A,#0xF1 ; This turns SFR bi ; addresses. 062C: 22 ret ;; User interface format: ; ; Location: Value (as in XXXX: VV) ; ; As user types new value, old value is left-shifted and ne ; in. [ENTER] moves to the next memory location. Values a ; "automatically." [ESC] or [SPACE] ends the memory exami ;; ;; Examine/modify eXternal memory ;; 062D: 85 04 82 cEX: mov DPL,ARGV1L 0630: 85 05 83 mov DPH,ARGV1H 0633: 7C FF mov R4,#0xFFh 0635: B1 46 cEX1: acall dispX ; Display DPTR 0637: E0 movx A,@DPTR ; Grab byte of RAM 0638: D1 CA acall cEE ; Let user edit value, or p 063A: F0 movx @DPTR,A 063B: A3 inc DPTR 063C: 40 F7 jc cEX1 063E: 22 ret ;; ;; Examine/modify Internal memory ;; 063F: A8 04 cEI: mov R0,ARGV1L ; get internal address into 0641: 7C FF cEI0: mov R4,#0xFFh ; set mask to 0FFFh cEI1: 0643: B1 A8 cEI2: acall dispI 0645: D1 4F acall grabI ;mov A,@R0 ; Grab byte of RAM 0647: D1 CA acall cEE ; Let user edit value, or p 0649: D1 68 acall putI ;mov @R0,A 064B: 08 inc R0 064C: 40 F5 jc cEI1 064E: 22 ret ; ; grabI: grab byte of Internal RAM, transparently redirecti ; to locations we've saved externally. ; ; Call with R0=location, returns value in A 064F: C0 D0 grabI: push PSW 0651: C0 82 push DPL 0653: C0 83 push DPH 0655: C0 00 push 0 0657: D1 81 acall cvtI ; convert Internal 0659: 40 03 jc gI1 ; if C=0: internal, C=1: external & 065B: E6 mov A,@R0 065C: 80 01 sjmp gIdone 065E: E0 gI1: movx A,@DPTR 065F: D0 00 gIdone: pop 0 0661: D0 83 pop DPH 0663: D0 82 pop DPL 0665: D0 D0 pop PSW 0667: 22 ret ; ; putI: put byte of Internal RAM, transparently redirecting ; to locations we've saved externally. ; ; Call with R0=location, writes A to that location 0668: C0 D0 putI: push PSW 066A: C0 82 push DPL 066C: C0 83 push DPH 066E: C0 00 push 0 0670: D1 81 acall cvtI ; convert Internal 0672: 40 03 jc pI1 ; if C=0, internal, C=1, external 0674: F6 mov @R0,A 0675: 80 01 sjmp pIdone 0677: F0 pI1: movx @DPTR,A 0678: D0 00 pIdone: pop 0 067A: D0 83 pop DPH 067C: D0 82 pop DPL 067E: D0 D0 pop PSW 0680: 22 ret ; cvtI: converts an Internal address, transparently redirec ; to saved internal RAM to the save-area in external ; ; Locations 0xE0h-0xFFh are in 0x0F00h-0x0F1Fh ; Locations 0x01h-0x1fh are in 0x0F21h-0x0F3Fh ; Location 0 is in R0SAVE ; ; Call with address in R0. ; Returns C=0 if new address is internal. R0 points to corr ; Returns C=1 if new address is external. DPTR points to co 0681: C0 E0 cvtI: push ACC 0683: C0 01 push 1 0685: E8 mov A,R0 0686: 60 12 jz cvt0 ; is address==0? Redirect 0688: 24 20 add A,#0x20h ; shift internal address a 068A: F9 mov R1,A 068B: 54 3F anl A,#0x3Fh 068D: B5 01 07 cjne A,1,cvtII 0690: 75 83 0F cvtX1: mov DPH,#SVDBLK/256 0693: F5 82 mov DPL,A 0695: 80 06 sjmp cvtX ; return w/ carry set 0697: C3 cvtII: clr C 0698: 80 04 sjmp cvtD 069A: 90 0F F2 cvt0: mov DPTR,#R0SAVE 069D: D3 cvtX: setb C 069E: D0 01 cvtD: pop 1 06A0: D0 E0 pop ACC 06A2: 22 ret ;; ;; Examine/modify Bit-addressible memory ;; 06A3: 51 EC cEB: acall startD 06A5: A8 04 mov R0,ARGV1L ; get internal address into 06A7: 7C 01 mov R4,#0x01h ; set mask to 01h 06A9: E8 cEB1: mov A,R0 06AA: 20 E7 16 jb 0xE7,cEB2 ; don't let user edit SFRs 06AD: B1 A4 acall dispB 06AF: 51 F9 acall getB 06B1: E4 clr A 06B2: 92 E0 mov 0xE0,C 06B4: D1 CA acall cEE ; Let user edit value, or p 06B6: C0 D0 push PSW 06B8: A2 E0 mov C,0xE0 06BA: 51 FD acall putB 06BC: D0 D0 pop PSW 06BE: 08 inc R0 06BF: 40 E8 jc cEB1 06C1: 61 0B ajmp stopD 06C3: 71 0B cEB2: acall stopD 06C5: 90 0C 67 mov DPTR,#EBERR ; "Cannot edit ... from 0x8 06C8: 81 2D ajmp printc ;; ;; Let user edit byte of RAM. (common to all 3 Examine rout ;; ; inputs: ; A == value to edit ; R4 == mask value (edited value is ANDed against this) ; outputs ; A == edited value ; R2,R3 trashed 06CA: FB cEE: mov R3,A ; Copy byte to R3 for safe 06CB: 71 45 acall a1outt ; Show byte of RAM 06CD: 71 C4 cE1a: acall waitt ; Wait for a character 06CF: B4 1B 02 cjne A,#0x1bh,cE0a ; Is character an ESC, Spac 06D2: 80 08 sjmp cE0c 06D4: B4 20 02 cE0a: cjne A,#0x20h,cE0b ; No, continue 06D7: 80 03 sjmp cE0c 06D9: B4 0D 0D cE0b: cjne A,#0x0Dh,cE2 06DC: C0 E0 cE0c: push ACC ; save keypress 06DE: 91 1E acall routt ; print a newline 06E0: D0 E0 pop ACC ; restore keypress 06E2: C3 clr C ; clear carry 06E3: B4 0D 01 cjne A,#0x0Dh,cE0 ; If it wasn't Enter, leave 06E6: D3 setb C 06E7: EB cE0: mov A,R3 06E8: 22 ret 06E9: 91 61 cE2: acall hexc ; Convert input from hex 06EB: 50 0F jnc cE3 ; ring bell on error 06ED: FA mov R2,A ; save input 06EE: EB mov A,R3 ; get "current value" 06EF: C4 swap A ; shift left by 4 06F0: 54 F0 anl A,#0xF0h ; bringing in 0's 06F2: 4A orl A,R2 ; logical-OR with input 06F3: 5C anl A,R4 ; mask against input mask ( 06F4: FB mov R3,A ; save new "current value" 06F5: 91 18 acall bs2outt 06F7: EB mov A,R3 06F8: 71 45 acall a1outt 06FA: 80 D1 sjmp cE1a 06FC: 91 14 cE3: acall beloutt 06FE: 80 CD sjmp cE1a ;; ;; Examine/modify registers ;; cR: ; step through registers one at a time: ; SP, PSW, DPL, DPH first ; A, and B next ; then R0 through R7 in the "current" bank 0700: 7C FF mov R4,#0xFFh ; Set edit mask to 0xFFh 0702: 79 00 mov R1,#0 ; start counter @ 0 0704: 90 0F 40 mov DPTR,#SVDREG ; point to the saved-regist 0707: F1 39 cR1: acall dispR ; display register name 0709: E0 movx A,@DPTR ; grab byte from sa 070A: D1 CA acall cEE ; let user edit byte 070C: F0 movx @DPTR,A ; write back edited 070D: 50 29 jnc cRdn 070F: A3 inc DPTR 0710: 09 inc R1 0711: B9 06 02 cjne R1,#0x06,cR2a 0714: 80 08 sjmp cR2b 0716: B9 04 EE cR2a: cjne R1,#0x04,cR1 0719: 90 0F F0 mov DPTR,#ASAVE 071C: 80 E9 sjmp cR1 071E: 90 0F 41 cR2b: mov DPTR,#SVDREG+1 0721: E0 movx A,@DPTR 0722: 54 18 anl A,#0x18 0724: 79 00 mov R1,#0 0726: F8 mov R0,A 0727: F1 55 cR3: acall dispRn 0729: D1 4F acall grabI 072B: D1 CA acall cEE 072D: D1 68 acall putI 072F: 50 07 jnc cRdn 0731: 08 inc R0 0732: 09 inc R1 0733: B9 08 F1 cjne R1,#0x08h,cR3 0736: 91 1E acall routt 0738: 22 cRdn: ret ; Displays register name enumerated in R1 ; ; 0x00-0x05: SP PSW DPL DPH A B ; ; format: "[REG]: " 0739: F1 51 dispR: acall dr 073B: E9 mov A,R1 073C: 23 rl A 073D: 23 rl A 073E: C0 83 push DPH 0740: C0 82 push DPL 0742: 75 83 0B mov DPH,#REGS/256 0745: 24 24 add A,#REGS&255 0747: F5 82 mov DPL,A 0749: 91 2D acall printc 074B: D0 82 pop DPL 074D: D0 83 pop DPH 074F: 80 11 sjmp dispRd 0751: 74 5B dr: mov A,#'[' 0753: 61 EE ajmp outt ; Displays register names R0-R7, as enumerated in R1 ; ; 0755: F1 51 dispRn: acall dr 0757: 91 10 acall soutt 0759: 74 52 mov A,#'R' 075B: 71 EE acall outt 075D: 74 30 mov A,#'0' 075F: 29 add A,R1 0760: 71 EE acall outt 0762: 74 5D dispRd: mov A,#']' 0764: 71 EE acall outt 0766: 74 3A mov A,#':' 0768: 71 EE acall outt 076A: 81 10 ajmp soutt ;; ;; Toggle "Quiet Mode" ;; 076C: D3 cQchk: setb C 076D: 80 01 sjmp cQ0 076F: C3 cQ: clr C 0770: 90 0F FB cQ0: mov DPTR,#QUIET 0773: E0 movx A,@DPTR 0774: B4 AA 02 cjne A,#0xAAh,cQnxt 0777: 80 03 sjmp cQtog 0779: B4 07 1B cQnxt: cjne A,#0x07h,cQerr 077C: 40 1C cQtog: jc cQdone 077E: 64 AD xrl A,#0xADh 0780: F0 movx @DPTR,A 0781: C0 E0 push ACC 0783: 90 0C A5 mov DPTR,#QMSG 0786: 91 2D acall printc 0788: D0 00 pop 0 078A: 74 6E mov A,#'n' 078C: B8 AA 04 cjne R0,#0xAA,cQon 078F: 74 66 mov A,#'f' 0791: 71 1D acall coutt 0793: 71 1D cQon: acall coutt 0795: 81 1E ajmp routt 0797: 74 AA cQerr: mov A,#0xAAh 0799: F0 movx @DPTR,A 079A: 22 cQdone: ret ;; ;; Go to executable code ;; 079B: 51 C0 cG: acall setbkp ; restore all saved registers 079D: C2 D3 clr 0xD3h ; set PSW for Bank 0 079F: C2 D4 clr 0xD4h ; Bank 0 --> R0-R7 are in 0 07A1: 90 0F F7 mov DPTR,#ISBKP 07A4: E0 movx A,@DPTR 07A5: F5 F0 mov B,A 07A7: 70 05 jnz gRSM 07A9: 90 0B BC mov DPTR,#GJUMP 07AC: 80 03 sjmp gMSG 07AE: 90 0B CA gRSM: mov DPTR,#GRSM 07B1: 91 2D gMSG: acall printc 07B3: 71 35 acall avoutt 07B5: 91 1E acall routt ; restore first half of saved memory (0xE0h-0xFFh) ; ( the user program's stack may be in that area ) 07B7: 90 0F 00 mov DPTR,#SVDBLK ; pull the saved internal R 07BA: 78 E0 mov R0,#SVSTART ; point to start of saved a 07BC: E0 g1: movx A,@DPTR ; get saved value 07BD: F6 mov @R0,A ; write it to internal RAM 07BE: A3 inc DPTR 07BF: 08 inc R0 07C0: B8 00 F9 cjne R0,#0,g1 ; loop until it's all copie ; restore the saved registers 07C3: 90 0F 40 mov DPTR,#SVDREG 07C6: 78 10 mov R0,#REGSTK ; initialize R0 to point to 07C8: E0 movx A,@DPTR 07C9: F9 mov R1,A 07CA: F6 g2: mov @R0,A 07CB: E0 movx A,@DPTR ; restore register 07CC: 08 inc R0 07CD: A3 inc DPTR 07CE: B8 17 F9 cjne R0,#REGSTK+7,g2 ; restore 6 interna 07D1: 89 81 mov SP,R1 ; get saved SP 07D3: E5 F0 mov A,B 07D5: 70 07 jnz gBK 07D7: 90 00 30 mov DPTR,#enter ; push entry point of monit 07DA: C0 82 push DPL 07DC: C0 83 push DPH 07DE: C0 04 gBK: push ARGV1L ; push address of user's ro 07E0: C0 05 push ARGV1H 07E2: E5 81 mov A,SP ; save the new SP to A 07E4: 75 81 16 mov SP,#REGSTK+6 07E7: 75 A0 30 mov P2,#P2SAVE ; restore P2 from P2SAVE 07EA: D0 B8 pop IP 07EC: D0 A8 pop IE 07EE: D0 83 pop DPH 07F0: D0 82 pop DPL 07F2: D0 D0 pop PSW ; this may change our regis 07F4: F5 81 mov SP,A ; get saved, updated SP fro 07F6: C0 82 push DPL ; save the DPTR we just res 07F8: C0 83 push DPH 07FA: C0 D0 push PSW ; and PSW 07FC: C2 D3 clr 0xD3h ; set PSW for Bank 0 07FE: C2 D4 clr 0xD4h ; Bank 0 --> R0-R7 are in 0 ; restore the second half of saved memory (0x01-0x1 0800: 90 0F 21 mov DPTR,#SVDBLK+0x21h 0803: 78 01 mov R0,#1 0805: E0 g3: movx A,@DPTR ; grab a byte 0806: F6 mov @R0,A ; save it 0807: A3 inc DPTR 0808: 08 inc R0 0809: B8 20 F9 cjne R0,#SVEND,g3 080C: 90 0F F2 mov DPTR,#R0SAVE ; get the saved value for R 080F: E0 movx A,@DPTR ; retrieve R0 0810: F8 mov R0,A 0811: 15 82 dec DPL 0813: E0 movx A,@DPTR ; retrieve B 0814: F5 F0 mov B,A ; store B 0816: 15 82 dec DPL 0818: E0 movx A,@DPTR ; store A 0819: D0 D0 pop PSW 081B: D0 83 pop DPH 081D: D0 82 pop DPL 081F: 22 ret ; jump to the user's routin 0820: 75 A8 00 main: mov IE,#0x00h 0823: 75 81 80 mov SP,#0x80h ; initialize stack pointer ; upper 128 bytes of RAM 0826: 11 3B acall initp ; initialize UARTs 0828: 12 04 AA lcall cC ; clear breakpoint 082B: 12 07 6C lcall cQchk ; init "quiet-mode" toggle 082E: 90 08 66 mov DPTR,#OPEN 0831: 12 04 2D lcall printc ; print opening message 0834: 74 FF mov A,#0xffh ; The "entry point" routine expects a PC value on t ; This PC value is compared against the break point ; currently set up. The breakpoint shouldn't ever ; us here in ROM. :-) Knowing this address could ; some fun, undocumented behavior, I guess. Anyway ; attempt is made to "resume execution at breakpoin ; this address as the breakpoint, then nothing prof ; happen--business as usual should commence. ie. t ; should get his prompt back. :-) BTW, setting th ; as the breakpoint address would require external ; editing memory manually anyway. :-) ; At the very least, this lcall properly pre-massag 0836: 12 00 30 eloop: lcall enter ; cute way to get into 'ent 0839: 80 FB sjmp eloop initp: ; delay to wait for UARTs to come out of reset. ; total delay == ((256*24)+24)*160 + 24 == 986904 c ; or approx 0.16 second at 6MHz. 083B: 75 07 A0 mov 0x7h,#0xA0h ; loop 0A000h times 083E: 12 04 3A initd: lcall dly2 0841: 75 A0 FF mov P2,#0xFFh ; should be 0FFh for all I/ 0844: E4 clr A 0845: F8 mov R0,A ; clear keypad 0846: 11 5F acall outp1 0848: 78 1F mov R0,#BAUDS&0FFh 084A: 74 3F mov A,#BAUD ; set baud to 9600 084C: 11 5F acall outp1 084E: 78 25 mov R0,#TSTAT&0FFh 0850: 79 27 mov R1,#USTAT&0FFh 0852: 11 5E acall outp2 0854: 74 40 mov A,#0x40h ; reset ports 0856: 11 5E acall outp2 0858: 74 6E mov A,#0x6eh ; write the mode 085A: 11 5E acall outp2 085C: 74 15 mov A,#0x15h ; write control word 085E: F3 outp2: movx @R1,A 085F: F2 outp1: movx @R0,A 0860: 22 ret ;; ;; text and ASCII assignments ;; 0861: 0D 0A 3E 20 00 PROMPT: .byte CR,LF,"> ",NULL 0866: 0C 0D 0A OPEN: .byte FF,CR,LF 0869: 38 30 35 78 20 4D 6F 6E 69 74 6F 72 20 28 46 72 69 20 31 33 74 68 29 .byte "805x Monitor (Fri 13th)" 0880: 0D 0A 0D 0A .byte CR,LF,CR,LF 0884: 48 61 72 64 77 61 72 65 3A 20 45 2E 20 4A 6F 68 6E 73 6F 6E 2C 20 4A 2E 20 53 69 65 67 6C 65 20 31 39 39 34 2D 39 35 .byte "Hardware: E. Johnson, J. Siegle 1994-95" 08AB: 0D 0A .byte CR,LF 08AD: 53 6F 66 74 77 61 72 65 3A 20 4A 2E 20 53 69 65 67 6C 65 2C 20 4A 2E 20 5A 62 69 63 69 61 6B 20 31 39 39 35 2D 39 36 .byte "Software: J. Siegle, J. Zbiciak 1995-96" 08D4: 0D 0A 0A .byte CR,LF,LF 08D7: 48 20 66 6F 72 20 48 45 4C 50 .byte "H for HELP" 08E1: 0D 0A 00 .byte CR,LF,NULL 08E4: 0D 0A TERM: .byte CR,LF 08E6: 54 65 72 6D 69 6E 61 6C 20 4D 6F 64 65 .byte "Terminal Mode" 08F3: 0D 0A .byte CR,LF 08F5: 28 5E 54 20 65 78 69 74 73 29 .byte "(^T exits)" 08FF: 0D 0A 0A 00 .byte CR,LF,LF,NULL 0903: 0D 0A MON: .byte CR,LF 0905: 4D 6F 6E 69 74 6F 72 20 4D 6F 64 65 .byte "Monitor Mode" 0911: 0D 0A 00 .byte CR,LF,NULL 0914: 0D 0A ERROR: .byte CR,LF 0916: 48 20 66 6F 72 20 48 45 4C 50 .byte "H for HELP" 0920: 07 00 .byte BELL,NULL 0922: 0C HELPTX: .byte FF 0923: 48 65 6C 70 3A .byte "Help:" 0928: 0D 0A 0A .byte CR,LF,LF 092B: 44 5B 58 49 42 5D 20 61 20 6C 20 20 44 69 73 70 6C 61 79 20 3C 6C 3E 20 6C 6F 63 61 74 69 6F 6E 73 20 73 74 61 72 74 69 6E 67 20 61 74 20 3C 61 3E 0D 0A .byte "D[XIB] a l Display locations starting 095E: 20 20 20 20 20 20 20 20 20 20 20 20 28 58 20 2D 2D 20 65 58 74 65 72 6E 61 6C 20 20 49 20 2D 2D 20 49 6E 74 65 72 6E 61 6C 20 20 42 20 2D 2D 20 42 69 74 2D 61 64 64 72 65 73 73 65 64 29 0D 0A .byte " (X -- eXternal I -- Internal 099E: 45 5B 58 49 42 5D 20 61 20 20 20 20 45 78 61 6D 69 6E 65 2F 6D 6F 64 69 66 79 20 6D 65 6D 6F 72 79 20 73 74 61 72 74 69 6E 67 20 61 74 20 3C 61 3E 0D 0A .byte "E[XIB] a Examine/modify memory starting 09D1: 52 20 20 20 20 20 20 20 20 20 20 20 45 78 61 6D 69 6E 65 2F 6D 6F 64 69 66 79 20 72 65 67 69 73 74 65 72 73 0D 0A .byte "R Examine/modify registers",CR,L 09F7: 42 20 61 64 64 72 20 20 20 20 20 20 53 65 74 20 62 72 65 61 6B 70 6F 69 6E 74 0D 0A .byte "B addr Set breakpoint",CR,LF 0A13: 43 20 20 20 20 20 20 20 20 20 20 20 43 6C 65 61 72 20 62 72 65 61 6B 70 6F 69 6E 74 0D 0A .byte "C Clear breakpoint",CR,LF 0A31: 47 20 61 64 64 72 20 20 20 20 20 20 45 78 65 63 75 74 65 20 63 6F 64 65 20 61 74 20 28 27 47 27 6F 74 6F 29 20 3C 61 64 64 72 3E 0D 0A .byte "G addr Execute code at ('G'oto)