⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monplus.asm

📁 MSC1210单片机的一个监控程序
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; A low-level monitor for the 8051 family for the A51 assembler
; Copyright 1989 by Steve Kemplin
; This program is provided for personal, private use only.
; Commercial use in whole or in part without express written permission of
; the author is prohibited.
; No warranty is made as to the suitability of the program for any
; particular use.
;
; Based on a monitor written and copyrighted by Ron Stubbers
; [Ver 900626]

        .ORG    0x40FC          ;SET UP LABEL ADDRESS FOR PATCH
        .EQU    PATCH,*         ;MUST BE RAM, BOTH PROG & DATA SPACE

        .EQU    CR,0x0D         ;CHARACTER EQUATES
        .EQU    LF,0x0A
        .EQU    ESC,0x1B

        .EQU    VECTAB,0x2000         ;ADDRESS OF BASIC VECTORS
        .EQU    RSTVEC,VECTAB         ;JUMPS HERE AT POWER UP
        .EQU    SERINVEC,VECTAB+3     ;JUMPS HERE TO READ A CHARACTER
        .EQU    SEROUTVEC,VECTAB+6    ;JUMPS HERE TO SEND A CHARACTER
        .EQU    INT1VEC,VECTAB+0x10   ;JUMPS HERE ON INT1
        .EQU    SERVEC,VECTAB+0x18    ;JUMPS HERE ON SERIAL INTERRUPT
        .EQU    TMR0VEC,VECTAB+0x20   ;JUMPS HERE ON TIMER 0 INTERRUPT
        .EQU    TMR1VEC,VECTAB+0x28   ;JUMPS HERE ON TIMER 1 INTERRUPT
        .EQU    TMR2VEC,VECTAB+0x30   ;JUMPS HERE ON TIMER 2 INTERRUPT

        .EQU    BUFFER,0x50     ;BUFFER AREA FOR PROM LOAD

        .EQU    CNTLO,0x70      ;LOW BYTE OF COUNT
        .EQU    CNTHI,CNTLO+1   ;HIGH BYTE OF COUNT
        .EQU    ADHI,CNTLO+2    ;HIGH ADDRESS
        .EQU    ADLO,CNTLO+3    ;LOW ADDRESS
        .EQU    DATA,CNTLO+4    ;TEMPORARY BYTE STORAGE LOCATION
        .EQU    CKSUM,CNTLO+5   ;CHECKSUM FOR PROM LOAD
        .EQU    TEMP1,CNTLO+6   ;TEMPORARY STORAGE LOCATIONS
        .EQU    TEMP2,CNTLO+7
        .EQU    TEMP3,CNTLO+8

        .EQU    ASAVE,0x7A      ;REGISTER IMAGES
        .EQU    BSAVE,ASAVE+1
        .EQU    PSWSAVE,ASAVE+2
        .EQU    DPHSAVE,ASAVE+3
        .EQU    DPLSAVE,ASAVE+4

        .EQU    BRKPT1,0x50     ;OVERLAYS LOAD BUFFER AREA
        .EQU    BRKPT2,BRKPT1+5
        .EQU    BRKPT3,BRKPT1+10
        .EQU    BRKPT4,BRKPT1+15

        .EQU    BKFLAG,0x7F

        .EQU    BK1MASK,0x01
        .EQU    BK2MASK,0x02
        .EQU    BK3MASK,0x04
        .EQU    BK4MASK,0x08
        .EQU    ALLMASK,BK1MASK|BK2MASK|BK3MASK|BK4MASK

        .EQU    BPHLR_HI,((BPHLR>>8)&0xFF)
        .EQU    BPHLR_LO,(BPHLR&0xFF)

        .eject

        .ORG    0
        LJMP    INIT            ;GO TO INIT AT POWER UP

        .ORG    0x03
        .EQU    INT0,*          ;VECTOR FOR EXTERNAL INTERRUPT 0
        LJMP    MONENT

        .ORG    0x0B
        .EQU    TMR0,*          ;VECTOR FOR TIMER 0
        LJMP    TMR0VEC

        .ORG    0x13
        .EQU    INT1,*          ;VECTOR FOR EXTERNAL INTERRUPT 1
        LJMP    INT1VEC

        .ORG    0x1B
        .EQU    TMR1,*          ;VECTOR FOR TIMER 1
        LJMP    TMR1VEC

        .ORG    0x23
        .EQU    SERINT,*        ;VECTOR FOR SERIAL I/O INTERRUPT
        LJMP    SERVEC

        .ORG    0x2B
        .EQU    TMR2,*          ;VECTOR FOR TIMER 2
        .EQU    INT2,*          ;ALSO FOR EXTERNAL INTERRUPT 2
        LJMP    TMR2VEC

        .eject

;START OF MONITOR PROGRAM
;
        .ORG    0x30            ;START OF MONITOR CODE

ENTLST: LJMP    INIT            ;Entry point to the monitor
                                ;
        LJMP    DELAY           ;Pause for 1 msec times value in ACC
                                ;
        LJMP    SERIN           ;Serial Input Primitive
                                ;
        LJMP    GETC            ;Read char from serial port,
                                ;Echo char back to serial port
                                ;
        LJMP    PUTC            ;Send char in ACC to serial port
                                ;
        LJMP    PUTS            ;Sends text string to serial port,
                                ;DPTR points to start, null ends
                                ;
        LJMP    CRLF            ;Sends CR,LF to serial port
                                ;
        LJMP    ASC2HEX         ;Converts ASCII char in ACC to HEX equivalent,
                                ;Returns value in lower nibble, upper nibble zeroes
                                ;
        LJMP    HEX2ASC         ;Convert lower nibble in ACC to ASCII char,
                                ;returned in ACC
                                ;
        LJMP    RDHEX           ;Reads 2 char from serial port,
                                ;converts to byte returned in ACC
                                ;
        LJMP    WRBYTE          ;Writes byte in ACC to serial port,
                                ;as 2 ASCII char
                                ;

        .eject

        .ORG    0x0080
INIT:   MOV     SP,#0x30        ;SET THE STACK POINTER SOMEWHERE SAFE
        MOV     SCON,#0x52
        MOV     TMOD,#0x20
        MOV     PCON,#0X80      ;SET FOR DOUBLE BAUD RATE
        MOV     A, #0xCC        ;1200 BAUD, #0xF3=>1200 BAUD (12 MHz)
        MOV     TH1,A
        SETB    TR1             ;START TIMER FOR SERIAL PORT
        SETB    P3.2            ;THIS TURNS OFF INT0
        MOV     A,#10           ;SHORT DELAY TO MAKE SURE IT GOT DONE
        DJNZ    ACC,*
        ORL     IE,#0x81        ;ENABLE INT0
        ORL     IP,#0x01        ;AND MAKE IT HIGH PRIORITY
        MOV     BKFLAG,#0       ;CLEAR ALL BREAKPOINTS
        JB      P1.6,GETCMD     ;IF PIN P1.6 NOT GROUNDED,CONTINUE
        LJMP    RSTVEC          ;ELSE JUMP TO USER PROGRAM

SAVEREG: MOV    PSWSAVE,PSW     ;SAVE EVERYTHING
        MOV     ASAVE,ACC
        MOV     BSAVE,B
        MOV     DPHSAVE,DPH
        MOV     DPLSAVE,DPL
        ACALL   RSTALL          ;FIX UP THE CODE FROM BREAKPOINTS
        RET

CALLRET: ACALL  SAVEREG         ;SAVE THE REGISTERS,FIXUP THE CODE
        SJMP    GETCMD          ;AND GO GET A COMMAND

RESTORE: MOV    PSW,PSWSAVE     ;RESTORE EVERYTHING EXCEPT PC
        MOV     ACC,ASAVE
        MOV     B,BSAVE
        MOV     DPH,DPHSAVE
        MOV     DPL,DPLSAVE
        RET

MONENT: CLR     EX0             ;DISABLE THE INTERRUPT
        ACALL   SAVEREG         ;SAVE THE REGISTERS,FIXUP THE CODE
        POP     ADHI            ;GET THE PROGRAM COUNTER
        POP     ADLO
        PUSH    ADLO
        PUSH    ADHI
        MOV     A,ADHI          ;DISPLAY THE ADDRESS
        ACALL   WRBYTE
        MOV     A,ADLO
        ACALL   WRBYTE          ;FALL THROUGH INTO GETCMD

        .eject

GETCMD: ACALL   CRLF            ;START OFF ON A NEW LINE
        MOV     A,#'#'          ;PROMPT FOR A COMMAND
        ACALL   PUTC
        ACALL   GETC            ;GET THE COMMAND
I_TEST: CJNE    A,#'I',M_TEST   ;IF NOT I, THEN CHECK M
        ACALL   INTRAM          ;I, SO RUN INTERNAL
M_TEST: CJNE    A,#'M',L_TEST   ;IF NOT M, THEN CHECK L
        ACALL   MEMORY          ;M, SO RUN MEMORY MODIFY
L_TEST: CJNE    A,#'L',G_TEST   ;IF NOT L, THEN CHECK G
        ACALL   LOAD            ;L, SO LOAD HEX FILE
G_TEST: CJNE    A,#'G',S_TEST   ;IF NOT G, THEN CHECK S
        AJMP    GO              ;G, SO GO TO ADDRESS
S_TEST: CJNE    A,#'S',C_TEST   ;IF NOT S, THEN CHECK C
        AJMP    STEP            ;S, SO SINGLE STEP
C_TEST: CJNE    A,#'C',D_TEST   ;IF NOT C, THEN CHECK D
        AJMP    UCALL           ;C, SO CALL
D_TEST: CJNE    A,#'D',P_TEST   ;IF NOT D, THEN CHECK P
        ACALL   DUMP            ;D, SO DUMP RAM
P_TEST: CJNE    A,#'P',F_TEST   ;IF NOT P, THEN CHECK F
        ACALL   PRMLD
F_TEST: CJNE    A,#'F',V_TEST   ;IF NOT F, THEN CHECK V
        ACALL   FILL            ;F, SO FILL RAM
V_TEST: CJNE    A,#'V',B_TEST   ;IF NOT V THEN NO MATCH SO TRY AGAIN
        ACALL   MOVE
B_TEST: CJNE    A,#'B',R_TEST   ;IF NOT B THEN CHECK R
        ACALL   BPDISP          ;CALL BREAKPOINT DISPATCHER
R_TEST: CJNE    A,#'R',NOMATCH  ;IF NOT R THEN NO MATCH SO TRY AGAIN
        ACALL   REGSTR          ;CALL REGISTER HANDLING ROUTINE
NOMATCH: MOV    A,#0xFF         ;WAIT A WHILE
        ACALL   DELAY
        SJMP    GETCMD          ;NOT FOUND, SO BACK TO GETCMD

        .eject

INTRAM: PUSH    DPH             ;SAVE DPTR
        PUSH    DPL
        ACALL   SPACE           ;OUTPUT A SPACE
        ACALL   RDHEX           ;GET ADDRESS OF DIRECT BYTE TO READ
RAMENT: PUSH    ACC             ;SAVE IT
        MOV     DPTR,#PATCH     ;MOV INSTRUCTION WILL BE ASSEMBLED AT PATCH
        MOV     A,#0xE5         ;0xE5 IS A MOV A,DIRECT
        MOVX    @DPTR,A         ;PUT THE INSTRUCTION AT PATCH
        POP     ACC             ;RETRIEVE THE ADDRESS OF THE DIRECT BYTE
        INC     DPTR            ;STORE IT TO THE NEXT LOCATION
        MOVX    @DPTR,A
        MOV     A,#0x22         ;0x22 IS RETURN INSTRUCTION
        INC     DPTR            ;PUT RET INSTRUCTION IN PATCH
        MOVX    @DPTR,A
        LCALL   PATCH           ;EXECUTE PATCH
        ACALL   SPACE           ;OUTPUT A SPACE
        ACALL   WRBYTE          ;SHOW BYTE RETRIEVED BY PATCH
        ACALL   SPACE           ;OUTPUT A SPACE
INTRAM1: ACALL  GETC            ;GET THE NEXT CHARACTER
        CJNE    A,#' ',INTRAM2  ;ITS NOT A SPACE, SO KEEP CHECKING
        SJMP    INTRAM1         ;A SPACE DOESN'T MEAN ANYTHING, SO LOOP
INTRAM2: CJNE   A,#CR,NEWINT    ;ITS NOT A RETURN EITHER
        SJMP    INTRAMX         ;ITS A RETURN SO WE'RE DONE
NEWINT: ACALL   RDHX1           ;PRESUME ITS A NEW VALUE
        PUSH    ACC             ;SAVE THE NEW VALUE
        MOV     DPTR,#PATCH     ;MOV INSTRUCTION WILL BE ASSEMBLED AT PATCH
        MOV     A,#0xF5         ;0xF5 IS A MOV DIRECT,A
        MOVX    @DPTR,A         ;PUT THE INSTRUCTION AT PATCH
        POP     ACC             ;RECOVER THE NEW VALUE
        LCALL   PATCH           ;DATA IN A, INSTRs AT PATCH, SO EXECUTE
INTRAMX: ACALL  CRLF            ;WE'RE DONE
        POP     DPL             ;RESTORE DPTR
        POP     DPH
        RET                     ;BACK FOR NEXT COMMAND

        .eject

MEMORY: PUSH    ACC             ;SAVE THE ACCUMULATOR
        PUSH    DPH             ;AND DPTR
        PUSH    DPL
        ACALL   RDHEX           ;GET THE UPPER ADDRESS BYTE
        MOV     DPH,A
        ACALL   RDHEX           ;GET THE LOWER ADDRESS BYTE
        MOV     DPL,A
MEM1:   ACALL   CRLF            ;GO TO A NEW LINE
        MOV     A,DPH           ;SHOW THE ADDRESS
        ACALL   WRBYTE
        MOV     A,DPL
        ACALL   WRBYTE
        ACALL   SPACE           ;SPACE BETWEEN ADDRESS AND DATA
        MOVX    A,@DPTR         ;SHOW THE CURRENT DATA
        ACALL   WRBYTE
        ACALL   SPACE           ;OUTPUT A SPACE
        ACALL   GETC            ;GET THE NEXT CHARACTER
        CJNE    A,#' ',MEM2     ;ITS NOT A SPACE SO KEEP CHECKING
        INC     DPTR            ;SPACE, SO SHOW NEXT LOCATION
        SJMP    MEM1
MEM2:   CJNE    A,#'^',MEM4     ;ITS NOT A ^ SO KEEP CHECKING
        XCH     A,DPL           ;THIS ROUTINE DECREMENTS DPTR
        JNZ     MEM3            ;DPL NOT ZERO, SO DON'T CHANGE DPH
        DEC     DPH
MEM3:   DEC     A
        XCH     A,DPL
        SJMP    MEM1            ;SO WE CAN DISPLAY PREVIOUS
MEM4:   CJNE    A,#CR,NEWMEM    ;PRESUME ITS A NEW VALUE
        SJMP    MEMX            ;ITS A RETURN SO EXIT
NEWMEM: ACALL   RDHX1           ;GET THE NEW VALUE
        MOVX    @DPTR,A         ;MOVE THE NEW VALUE TO MEMORY
        INC     DPTR            ;POINT TO NEXT LOCATION
        SJMP    MEM1            ;AND CONTINUE
MEMX:   POP     DPL             ;RESTORE DPTR
        POP     DPH
        POP     ACC             ;AND THE ACCUMULATOR
        RET                     ;BACK FOR NEXT COMMAND

        .eject

LOAD:   PUSH    DPH             ;SAVE DPTR
        PUSH    DPL
        PUSH    CNTLO           ;SAVE CNTLO
        PUSH    ADHI            ;SAVE ADHI AND ADLO
        PUSH    ADLO
        MOV     ADHI,#0         ;INITIALIZE ADHI AND ADLO TO 0
        MOV     ADLO,#0
LOADX:  ACALL   GETC            ;GET THE NEXT CHARACTER
        CJNE    A,#' ',LOAD1    ;NOT A SPACE SO KEEP CHECKING
        SJMP    LOADX           ;SPACE DOESN'T MEAN ANYTHING SO LOOP
LOAD1:  CJNE    A,#CR,LOAD2     ;NOT A RETURN SO PRESUME A NEW ADDRESS
        SJMP    LOAD3           ;RETURN, SO LOAD FROM OLD ADDRESS
LOAD2:  ACALL   RDHX1           ;PRESUME A NEW ADDRESS
        MOV     ADHI,A
        ACALL   RDHEX
        MOV     ADLO,A
LOAD3:  ACALL   CRLF
        ACALL   CRLF
WAITBGN: ACALL  GETC            ;WAIT UNTIL ':' IS RECEIVED (START OF LINE)
        CJNE    A,#':',WAITBGN
        ACALL   RDHEX           ;GET THE BYTE COUNT
        JZ      ALLRD           ;LAST RECORD HAS 0 BYTE COUNT
        MOV     CNTLO,A         ;LOAD BYTE COUNT FOR LINE INTO CNTLO
        ACALL   RDHEX           ;READ HIGH BYTE OF START ADDRESS
        MOV     DPH,A
        ACALL   RDHEX           ;READ LOW BYTE OF START ADDRESS
        ADD     A,ADLO          ;ADD OFFSET ADDRESS
        MOV     DPL,A
        MOV     A,DPH
        ADDC    A,ADHI
        MOV     DPH,A
        ACALL   RDHEX           ;READ RECORD TYPE 00 = DATA, 01 = END
RDLP:   ACALL   RDHEX           ;GET DATA BYTE
        MOVX    @DPTR,A         ;STORE IT
        INC     DPTR            ;POINT TO NEXT BYTE ADDRESS
        DJNZ    CNTLO,RDLP      ;DECR BYTE COUNTER, LOOP IF NOT FINISHED
        ACALL   RDHEX           ;SKIP THE CHECKSUM
        ACALL   CRLF            ;GO TO A NEW LINE
        SJMP    WAITBGN         ;IGNORE CHECKSUM, LINE FEED, CARRIAGE RETURN
ALLRD:  ACALL   RDHEX           ;READ ADDRESS
        ACALL   RDHEX           ;READ ADDRESS
        ACALL   RDHEX           ;READ RECORD TYPE
        ACALL   RDHEX           ;READ LAST CHECKSUM
        ACALL   GETC            ;READ LAST CR
        ACALL   CRLF            ;GO TO A NEW LINE
        POP     ADLO            ;RESTORE ADHI AND ADLO
        POP     ADHI
        POP     CNTLO           ;RESTORE CNTLO
        POP     DPL             ;RESTORE DPTR
        POP     DPH
        RET                     ;DONE, BACK FOR NEXT COMMAND

        .eject

GO:     POP     DPH             ;GET THE OLD PROGRAM COUNTER
        POP     DPL             ;USE DPTR SINCE IT WILL BE RESTORED

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -