        TITL    "MSC51 monitor"
        PAGE    60

        INCL    "8051"

;****************************************************************************
;
;       Reset og interrupt vektorer
;
;****************************************************************************
;
        ORG     RESET
        LJMP    START                   ;RESET

;Interruptvektorer
        ORG     EXTI0

        ORG     TIMER0

        ORG     EXTI1

        ORG     TIMER1

        ORG     SINT
        LJMP    MONINT                  ;Jump til monitor interrupt


;****************************************************************************
;
;       Diverse rutiner
;
;****************************************************************************
;
        ORG     30H

CTS:    EQU     P3+4    ;CTS ben (In).   Der ventes med transmit n†r CTS er h›j.
RTS:    EQU     P3+5    ;RTS ben (Out).  Computer/terminal m† vente n†r RTS h›j.

ECHOFLG:EQU     0       ;Echoflag.  True for echo on.

;----------------------------------------------------------------------------
;
;Procedure WRLN
;
;Funktion:
;  Udskriver en tekst streng til RS232 interface.
;
;Parameter:
;  Efter CALL s‘tningen, skal strengen der skal udskrives defineres med
;DFB indstruktionen.  Strengen skal afsluttes med 0.
;Eksempel der udskriver teksten "Monitor aktiv":
;        ACALL   WRLN
;        DFB      "Monitor aktiv",0
;
;Reserverede registre: Ingen
;Reserverede flag: Ingen
;
;Stakforbrug:
;  7 bytes, incl. procedurekald.
;
;Beskrivelse:
;  N†r en procedure kaldes med CALL eller ACALL, gemmes returadressen p†
;stakken.  Returadressen er adressen umiddelbart efter CALL indstruktionen.
;Efter WRLN har gemt registrene p† stakken hentes returadressen.  karakterene
;ved denne adresse udskrives med WRITE proceduren indtil er n†s et 0.  Til
;sidst justeres returadressen til efter strengen, registrer hentes og der
;returneres.

WRLN:   PUSH    DPL                     ;Gem registre
        PUSH    DPH
        PUSH    ACC
        DEC     SP                      ;S‘t SP tilbage til ret adr
        DEC     SP                      ; Bem‘rk, her oversrives stak ved
        DEC     SP                      ; interrupt, og disse skal disables!
        POP     DPH                     ;Hent ret adr
        POP     DPL
WRLN2:  CLR     A                       ;Hent tegn
        MOVC    A,@A+DPTR
        INC     DPTR
        JZ      WRLN1                   ;Stop hvis nul
        ACALL   WRITE                   ;Send tegn
        SJMP    WRLN2
WRLN1:  PUSH    DPL                     ;Gem ny ret adr
        PUSH    DPH
        INC     SP                      ;Flyt SP til gemte registre
        INC     SP
        INC     SP
        POP     ACC                     ;Pop registre
        POP     DPH
        POP     DPL
        RET                             ;Returner

;----------------------------------------------------------------------------
;
;Procedure NL
;
;Funktion:
;  Udskriver ny linie til RS232.
;
;Parameter:
;  Ingen
;
;Reserverede registre: Ingen
;Reserverede flag: Ingen
;
;Stakforbrug:
;  5 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Procedure udskriver f›rst karakter 13 og herefter karakter 10 med WRITE
;proceduren.  N†r proceduren ikke benytter WRLN proceduren, er det for at
;spare p† stakforbruget.

NL:     PUSH    ACC                     ;Ny linie
        MOV     A,#0DH                  ;Udskriv karakter 13  (Return)
        ACALL   WRITE
        MOV     A,#0AH                  ;Udskriv karakter 10  (Linefeed)
        SJMP    WRSP1

;----------------------------------------------------------------------------
;
;Procedure TOSP
;
;Funktion:
;  Udskriver to mellemrum til RS232.
;
;Parameter:
;  Ingen
;
;Reserverede registre: Ingen
;Reserverede flag: Ingen
;
;Stakforbrug:
;  7 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Proceduren udskriver to mellemrum til RS232 med WRITE proceduren.  N†r
;proceduren ikke benytter WRLN proceduren, er det for at spare p†
;stakforbruget.

TOSP:   ACALL   WRSP                    ;2 mellemrum

;----------------------------------------------------------------------------
;
;Procedure WRSP
;
;Funktion:
;  Udskriver en mellemrum til RS232.
;
;Parameter:
;  Ingen
;
;Reserverede registre: Ingen
;Reserverede flag: Ingen
;
;Stakforbrug:
;  5 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Proceduren udskriver en mellemrum til RS232 med WRITE proceduren.  N†r
;proceduren ikke benytter WRLN proceduren, er det for at spare p†
;stakforbruget.

WRSP:   PUSH    ACC                     ;1 mellemrum
        MOV     A,#" "
WRSP1:  ACALL   WRITE                   ;Udskriv
        POP     ACC
        RET

;----------------------------------------------------------------------------
;
;Procedure ECHO
;
;Funktion:
;  Udskriver tegnet i A registret til RS232, hvis echoflg er sat.
;
;Parameter:
;  A = tegn
;  ECHOFLG
;    False: Udskriver intet
;    True:  Udskriver tegn
;
;Reserverede registre: A
;Reserverede flag: ECHOFLG
;
;Stakforbrug:
;  2 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Proceduren udskriver tegn til RS232 med WRITE proceduren, hvis echoflg er
;sat.

ECHO:   JNB     ECHOFLG,WRRET

;----------------------------------------------------------------------------
;
;Procedure WRITE
;
;Funktion:
;  Udskriver tegnet i A registret til RS232.
;
;Parameter:
;  A = tegn
;
;Reserverede registre: A
;Reserverede flag: Ingen
;
;Stakforbrug:
;  2 bytes, incl. procedurekald.
;
;Beskrivelse:
;  N†r forrige tegn er sendt, ventes p† CTS.  Herefter sendes tegnet i A
;registret.

WRITE:  JNB     TI,WRITE                ;Vent p† sidste data sendt
W1:     JB      CTS,W1                  ;Vent p† CTS
        MOV     SBUF,A                  ;Send A
        CLR     TI                      ;Indiker data sendes
WRRET:  RET                             ;Returner

;----------------------------------------------------------------------------
;
;Procedure HEXWR
;
;Funktion:
;  Udskriver hexidecimalt indholdet af A registret til RS232.
;
;Parameter:
;  A = hexbyte
;
;Reserverede registre: A
;Reserverede flag: Ingen
;
;Stakforbrug:
;  7 bytes, incl. procedurekald.
;
;Beskrivelse:
;  F›rst udskrives high nibble til RS232, med procedure HEXDIG.  Herefter
;udskrives low nibbel til RS232, med proceduren HEXDIG.

HEXWR:  ACALL   HEXWR1                  ;Udf›res 2 gange
HEXWR1: SWAP    A

;----------------------------------------------------------------------------
;
;Procedure HEXDIG
;
;Funktion:
;  Udskriver hexidecimalt low nibbel af A registret til RS232.
;
;Parameter:
;  A = hexdigit
;
;Reserverede registre: A
;Reserverede flag: Ingen
;
;Stakforbrug:
;  5 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Udskriver f›lgende med WRITE proceduren til RS232:
;
;  A reg, bit   Udskriver        A reg, bit   Udskriver
;   3 2 1 0     HEX ASCII         3 2 1 0     HEX ASCII
;  ----------------------        ----------------------
;   0 0 0 0   : 30H   "0"         1 0 0 0   : 38H   "8"
;   0 0 0 1   : 31H   "1"         1 0 0 1   : 39H   "9"
;   0 0 1 0   : 32H   "2"         1 0 1 0   : 41H   "A"
;   0 0 1 1   : 33H   "3"         1 0 1 1   : 42H   "B"
;   0 1 0 0   : 34H   "4"         1 1 0 0   : 43H   "C"
;   0 1 0 1   : 35H   "5"         1 1 0 1   : 44H   "D"
;   0 1 1 0   : 36H   "6"         1 1 1 0   : 45H   "E"
;   0 1 1 1   : 37H   "7"         1 1 1 1   : 46H   "F"

HEXDIG: PUSH    ACC                     ;Gem ACC og PSW
        PUSH    PSW
        ANL     A,#0FH                  ;Isoler low nibble
        ADD     A,#-10                  ;Unders›g om tal eller bogstav
        JNC     HEXWR2                  ;Hop hvis tal
        ADD     A,#7                    ;L‘g 7 til hvis bogstav
HEXWR2: ADD     A,#48+10                ;Beregn ascii v‘rdi
        POP     PSW                     ;Hent flag
        ACALL   WRITE                   ;Udskriv tegn
        POP     ACC                     ;Hent ACC
        RET                             ;Returner

;----------------------------------------------------------------------------
;
;Procedure BINWR
;
;Funktion:
;  Udskriver bin‘rt indholdet af A registret til RS232.
;
;Parameter:
;  A = bindigit
;
;Reserverede registre: A
;Reserverede flag: Ingen
;
;Stakforbrug:
;  8 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Udskriver skriftevis mellemrum og A bin‘rt.
;Er A f.eks 4AH udskrives " 0 1 0 0 1 0 1 0".

BINWR:  PUSH    B                       ;Gem B
        MOV     B,#8                    ;Benyt B som t‘llevariabel
BINWR1: RL      A
        ACALL   WRSP                    ;Udskriv mellemrum
        PUSH    ACC
        ANL     A,#1                    ;Isoler bit 0
        ORL     A,#"0"                  ;Tal starter med "0"
        ACALL   WRITE                   ;Udskriv A
        POP     ACC
        DJNZ    B,BINWR1                ;N‘ste
        POP     B                       ;Hent B
        RET                             ;Returner

;----------------------------------------------------------------------------
;
;Procedure BIGCHAR
;
;Funktion:
;  Oms‘tter et tegn i A registret til stort tegn.
;
;Parameter:
;  A = tegn
;
;Returparameter:
;  A = stor tegn
;
;Reserverede registre: A
;Reserverede flag: C
;
;Stakforbrug:
;  2 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Hvis A registret er i intervallet 60H til 7FH, dvs.  lille tegn, s†
;tr‘kkes 32 fra A registet.

BIGCHAR:CJNE    A,#60H,$+3              ;Hvis <60H, s† returner
        JC      BIGRET
        JB      ACC+7,BIGRET            ;Hvis >=80H, s† returner
        CLR     ACC+5                   ;Ellers lav lille tegn stor
BIGRET: RET                             ;Return

;----------------------------------------------------------------------------
;
;Procedure READ
;
;Funktion:
;  L‘ser et tegn fra RS232 til A registret.
;
;Parameter:
;  ingen
;
;Returparameter:
;  A = tegn
;
;Reserverede registre: A
;Reserverede flag: Ingen
;
;Stakforbrug:
;  2 bytes, incl. procedurekald.
;
;Beskrivelse:
;  F›rst s‘ttes RTS aktiv, for at indikere klar til at modtage.  Herefter
;ventes p† data modtages.  Den modtagede byte gemmes i A registret.

READ:   CLR     RTS                     ;Klar til at modtage
READ1:  JNB     RI,READ1                ;Vent p† data modtaget
        MOV     A,SBUF
        SETB    RTS                     ;Ikke klar til at modtage
        CLR     RI
        RET

;----------------------------------------------------------------------------
;
;Procedure RDLN
;
;Funktion:
;  L‘ser og editerer en linie fra RS232.
;
;Parameter:
;  R0 = Adresse for linie buffer
;  A  = Buffer l‘ngde
;Flag:
;  F0
;    False: Modtager b†de store og sm† tegn
;    True:  Laver sm† tegn til store tegn
;  ECHOFLG
;    False: Echo off
;    True:  Echo on
;
;Returparameter:
;  Der returneres med streng i liniebufferen.
;  A = Antal tegn
;  AC = True for buffer tom
;
;Reserverede registre: A,R0
;Reserverede flag: F0,AC,OV,C,ECHOFLG
;
;Stakforbrug:
;  4 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Det er gjort meget ud af, at lave denne procedure, s† den optager s† lidt
;plads som muligt.  Stakken er p† kun 4 bytes, og der benyttes kun den plads
;i RAM lageret, som bufferen optager.  Der er ingen byte i bufferen, som
;indeholder antallet af tegn, men proceduren returnerer med antallet af tegn
;i A registret.  Af registre benyttes kun R0 og A registret, samt nogle flag.
;  Proceduren holder ›je med, om der indtastes for mange tegn, eller om back
;space benyttes for mange gange.  I s† fald, ignoreres tegnene, og de sendes
;ikke tilbage som echo.
;  Disse ting styres ved at benytte bit 7 af tegnene i bufferen.  Bit 7 er
;sat ved alle tegn, undtagen f›rste og sidste i bufferen.  Men inden der
;returneres, slettes bit 7 ved alle tegn i bufferen, og "procedure brugeren"
;opdager s†ledes ikke disse ting.
;  Bufferens l‘ngde, skal v‘re p† mindst 2 bytes.

RDLN:   DEC     A                       ;Feltl‘ngde-1
        XCH     A,R0                    ;R0 ved enden af felt
        ADD     A,R0
        XCH     A,R0
        MOV     @R0,A                   ;Gem feltl‘ngde-1
RDLN1:  DEC     R0
        MOV     @R0,#80H                ;Gem 80H
        DJNZ    ACC,RDLN1               ;Forts‘t til start af felt
        MOV     @R0,A                   ;Gem 0H
        SETB    AC                      ;Buffer tom
        SETB    PSW+2                   ;Marker ikke enden af buffer i OV flag
        SJMP    RDLN2

RDLN10: CJNE    A,#20H,$+3              ;Hvis tegn <20H s† l‘s igen
        JC      RDLN2
        JNB     PSW+2,RDLN2             ;Hvis buffer fuld, s† l‘s igen
        XCH     A,@R0                   ;Gem tegn
        RLC     A                       ;Unders›g buffer tom eller fuld
        MOV     A,@R0
        JBC     AC,RDLN11               ;Hvis f›rste s† ikke mere f›rste, n‘ste
        MOV     PSW+2,C                 ;clr PSW+2 n†r buffer fuld
        JNC     RDLN11                  ;Hop hvis buffer fuld
        SETB    ACC+7                   ;Hvis ikke buffer tom eller fuld,
                                        ;  s† s‘t bit 7
RDLN11: XCH     A,@R0
        INC     R0                      ;N‘ste tegn
        ACALL   ECHO                    ;Ellers udskriv hvis echoflg

RDLN2:  ACALL   READ                    ;L‘s rs232 port
        JB      ACC+7,RDLN2             ;Tegn skal v‘re <80H
        JNB     F0,RDLN3                ;Oms‘t evt til stort
        ACALL   BIGCHAR

RDLN3:  CJNE    A,#8,RDLN4              ;Back Space?
        JB      AC,RDLN4                ;Hvis noget i buffer s†
        ACALL   ECHO                    ;  Udskriv BS
        DEC     R0                      ;  Forrige tegn
        MOV     A,@R0                   ;  Hent tegn
        RLC     A                       ;  Unders›g om f›rste
        CPL     C
        ANL     C,PSW+2                 ;  F›rste kun n†r OV er sat
        MOV     AC,C                    ;  Hvis f›rste s‘t buffer tom flag
        SETB    PSW+2
        MOV     A,#20H                  ;  Slet tegn
        ACALL   ECHO
        MOV     A,#8H
        ACALL   ECHO

RDLN4:  CJNE    A,#1BH,RDLN5            ;ESC?
        JB      AC,RDLN9                ;Hvis buffer allerede tom, s† returner
        SETB    AC                      ;Ellers s‘t buffer tom
        SJMP    RDLN13                  ;Bestem start af felt

RDLN5:  CJNE    A,#0DH,RDLN10           ;RET?
RDLN9:  CLR     A
        JB      AC,LRET                 ;Returner n†r buffer tom
RDLN13: JB      PSW+2,RDLN7
        INC     A
        DEC     R0
RDLN7:  XCH     A,@R0                   ;Hent tegn
RDLN6:  XCH     A,@R0                   ;Gem tegn
        INC     A                       ;N‘ste ant tegn
        DEC     R0                      ;Forrige tegn
        XCH     A,@R0                   ;Hent tegn
        JBC     ACC+7,RDLN6             ;Forts‘t s† l‘nge bit 7 sat
        XCH     A,@R0                   ;Gem tegn
        JB      AC,RDLN9                ;Hvis buffer tom, s† returner med 0
LRET:   RET                             ;Return

;----------------------------------------------------------------------------
;
;Procedure IGNSP
;
;Funktion:
;  Ignorerer mellemrum fra tegnbuffer
;
;Parameter:
;  R0 = Adresse for tegnbuffer
;  A  = Antal tegn i tegnbuffer
;
;Returparameter:
;  R0 = Adresse for f›rste ikke mellemrum i tegnbuffer
;  A =  Antal tegn tilbage i tegnbuffer
;Flag:
;  C
;    False: Hvis f›rste tegn, som ikke er mellemrum er > 20H
;    True:  Hvis f›rste tegn, som ikke er mellemrum er < 20H
;
;Reserverede registre: A,R0
;Reserverede flag: C
;
;Stakforbrug:
;  2 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Der l‘ses tegn fra tegnbuffer, R0 incrementes, A decrementes, og der
;returneres n†r det l‘ste tegn er forskellig fra mellemrum, eller n†r A=0.

IGNSP:  CJNE    @R0,#20H,LRET           ;Procedure der ignoerer mellemrum
        JZ      LRET                    ;Returner hvis tom
        INC     R0                      ;N‘ste tegn
        DEC     A
        SJMP    IGNSP

;----------------------------------------------------------------------------
;
;Procedure HEXRD
;
;Funktion:
;  L‘ser et HEX ord (2 bytes) fra tegnbuffer.
;
;Parameter:
;  R0 = Adresse for tegnbuffer
;  A  = Antal tegn i tegnbuffer
;  R1 = Adresse for resultat (2 bytes)
;
;Returparameter:
;  R0 = Adresse efter hextal
;  A  = Antal tegn tilbage i tegnbuffer
;  R1 = R1+2
;
;Flag:
;  C
;    False: Fejl i HEX tegn
;    True:  Ok
;
;Reserverede registre: A,R0,R1
;Reserverede flag: AC,OV,C
;
;Stakforbrug:
;  3 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Denne procedure l‘ser et hex tal fra tegnbufferen, og gemmer resultatet
;ved @R1 og @R1+1.  Der accepteres b†de store og sm† bogstaver.  Hvis tegnet
;efter hex tallet ikke er mellemrum eller tom, res‘ttes C flag for indikation
;af fejl.

HEXRD:  MOV     @R1,#0                  ;Reset resultat
        INC     R1
        MOV     @R1,#0
        DEC     R1
HEXRD1: PUSH    ACC                     ;Gem ant tegn
        MOV     A,@R0                   ;Hent tegn
        ADD     A,#-"0"                 ;Hvis <"0" s† fejl
        JNC     HEXERR
        ADD     A,#-10                  ;Hvis A<="9" s† ok
        JNC     HEXOK
        ADD     A,#-7                   ;Hvis A<"A" s† fejl
        JNC     HEXERR
        CJNE    A,#6,$+3                ;Hvis A<="F" s† ok
        JC      HEXOK
        ADD     A,#-20H                 ;Hvis A<"a" s† fejl
        JNC     HEXERR
        CJNE    A,#6,$+3                ;Hvis A>"f" s† fejl
        JNC     HEXERR
HEXOK:  ADD     A,#10                   ;Beregn digit v‘rdi
        XCH     A,@R1                   ;Swap @R1
        SWAP    A
        XCH     A,@R1
        XCHD    A,@R1                   ;Byt A low digit ind i @R0
        INC     R1                      ;High byte
        XCH     A,@R1                   ;Swap @R1
        SWAP    A
        XCH     A,@R1
        XCHD    A,@R1                   ;Byt A high digit ind i @R0
        DEC     R1
        POP     ACC                     ;Hent ant tegn
        INC     R0                      ;N‘ste tegn
        DEC     A
        JZ      HEXTOM                  ;Forts‘t til tom
        CJNE    @R0,#20H,HEXRD1         ;eller mellemrum
HEXTOM: SETB    C                       ;C flag sat n†r ok
        RET
HEXERR: POP     ACC                     ;Hent ant tegn
        RET

;****************************************************************************
;
;       M O N I T O R   P R O G R A M
;
;****************************************************************************
;
;Organisering af intern hukommelse
;        00       01       02       03       04       05        06       07
;00 : ----------------------------Register bank 0----------------------------- .
;08 : ----------------------------Register bank 1----------------------------- .
;10 : ----------------------------Register bank 2----------------------------- .
;18 : ----------------------------Register bank 3----------------------------- .
;20 : Div flag,        ,        ,        ,        ,         ,        ,         .
;28 :         ,        ,        ,        ,        ,         ,        ,         .
;30 :         ,        ,        ,        ,        ,         ,        ,         .
;38 :         ,        ,        ,        ,        ,         ,        ,         .
;40 :         ,        ,        ,        ,        ,         ,        ,         .
;48 :         ,        ,        ,        ,        ,         ,        ,         .
;50 :         ,        ,        ,        ,        ,         ,        ,         .
;58 :         ,        ,        ,        ,        ,         ,        ,         .
;60 :         ,        ,        ,        ,        ,         ,        ,         .
;68 :         ,        ,---------------Stak-----------------,RDLN buffer/stak  .
;70 : ---------------------------RDLN buffer/stak-------------MARGC---MARGCNT- .
;78 :  MARG1L , MARG1H , MARG2L , MARG2H ,  MR0   ,  MACC   ,  MPSW  ,  MSP    .


PRGSP:  EQU     30H
MONSP:  EQU     69H     ;Monitor stak starter ved 6AH

MBUF:   EQU     6EH     ;Monitor RDLN buffer starter ved 6EH
MBUFLEN:EQU     0AH     ;RDLN buffer er 10 bytes lang

MBUF1:  EQU     74H     ;RDLN byte buffer
MBUF1L: EQU     2H      ;2 bytes lang

MARGC:  EQU     76H     ;Argument kommando *2+3
MARGCNT:EQU     77H     ;Antal argumenter

MARG1L: EQU     78H     ;F›rste argument low byte
MARG1H: EQU     79H     ;F›rste argument high byte
MARG2L: EQU     7AH     ;Andet argument low byte
MARG2H: EQU     7BH     ;Andet arugment high byte

MR0:    EQU     7CH     ;Gemmer R0
MACC:   EQU     7DH     ;Gemmer A
MPSW:   EQU     7EH     ;Gemmer flag
MSP:    EQU     7FH     ;Gemmer stak


;Monitor interrupt rutine.
;Skifter mellem monitor og program. Ombytter A, PSW, SP med MACC, MPSW, MSP.

MONINT: MOV     MACC,A                  ;Gem A
        MOV     A,PSW                   ;Ombyt flags og monitor flags
        XCH     A,MPSW
        MOV     PSW,A
        MOV     A,SP                    ;Ombyt SP og monitor SP
        XCH     A,MSP
        MOV     SP,A
        RET                             ;Returner til adresse p† monitor SP


;Her starter monitoren.

MONIT:  SETB    ECHOFLG                 ;Monitor skal sende echo
        ACALL   WRLN                    ;Udskriv tekst
        DFB     0DH,0AH,"Monitor aktiv",0

MON1:   ACALL   WRLN                    ;Udskriv
        DFB     0DH,0AH,"-",0           ;ny linie og streg
        MOV     R0,#MBUF                ;Indl‘sning i MBUF
        MOV     A,#MBUFLEN              ;A=Indl‘sningsbuffer st›rrelse
        SETB    F0                      ;Indl‘s store tegn
        ACALL   RDLN                    ;Kald linieindl‘sningsproceduren
        ACALL   IGNSP                   ;Ignorer mellemrum
        JZ      MON1                    ;Forts‘t til ikke tom
        XCH     A,@R0                   ;Gem kommando p† stak
        PUSH    ACC
        XCH     A,@R0
        INC     R0                      ;N‘ste argument
        DEC     A
        XCH     A,R1                    ;Gem R1 p† stak
        PUSH    ACC
        XCH     A,R1

        ACALL   IGNSP                   ;Ignorer mellemrum
        MOV     R1,#0
        JZ      NARGERR                 ;Afslut hvis tom
        MOV     R1,#MARG1L              ;Oms‘t f›rste argument
        ACALL   HEXRD
        JNC     ARGERR                  ;Udskriv evt fejl
        ACALL   IGNSP
        MOV     R1,#1
        JZ      NARGERR                 ;Afslut hvis tom
        MOV     R1,#MARG2L              ;Oms‘t anden argument
        ACALL   HEXRD
        MOV     R1,#2
        JC      NARGERR                 ;Hop hvis ingen fejl
ARGERR: POP     ACC                     ;Hent R1
        MOV     R1,A
        POP     ACC                     ;Hent kommando

;Argument fejl.
        ACALL   WRLN
        DFB     0DH,0AH,"Argument fejl",0
        SJMP    MON1

;Procedure der udskriver kommandofejl.
CERR:   ACALL   WRLN
        DFB     "Kommandofejl",0
        RET

;Procedure der udskriver parameterfejl.
CNTERR: ACALL   WRLN
        DFB     "For f",134," parametre",0
        RET

;Her forts‘tter programmet, n†r ingen fejl
NARGERR:MOV     MARGCNT,R1
        POP     ACC                     ;Pop R1
        MOV     R1,A
        POP     ACC                     ;Hent kommando
        MOV     R0,A                    ;Gem i R0
        ACALL   NL                      ;Ny linie
        MOV     A,#LOW MON1             ;Gem MON1 adresse p† stak
        PUSH    ACC
        MOV     A,#HIGH MON1
        PUSH    ACC
        MOV     A,R0                    ;Hent kommando
        ADD     A,#-LAST-1              ;Skal v‘re < Y
        JC      CERR                    ;Ellers kommandofejl
        ADD     A,#LAST+1-"A"           ;Hvis < A
        JNC     CERR                    ;S† kommandofejl
        INC     A                       ;*2+3
        RLC     A
        MOV     MARGC,A                 ;Gem kommando i MARGC
        ADD     A,#6
        MOVC    A,@A+PC                 ;Hent lav adresse
        PUSH    ACC
        MOV     A,MARGC                 ;Hent kommando i MARGC
        MOVC    A,@A+PC                 ;Hent h›j adresse
        PUSH    ACC
        RET                             ;Udf›r indstruktion

;Tabel over monitor funktioner
        DWM      LADD                    ;A Add
        DWM      BITMAP                  ;B Bitmap
        DWM      DISPC                   ;C Code
        DWM      DISPD                   ;D Data memry
        DWM      DISPE                   ;E Extern memry
        DWM      DISPF                   ;F Function registers
        DWM      GO                      ;G Go
        DWM      HELP                    ;H Help menu
        DWM      CERR                    ;I
        DWM      CERR                    ;J
        DWM      CERR                    ;K
        DWM      CERR                    ;L
        DWM      CERR                    ;M
        DWM      CERR                    ;N
        DWM      CERR                    ;O
        DWM      XPC                     ;P S‘t PC
        DWM      CERR                    ;Q
        DWM      REG                     ;R Display registre
        DWM      STEP                    ;S Single step
        DWM      TRACE                   ;T Trace n
        DWM      CERR                    ;U
        DWM      CERR                    ;V
        DWM      CERR                    ;W
        DWM      XDATA                   ;X Write to extern memry

LAST:   EQU     "X"

;----------------------------------------------------------------------------
;
;       Monitor rutiner
;
;----------------------------------------------------------------------------

;Rutine for hj‘lp.

HELP:   ACALL   WRLN                    ;Udskrift af hj‘lp
        DFB     "DISPLAY / CHANGE",0DH,0AH
        DFB     "  C Code",0DH,0AH
        DFB     "  D Data memry",0DH,0AH
        DFB     "  E Extern memry",0DH,0AH
        DFB     "  F Function registers",0DH,0AH
        DFB     "  X Exchange",0DH,0AH
        DFB     "SINGLE STEP",0DH,0AH
        DFB     "  G Go",0DH,0AH
        DFB     "  P Set PC",0DH,0AH
        DFB     "  R Show registrs",0DH,0AH
        DFB     "  S Step",0DH,0AH
        DFB     "  T Trace",0DH,0AH
        DFB     "OTHER FUNCTIONS",0DH,0AH
        DFB     "  A Add/Sub",0DH,0AH
        DFB     "  B Show bit map",0DH,0AH
        DFB     "  H Help menu",0
        RET


;Rutine for at vise/‘ndre program counter.
;Viser PC n†r ingen parameter, ellers s‘tter PC=argument.

XPC:    MOV     A,MARGCNT               ;Hvis ingen argumenter,
        JZ      WRPC                    ;s† udskriv PC, ellers
        MOV     R0,MSP                  ;R0 = PC adresse
        MOV     @R0,MARG1H              ;S‘t PCH
        DEC     R0
        MOV     @R0,MARG1L              ;S‘t PCL
        RET                             ;Return


;Rutine der udskriver indholdet af 80C31'erens registre.

REG:    ACALL   WRPC                    ;Udskriv PC
        ACALL   WRLN
        DFB     "  Reg:",0
        MOV     A,PSW                   ;Bestem adresse for R0
        ANL     A,#18H
        MOV     R0,A                    ;Gem i R0
        MOV     A,MR0                   ;Udskriv f›rst program R0
        PUSH    B
        MOV     B,#8                    ;Der er 8 registre
REG1:   ACALL   WRSP                    ;Udskriv mellemrum
        ACALL   HEXWR                   ;Udskriv register indhold
        INC     R0                      ;N‘ste register
        MOV     A,@R0                   ;A= indhold af n‘ste register
        DJNZ    B,REG1                  ;Forts‘t til alle registre udl‘st
        POP     B
        ACALL   WRLN                    ;Udskriv indhold af A
        DFB     "  A=",0
        MOV     A,MACC
        ACALL   HEXWR
        ACALL   WRLN                    ;Udskriv flag
        DFB     "  FLAG=",0
        MOV     A,MPSW
        AJMP    BINWR                   ;Kald BINWR og returner


;Procedure der udskriver indhold af program counter.

WRPC:   ACALL   WRLN
        DFB     " PC=",0
        MOV     R0,MSP                  ;Hent adresse for PC
        MOV     A,@R0                   ;Hent PCH
        MOV     MARG1H,A                ;Gem i MARG1H
        ACALL   HEXWR                   ;Og udskriv
        DEC     R0
        MOV     A,@R0                   ;Hent PCL
        MOV     MARG1L,A                ;Gem i MARG1L
        AJMP    HEXWR                   ;Udskriv PCL


;Rutine der udf›re hovedprogrammet, indtil der modtages noget fra seriel port.
;Hvis breakadresse angivet, singlesteppes indtil adresse n†es.

GO:     CLR     RTS                     ;Klar til at modtage
        MOV     A,MARGCNT               ;Hvis parameter (breakpoint)
        JNZ     GO2                     ;s† step
GO3:    JNB     TI,GO3                  ;Vent p† sidste data sendt
        CLR     TI                      ;Ingen transmit interrupt
        ACALL   SCONT                   ;Run program
        SETB    TI                      ;Angiv data er sendt
        RET                             ;Returner
GO2:    MOV     MARG2L,MARG1L           ;MARG2 indeholder breakpoint
        MOV     MARG2H,MARG1H
GO1:    ACALL   SSTEP                   ;Singlestep
        ACALL   WRPC                    ;Udskriv PC
        JB      RI,GORET                ;Afslut hvis modtaget data
        MOV     A,MARG1L                ;Unders›g om PCL=brkadrL
        CJNE    A,MARG2L,GO1            ;Ellers step n‘ste
        MOV     A,MARG1H                ;Hvis ikke PCH=brkadrH
        CJNE    A,MARG2H,GO1            ;s† step n‘ste
GORET:  SETB    RTS                     ;Ikke klar til at modtage
        RET                             ;Return


;Rutine der singlestepper n step, og udskriver registre hver gang.

TRACE:  MOV     MARG2H,#0               ;MARG2H er 0 ved trace
        SJMP    S4


;Rutine der singlestepper n step, men f›rst udskriver registre bagefter.

STEP:   MOV     MARG2H,#1               ;MARG2H er 1 ved step
S4:     MOV     MARG2L,MARG1L           ;MARG2L er antal
        MOV     A,MARGCNT               ;Step 1 gang hvis ingen parameter
        JNZ     S3
        MOV     MARG2L,#1
S3:     CLR     A                       ;A=0 for altid at udskrive reg. 1.gang
S1:     JNZ     S2                      ;Udskriv ikke registre n†r MARG2H er 1
        ACALL   REG                     ;Udskriv registre
        MOV     MARGCNT,#1              ;Udskriv 1 codelinie
        CLR     PSW+1
        ACALL   DISPLN
        ACALL   NL                      ;Ny linie
S2:     ACALL   SSTEP                   ;Single step
        MOV     A,MARG2H                ;Unders›g om trace/step
        DJNZ    MARG2L,S1               ;Forts‘t antal gange
        AJMP    REG                     ;Udskriv registre


;Rutine der addere argument 1 og 2 og udskriver resultat.

LADD:   MOV     A,MARGCNT               ;Unders›g om 2 argumenter
        CJNE    A,#2,LADD1              ;Ellers argument fejl
        MOV     A,MARG1L                ;Adder low bytes
        ADD     A,MARG2L
        MOV     R0,A                    ;Gem sum low byte i R0
        MOV     A,MARG1H                ;Adder high bytes
        ADDC    A,MARG2H
        ACALL   HEXWR                   ;Udskriv
        MOV     A,R0                    ;Hent sum low byte
        ACALL   HEXWR                   ;Udskriv
        ACALL   WRSP                    ;Udskriv mellemrum
        CLR     C                       ;Ingen carry
        MOV     A,MARG1L                ;Subtraher low bytes
        SUBB    A,MARG2L
        MOV     R0,A                    ;Gem sub low byte i R0
        MOV     A,MARG1H                ;Subtraher high bytes
        SUBB    A,MARG2H
        ACALL   HEXWR                   ;Udskriv sub high byte
        MOV     A,R0                    ;Hent sub low byte
        AJMP    HEXWR                   ;Udskriv og returner
LADD1:  AJMP    CNTERR


;Rutine der udskriver indholdet af 80C31"erens bit

BITMAP:
;Udskriv 7 6 5 4 3 2 1 0 - F E D C B A 9 8
        ACALL   TOSP                    ;6 mellemrum
        ACALL   TOSP
        ACALL   TOSP
        MOV     A,#7                    ;Start ved 7
BM1:    ACALL   HEXDIG                  ;Udskriv digit
        ACALL   WRSP                    ;mellemrum
        JNZ     BM2                     ;Efter 0 :
        ACALL   WRLN                    ;  skriv -
        DFB     "- ",0
BM2:    DEC     A                       ;N‘ste
        CJNE    A,#0F7H,BM1             ;Forts‘t til -8
        ACALL   NL                      ;Ny linie
;Udskriv bitmap
        SETB    F0                      ;S‘t flag for SFR read/write
        SETB    PSW+1
        MOV     MARGCNT,R1              ;Benyt MARGCNT til at gemme R1
        MOV     R1,#20H                 ;Startadresse for bit 0-7f
        CLR     A                       ;R0=A=0 for startadresse
        MOV     R0,A
BM5:    ACALL   WRSP                    ;Skriv mellemrum
        ACALL   HEXWR                   ;Udskriv bit adr
        ACALL   WRLN                    ;Skriv :
        DFB     ": ",0
        ACALL   BM4                     ;Udskriv byte, n‘ste byte
        ACALL   WRLN                    ;Skriv -
        DFB     " -",0
        ACALL   BM4                     ;Udskriv byte, n‘ste byte
        ACALL   NL                      ;Ny linie
        MOV     A,R0                    ;A=Adr
        JNZ     BM5                     ;Forts‘t til 0
        MOV     R1,MARGCNT              ;Hent R1 fra MARGCNT
        RET                             ;Returner


;Procedure der udskriver byte bin‘r.

BM4:    ACALL   RDMEM                   ;A = SFR(adr)
        CJNE    R0,#80H,$+3             ;Hvis adr<80, s†
        JNC     BM3
        MOV     A,@R1                   ;  L‘s fra user flag area
BM3:    XCH     A,R0                    ;N‘ste adr
        ORL     A,#7
        INC     A
        XCH     A,R0
        INC     R1                      ;N‘ste adr i user flag area
        AJMP    BINWR                   ;Udskriv bin‘rt


;Rutine til display af extern ram.

DISPE:  SETB    PSW+1                   ;Extern ram
        SJMP    DISPC1


;Rutine til display af code.

DISPC:  CLR     PSW+1                   ;CODE
DISPC1: MOV     MARGCNT,#11H            ;17 linier


;Procedure til display af en code linie.

DISPLN: CLR     F0                      ;Extern ram / code
        MOV     R0,MARG1L               ;Start ved Lav adresse
        SJMP    DISP7


;Procedure til display af intern data ram.

DISPD:  CLR     PSW+1                   ;Udskriv data memry
        SJMP    DISP6


;Procedure til display af SFRs.

DISPF:  SETB    PSW+1                   ;Udskriv SFRs
DISP6:  MOV     MARGCNT,#10H            ;16 linier
        MOV     R0,#0                   ;Start ved adr 0
        SETB    F0                      ;Intern ram


;Display rutine.

DISP7:  PUSH    DPH
        MOV     DPH,MARG1H
DISP5:  MOV     MARG1L,R0               ;Gem aktuel adresse
        MOV     MARG1H,DPH
        ACALL   NL
        ACALL   TOSP
        JB      F0,DISP4                ;Kun 1 byte adresse n†r F0=1
        MOV     A,DPH                   ;Udskriv H adresse
        ACALL   HEXWR
DISP4:  MOV     A,R0                    ;Udskriv Lav adresse
        ACALL   HEXWR
        ACALL   WRLN
        DFB     ": ",0
        MOV     MARGC,#10H              ;Benyte MARGC som t‘llevariabel
DISP1:  ACALL   RDMEM                   ;L‘s byte
        ACALL   HEXWR                   ;Udskriv hexidecimalt
        ACALL   WRSP                    ;Udskriv mellemrum
        MOV     A,MARGC
        CJNE    A,#9,DISP8
        ACALL   WRLN                    ;Udskriv " - " efter 8 tegn
        DFB     "- ",0
DISP8:  DJNZ    MARGC,DISP1
        ACALL   TOSP
        MOV     R0,MARG1L               ;Forfra
        MOV     DPH,MARG1H
        MOV     MARGC,#10H              ;Benyt MARGC som t‘llevariabel
DISP3:  ACALL   RDMEM
        CJNE    A,#20,$+3
        JNC     DISP2
        MOV     A,#"."                  ;Udskriv "." hvis <" "
DISP2:  ACALL   WRITE
        MOV     A,MARGC
        CJNE    A,#9,DISP9
        ACALL   WRLN                    ;Udskriv " - " efter 8 tegn
        DFB     " - ",0
DISP9:  DJNZ    MARGC,DISP3
        DJNZ    MARGCNT,DISP5           ;MARGCNT indeholder ant linier
        POP     DPH
X2:     RET

CERR1:  AJMP    CERR                    ;Udskriver kommandofejl og returnerer


;Rutine til ‘ndring af data i datamemory,extern memory eller sfr.

XDATA:  MOV     A,MARGCNT               ;Kommandofejl hvis ingen parametre
        JZ      CERR1
        MOV     A,MARG1L                ;Hent 2. kommando
        ADD     A,#-0DH                 ;Fejl hvis <D
        JNC     CERR1
        ADD     A,#-3                   ;Fejl hvis >E
        JC      CERR1
        RRC     A                       ;Ops‘t PSW+1 og F0
        MOV     F0,C
        RRC     A
        MOV     PSW+1,C

X1:     ACALL   NL                      ;Udskriv ny linie og 2 mellemrum
        ACALL   TOSP
        PUSH    DPH                     ;Gem DPH
        JB      F0,X3                   ;Hop hvis F0, hvis ej F0, s†
        MOV     A,MARG2H                ;  Hent h›j adresse
        MOV     DPH,A                   ;  Gem i DPH
        ACALL   HEXWR                   ;  Udskriv hexidecimalt
X3:     MOV     A,MARG2L                ;Hent lav adresse
        MOV     R0,A                    ;Gem i R0
        ACALL   HEXWR                   ;Udskriv hexidecimalt
        ACALL   WRLN                    ;Udskriv kolon og mellemrum
        DFB     ": ",0
        ACALL   RDMEM                   ;L‘s indhold af adresse
        ACALL   HEXWR                   ;Udskriv
        ACALL   WRLN                    ;Udksriv mellemrum og lig
        DFB     " =",0
        MOV     R0,#MBUF1               ;Opstil adresse for buffer
        MOV     A,#MBUF1L               ;Buffers l‘ngde
        ACALL   RDLN                    ;Indl‘s
        MOV     MARGCNT,R1              ;Benyt MARGCNT som register, gem R1
        MOV     R1,#MARG1L              ;Adresse for resultat
        ACALL   HEXRD                   ;Oms‘t
        MOV     R1,MARGCNT              ;Hent R1 fra MARGCNT
        POP     DPH                     ;Hent DPH
        JNC     X2                      ;Afslut hvis fejl, ellers
        MOV     A,MARG1L                ;Hent byte
        MOV     R0,MARG2L               ;Hent adresse
        MOV     DPH,MARG2H
        SETB    AC                      ;Write til memory
        ACALL   RDWRMEM
        MOV     MARG2H,DPH              ;Gem adresse
        MOV     MARG2L,R0
        SJMP    X1                      ;N‘ste


;Procedure for l‘sning af code, datamemory, extern memory og sfrs.

RDMEM:  CLR     AC                      ;AC flag = false for read


;Procedure RDWRMEM
;
;Funktion:
;  L‘ser/skriver fra code, datamemory, extern memory og sfrs, samt l‘gger en
;adressen.
;
;Parameter:
;  A = data der skal gemmes, ved write.  Ellers ligegyldig.
;  R0 = low adr
;  DPH = high adr, ved code/ext ram read/write.  Ellers ligegyldig
;
;  F0, PSW+1 og AC bestemmer mode:
;    F0  PSW+1   AC      Funktion
;     0     0     0      L‘s CODE
;     0     0     1      L‘s CODE
;     0     1     0      L‘s EXT ram
;     0     1     1      Skriv EXT ram
;     1     0     0      L‘s DATA ram
;     1     0     1      Skriv DATA ram
;     1     1     0      L‘s SFR
;     1     1     1      Skriv SFR
;  hvor 0 er false og 1 er true
;
;Returparameter:
;  A = Data
;  R0 = n‘ste low adr
;  DPH = n‘ste high adr, hvis code/ext ram read/write.  Ellers ingen ‘ndring.
;
;Reserverede registre: A,R0. DPH hvis code/ext ram read/write.
;Reserverede flag: F0, PSW+1, AC og C
;
;Stakforbrug:
;  8 bytes, incl. procedurekald.
;
;Beskrivelse:
;  Hvis F0=PSW+1=0
;    s† l‘ses fra code med MOVC A,@A+DPTR indstruktionen, hvor A=0 og DPL=R0
;  Hvis F0=0, PSW+1=1, AC=0
;    s† l‘ses fra extern ram med MOVX A,@DPTR, hvor DPL=R0.
;  Hvis F0=0, PSW+1=1, AC=1
;    s† skrives til ext. ram med MOVX @DPTR,A, hvor DPL=R0.
;  Hvis F0=1, PSW+1=0, AC=0
;    s† l‘ses fra intern data ram med MOV A,@R0.
;    Dog l‘ses MR0 n†r R0 er adressen for R0.
;  Hvis F0=1, PSW+1=0, AC=1
;    s† skrives til intern data ram med MOV @R0,A.
;    Dog skrives MR0 n†r R0 er adressen for R0.
;  Hvis F0=1, PSW+1=1, AC=0
;    hvis R0<80H, s† l‘ses fra intern data ram med MOV A,@R0.
;      Dog l‘ses MR0 n†r R0 er adressen for R0.
;    ellers singlesteppes indstruktionen p† adressen SFRBLK+2*(R0-80H)
;      Dog l‘ses MACC for R0=#ACC og MSP for R0=#SP.
;  Hvis F0=1, PSW+1=1, AC=1
;    hvis R0<80H, s† skrives til intern data ram med MOV @R0,A.
;      Dog skrives MR0 n†r R0 er adressen for R0.
;    ellers singlesteppes indstruktionen p† adressen SFRBLK+2*(R0-80H)+101H
;      Dog skrives i MACC for R0=#ACC og i MSP for R0=#SP.

RDWRMEM:JB      F0,RDWR4                ;Hop hvis l‘s/skriv data ram/sfr
        PUSH    DPL                     ;Gem DPL
        MOV     DPL,R0                  ;DPL=adr lav
        JB      PSW+1,RDWR1             ;L‘s fra code n†r PSW+1=0, ellers hop
        CLR     A                       ;L‘s code
        MOVC    A,@A+DPTR
        SJMP    RDWR3                   ;N‘ste adresse

RDWR1:  JNB     AC,RDWR2                ;Hop hvis AC=0 ellers
        MOVX    @DPTR,A                 ;  Skriv til ext ram
RDWR2:  MOVX    A,@DPTR                 ;L‘s fra ext ram
RDWR3:  INC     DPTR                    ;N‘ste DPH
        POP     DPL                     ;Hent DPL
        INC     R0                      ;N‘ste R0
        RET


;L‘s/skriv data ram/sfr.

RDWR4:  PUSH    MACC                    ;Gem MACC
        JNB     AC,RDWR5                ;Hvis AC=1 s† skriv, ellers l‘s
        MOV     MACC,A                  ;Gem A i MACC hvis skriv
RDWR5:  JB      PSW+1,RDWR11            ;Hop hvis sfr


;L‘s/skriv data ram.

RDWR6:  MOV     A,PSW                   ;Hent flag
        ANL     A,#18H                  ;Beregn adresse for R0
        XRL     A,R0                    ;Unders›g om R0
        JNZ     RDWR8                   ;Hop hvis ikke R0, hvis R0 s†
        JNB     AC,RDWR7                ;  Hop hvis l‘s, ellers
        MOV     MR0,MACC                ;    skriv R0
RDWR7:  MOV     A,MR0                   ;L‘s R0
        SJMP    RDWR10                  ;Returner
RDWR8:  JNB     AC,RDWR9                ;Hop hvis l‘s, hvis skriv s†
        MOV     A,MACC                  ;  Hent A
        MOV     @R0,A                   ;  Skriv @R0
RDWR9:  MOV     A,@R0                   ;L‘s @R0
RDWR10: POP     MACC                    ;Returner
        INC     R0                      ;N‘ste R0
        RET

RDWR11: CJNE    R0,#SP,RDWR12           ;Hvis SP, ellers hop
        JNB     AC,RDWR12               ;Hvis AC=1, s† skriv, ellers hop
        INC     A                       ;L‘g 2 til A
        INC     A
        MOV     MSP,A                   ;Gem i MSP
RDWR12: MOV     A,R0                    ;A=SFR adresse
        JNB     ACC+7,RDWR6             ;Hop hvis <80H til data
        PUSH    MSP                     ;Gem MSP
        MOV     C,AC                    ;C=l‘se/skrive
        ACALL   SSFR                    ;Single step MOV SFR instruktion
        POP     MSP                     ;Hent MSP
        POP     ACC                     ;Hent MACC fra stak
        MOV     C,P                     ;C = Paritet
        XCH     A,MPSW                  ;S‘t rigtig paritetflag i MPSW
        MOV     ACC+0,C
        XCH     A,MPSW
        XCH     A,MACC                  ;A=MACC, Restore MACC
        CJNE    R0,#SP,RDWR13           ;Hop hvis ej SP, hvis SP s†
        DEC     A                       ;Tr‘k 2 fra
        DEC     A
RDWR13: CJNE    R0,#ACC,RDWR14          ;Hop hvis ej ACC, hvis ACC s†
        MOV     MACC,A                  ;Gem i MACC
RDWR14: INC     R0                      ;N‘ste R0
        RET

SSFR:
;Udf›rer MOV A,direct n†r C=0, MOV direct,A n†r C=1. Adr=SFRBLK+A*2+C
        RLC     A                       ;Beregn A*2+C
        ADD     A,#LOW SFRBLK           ;Beregn low(SFRBLK+A+#100H*(A AND #1))
        PUSH    ACC                     ;Gem indstruktion lav adresse
        ADD     A,#-LOW SFRBLK          ;Reberegn A. C = NOT C = 1-C
        ANL     A,#1                    ;Beregn A AND #1
        SUBB    A,#-{{HIGH SFRBLK}+1}   ;Beregn A+(high(SFRBLK)+1)-C
        PUSH    ACC                     ;Gem indstruktion h›j adresse
        MOV     MSP,SP                  ;stak=monitor stak, (Husk at gemme MSP)
        POP     ACC                     ;Normaliser SP inden ret
        POP     ACC

;Single step rutine
SSTEP:  JNB     TI,SSTEP                ;Vent p† sidste data sendt, interrupt
SCONT:  MOV     A,PSW                   ;Ombyt flags og monitor flags
        XCH     A,MPSW
        MOV     PSW,A
        MOV     A,SP                    ;Ombyt SP og monitor SP
        XCH     A,MSP
        MOV     SP,A
        MOV     A,MACC                  ;A=MACC
        RETI                            ;Single step


;Indstruktioner til l‘sning og skrivning i SFR
;Der er ikke mulighed for inddirekte adressering af SFR"s, derfor laves
;MOV A,direct og MOV direct,A ved at singlesteppe indstruktionerne.

;MOV A,direct block

SFRBLK: MOV     A,080H                  ;080H
        MOV     A,081H                  ;081H
        MOV     A,082H                  ;082H
        MOV     A,083H                  ;083H
        MOV     A,084H                  ;084H
        MOV     A,085H                  ;085H
        MOV     A,086H                  ;086H
        MOV     A,087H                  ;087H
        MOV     A,088H                  ;088H
        MOV     A,089H                  ;089H
        MOV     A,08AH                  ;08AH
        MOV     A,08BH                  ;08BH
        MOV     A,08CH                  ;08CH
        MOV     A,08DH                  ;08DH
        MOV     A,08EH                  ;08EH
        MOV     A,08FH                  ;08FH
        MOV     A,090H                  ;090H
        MOV     A,091H                  ;091H
        MOV     A,092H                  ;092H
        MOV     A,093H                  ;093H
        MOV     A,094H                  ;094H
        MOV     A,095H                  ;095H
        MOV     A,096H                  ;096H
        MOV     A,097H                  ;097H
        MOV     A,098H                  ;098H
        MOV     A,099H                  ;099H
        MOV     A,09AH                  ;09AH
        MOV     A,09BH                  ;09BH
        MOV     A,09CH                  ;09CH
        MOV     A,09DH                  ;09DH
        MOV     A,09EH                  ;09EH
        MOV     A,09FH                  ;09FH
        MOV     A,0A0H                  ;0A0H
        MOV     A,0A1H                  ;0A1H
        MOV     A,0A2H                  ;0A2H
        MOV     A,0A3H                  ;0A3H
        MOV     A,0A4H                  ;0A4H
        MOV     A,0A5H                  ;0A5H
        MOV     A,0A6H                  ;0A6H
        MOV     A,0A7H                  ;0A7H
        MOV     A,0A8H                  ;0A8H
        MOV     A,0A9H                  ;0A9H
        MOV     A,0AAH                  ;0AAH
        MOV     A,0ABH                  ;0ABH
        MOV     A,0ACH                  ;0ACH
        MOV     A,0ADH                  ;0ADH
        MOV     A,0AEH                  ;0AEH
        MOV     A,0AFH                  ;0AFH
        MOV     A,0B0H                  ;0B0H
        MOV     A,0B1H                  ;0B1H
        MOV     A,0B2H                  ;0B2H
        MOV     A,0B3H                  ;0B3H
        MOV     A,0B4H                  ;0B4H
        MOV     A,0B5H                  ;0B5H
        MOV     A,0B6H                  ;0B6H
        MOV     A,0B7H                  ;0B7H
        MOV     A,0B8H                  ;0B8H
        MOV     A,0B9H                  ;0B9H
        MOV     A,0BAH                  ;0BAH
        MOV     A,0BBH                  ;0BBH
        MOV     A,0BCH                  ;0BCH
        MOV     A,0BDH                  ;0BDH
        MOV     A,0BEH                  ;0BEH
        MOV     A,0BFH                  ;0BFH
        MOV     A,0C0H                  ;0C0H
        MOV     A,0C1H                  ;0C1H
        MOV     A,0C2H                  ;0C2H
        MOV     A,0C3H                  ;0C3H
        MOV     A,0C4H                  ;0C4H
        MOV     A,0C5H                  ;0C5H
        MOV     A,0C6H                  ;0C6H
        MOV     A,0C7H                  ;0C7H
        MOV     A,0C8H                  ;0C8H
        MOV     A,0C9H                  ;0C9H
        MOV     A,0CAH                  ;0CAH
        MOV     A,0CBH                  ;0CBH
        MOV     A,0CCH                  ;0CCH
        MOV     A,0CDH                  ;0CDH
        MOV     A,0CEH                  ;0CEH
        MOV     A,0CFH                  ;0CFH
        MOV     A,0D0H                  ;0D0H
        MOV     A,0D1H                  ;0D1H
        MOV     A,0D2H                  ;0D2H
        MOV     A,0D3H                  ;0D3H
        MOV     A,0D4H                  ;0D4H
        MOV     A,0D5H                  ;0D5H
        MOV     A,0D6H                  ;0D6H
        MOV     A,0D7H                  ;0D7H
        MOV     A,0D8H                  ;0D8H
        MOV     A,0D9H                  ;0D9H
        MOV     A,0DAH                  ;0DAH
        MOV     A,0DBH                  ;0DBH
        MOV     A,0DCH                  ;0DCH
        MOV     A,0DDH                  ;0DDH
        MOV     A,0DEH                  ;0DEH
        MOV     A,0DFH                  ;0DFH
        NOP                             ;NOP, da MOV A,ACC laver mystiske ting
        NOP
        MOV     A,0E1H                  ;0E1H
        MOV     A,0E2H                  ;0E2H
        MOV     A,0E3H                  ;0E3H
        MOV     A,0E4H                  ;0E4H
        MOV     A,0E5H                  ;0E5H
        MOV     A,0E6H                  ;0E6H
        MOV     A,0E7H                  ;0E7H
        MOV     A,0E8H                  ;0E8H
        MOV     A,0E9H                  ;0E9H
        MOV     A,0EAH                  ;0EAH
        MOV     A,0EBH                  ;0EBH
        MOV     A,0ECH                  ;0ECH
        MOV     A,0EDH                  ;0EDH
        MOV     A,0EEH                  ;0EEH
        MOV     A,0EFH                  ;0EFH
        MOV     A,0F0H                  ;0F0H
        MOV     A,0F1H                  ;0F1H
        MOV     A,0F2H                  ;0F2H
        MOV     A,0F3H                  ;0F3H
        MOV     A,0F4H                  ;0F4H
        MOV     A,0F5H                  ;0F5H
        MOV     A,0F6H                  ;0F6H
        MOV     A,0F7H                  ;0F7H
        MOV     A,0F8H                  ;0F8H
        MOV     A,0F9H                  ;0F9H
        MOV     A,0FAH                  ;0FAH
        MOV     A,0FBH                  ;0FBH
        MOV     A,0FCH                  ;0FCH
        MOV     A,0FDH                  ;0FDH
        MOV     A,0FEH                  ;0FEH
        MOV     A,0FFH                  ;0FFH

;MOV direct,A block

        NOP
        MOV     080H,A                  ;080H
        MOV     081H,A                  ;081H
        MOV     082H,A                  ;082H
        MOV     083H,A                  ;083H
        MOV     084H,A                  ;084H
        MOV     085H,A                  ;085H
        MOV     086H,A                  ;086H
        MOV     087H,A                  ;087H
        MOV     088H,A                  ;088H
        MOV     089H,A                  ;089H
        MOV     08AH,A                  ;08AH
        MOV     08BH,A                  ;08BH
        MOV     08CH,A                  ;08CH
        MOV     08DH,A                  ;08DH
        MOV     08EH,A                  ;08EH
        MOV     08FH,A                  ;08FH
        MOV     090H,A                  ;090H
        MOV     091H,A                  ;091H
        MOV     092H,A                  ;092H
        MOV     093H,A                  ;093H
        MOV     094H,A                  ;094H
        MOV     095H,A                  ;095H
        MOV     096H,A                  ;096H
        MOV     097H,A                  ;097H
        MOV     098H,A                  ;098H
        MOV     099H,A                  ;099H
        MOV     09AH,A                  ;09AH
        MOV     09BH,A                  ;09BH
        MOV     09CH,A                  ;09CH
        MOV     09DH,A                  ;09DH
        MOV     09EH,A                  ;09EH
        MOV     09FH,A                  ;09FH
        MOV     0A0H,A                  ;0A0H
        MOV     0A1H,A                  ;0A1H
        MOV     0A2H,A                  ;0A2H
        MOV     0A3H,A                  ;0A3H
        MOV     0A4H,A                  ;0A4H
        MOV     0A5H,A                  ;0A5H
        MOV     0A6H,A                  ;0A6H
        MOV     0A7H,A                  ;0A7H
        MOV     0A8H,A                  ;0A8H
        MOV     0A9H,A                  ;0A9H
        MOV     0AAH,A                  ;0AAH
        MOV     0ABH,A                  ;0ABH
        MOV     0ACH,A                  ;0ACH
        MOV     0ADH,A                  ;0ADH
        MOV     0AEH,A                  ;0AEH
        MOV     0AFH,A                  ;0AFH
        MOV     0B0H,A                  ;0B0H
        MOV     0B1H,A                  ;0B1H
        MOV     0B2H,A                  ;0B2H
        MOV     0B3H,A                  ;0B3H
        MOV     0B4H,A                  ;0B4H
        MOV     0B5H,A                  ;0B5H
        MOV     0B6H,A                  ;0B6H
        MOV     0B7H,A                  ;0B7H
        MOV     0B8H,A                  ;0B8H
        MOV     0B9H,A                  ;0B9H
        MOV     0BAH,A                  ;0BAH
        MOV     0BBH,A                  ;0BBH
        MOV     0BCH,A                  ;0BCH
        MOV     0BDH,A                  ;0BDH
        MOV     0BEH,A                  ;0BEH
        MOV     0BFH,A                  ;0BFH
        MOV     0C0H,A                  ;0C0H
        MOV     0C1H,A                  ;0C1H
        MOV     0C2H,A                  ;0C2H
        MOV     0C3H,A                  ;0C3H
        MOV     0C4H,A                  ;0C4H
        MOV     0C5H,A                  ;0C5H
        MOV     0C6H,A                  ;0C6H
        MOV     0C7H,A                  ;0C7H
        MOV     0C8H,A                  ;0C8H
        MOV     0C9H,A                  ;0C9H
        MOV     0CAH,A                  ;0CAH
        MOV     0CBH,A                  ;0CBH
        MOV     0CCH,A                  ;0CCH
        MOV     0CDH,A                  ;0CDH
        MOV     0CEH,A                  ;0CEH
        MOV     0CFH,A                  ;0CFH
        MOV     0D0H,A                  ;0D0H
        MOV     0D1H,A                  ;0D1H
        MOV     0D2H,A                  ;0D2H
        MOV     0D3H,A                  ;0D3H
        MOV     0D4H,A                  ;0D4H
        MOV     0D5H,A                  ;0D5H
        MOV     0D6H,A                  ;0D6H
        MOV     0D7H,A                  ;0D7H
        MOV     0D8H,A                  ;0D8H
        MOV     0D9H,A                  ;0D9H
        MOV     0DAH,A                  ;0DAH
        MOV     0DBH,A                  ;0DBH
        MOV     0DCH,A                  ;0DCH
        MOV     0DDH,A                  ;0DDH
        MOV     0DEH,A                  ;0DEH
        MOV     0DFH,A                  ;0DFH
        NOP                             ;NOP, da MOV ACC,A laver mystiske ting
        NOP
        MOV     0E1H,A                  ;0E1H
        MOV     0E2H,A                  ;0E2H
        MOV     0E3H,A                  ;0E3H
        MOV     0E4H,A                  ;0E4H
        MOV     0E5H,A                  ;0E5H
        MOV     0E6H,A                  ;0E6H
        MOV     0E7H,A                  ;0E7H
        MOV     0E8H,A                  ;0E8H
        MOV     0E9H,A                  ;0E9H
        MOV     0EAH,A                  ;0EAH
        MOV     0EBH,A                  ;0EBH
        MOV     0ECH,A                  ;0ECH
        MOV     0EDH,A                  ;0EDH
        MOV     0EEH,A                  ;0EEH
        MOV     0EFH,A                  ;0EFH
        MOV     0F0H,A                  ;0F0H
        MOV     0F1H,A                  ;0F1H
        MOV     0F2H,A                  ;0F2H
        MOV     0F3H,A                  ;0F3H
        MOV     0F4H,A                  ;0F4H
        MOV     0F5H,A                  ;0F5H
        MOV     0F6H,A                  ;0F6H
        MOV     0F7H,A                  ;0F7H
        MOV     0F8H,A                  ;0F8H
        MOV     0F9H,A                  ;0F9H
        MOV     0FAH,A                  ;0FAH
        MOV     0FBH,A                  ;0FBH
        MOV     0FCH,A                  ;0FCH
        MOV     0FDH,A                  ;0FDH
        MOV     0FEH,A                  ;0FEH
        MOV     0FFH,A                  ;0FFH


;****************************************************************************
;
;       Start og initialisering
;
;****************************************************************************

        ORG     800H

FOSC:   EQU     384                     ;Osc frekvens / 19200
RATE:   EQU     96                      ;9600 baud
SMOD:   EQU     80H


START:
;----------------------------------------------------------------------------
;
;       Ops‘t og initialiser seriel port.
;
;----------------------------------------------------------------------------

        ORL     PCON,#SMOD              ;SETB SMOD
        MOV     SCON,#52H               ;8 bit, 0D0H for 9 bit
        MOV     TH1,#256-{FOSC/RATE}    ;Ops‘t baudrate
        MOV     TMOD,#20H               ;Timer 1 auto reload
        SETB    TR1                     ;Start timer 1


;----------------------------------------------------------------------------
;
;       Ops‘t monitor og program stak.  Enable seriel interrupt.
;
;----------------------------------------------------------------------------

        MOV     SP,#MONSP               ;S‘t monitor stak
        MOV     A,#LOW MONIT            ;Gem monitor adresse p† monitor stak
        PUSH    ACC
        MOV     A,#HIGH MONIT
        PUSH    ACC
        MOV     MSP,SP                  ;MSP = monitor stak
        MOV     SP,#PRGSP               ;SP = program stak

;Enable seriel interrupt.
        SETB    EA                      ;Enable interrupts
        SETB    ES                      ;Enable seriel interrupt

;****************************************************************************
;
;       P R O G R A M
;
;****************************************************************************
;
;Lille program eksempel, som laver lyd n†r h›jttaler tilsluttes P1 bit 0.
;God til at teste MSC51 system.

L0:     MOV     A,#20H
L2:     NOP
        NOP
L3:     DJNZ    R2,L1
        INC     P1
        MOV     R2,A
L1:     DJNZ    R3,L2
        DJNZ    ACC,L2
        SJMP    L0

        END

