PGM 8086 MONITOR
TTL MONITOR2
REL
*
* This version allows Tripos to start at absolute
* location #500
*
*
BEGIN EQU $
*
*
*
CLKCTL EQU #B6 SET UP TIMER 2 AS CLOCK
TIMCTL EQU #D6 ADD OF TIMER CONTROL
TIM2 EQU #D4 ADD OF TIMER 2
CNCTL EQU #DA ADD OF ONBOARD USART
MODE EQU #4E USART AS VDU
CMD EQU #27 SET USART OFF
INT3 EQU #CC INT3 COMMAND
*
*
UIO0 EQU #B0 BUFFER OF USART 0
UST0 EQU #B1 STATUS OF USART 0
UIO1 EQU #B2
UST1 EQU #B3
UIO2 EQU #B4
UST2 EQU #B5
UIO3 EQU #B6
UST3 EQU #B7
*
*
*
*
* TABLE OF VARIOUS BAUD RATES
*
*
RATET EQU $
B38400 DW 2
B19200 DW 4
B9600 DW 8
B4800 DW 16
B2400 DW 32
B1200 DW 64
B600 DW 128
B300 DW 256
B150 DW 512
B110 DW 698
B75 DW 1024
NRATES EQU $-RATET NUMBER OF RATES IN TABLE
*
*
*
*
*
*
*SET UP SOME CHARACTERS
*
*
*
CR EQU #D
LF EQU #A
ESC EQU #1B
BRCHR EQU #1B
*
*
*
*
CONST EQU #DE ADD OF CONSOLE STATUS
CONDR EQU #DC ADD OF INPUT-OUTPUT OF CONSOLE
TRDY EQU 1 DATA FOR CONSOLE
RBR EQU 2 CONSOLE READ READY
*
*
*
*CONSTANT DEFINITIONS
*
*
*
PRTY0 EQU #7F MASK TO BLANK OFF PARITY
*RSAV EQU -- START ADD OF SAVED REGS-DEFINED LATER
*TABLE EQU -- START OF RECOGNISED SYMBOLS-LATER
*CTAB EQU -- START OF RECOGNISED COMMANDS
*NCMDS EQU -- NO OF RECOGNISED COMMANDS
*CADR EQU -- START OF COMMAND ADDRESSES
*LSGNON EQU -- LENGTH OF SIGN ON MESSAGE-DEFINED LATER
MSEG EQU #40 MONITOR DATA SEGMENT AT #400
*MSEG EQU #500 FOR TESTS AT 4000
LMSEG DW MSEG START OF MONITOR TABLES-DS,SS&ES
MSTAK EQU #80 START OF MONITOR STACK
TOPINTLOC EQU #400
MCSEG EQU #FF80 START OF CODE SEG- TOP OF MEM-ROM (#FF800)
*MCSEG EQU #400 TEMP FOR TESTS
*
EJT
RTAB
DB "SPSSCSIPFSESDSDISIBPDXCXBXAXCOSTS1S2#1#2ID"
LTAB EQU $-RTAB
*
*
*
SPSAV EQU 0
SSSAV EQU 2
CSSAV EQU 4
IPSAV EQU 6
FSSAV EQU 8
ESSAV EQU 10
DSSAV EQU 12
DISAV EQU 14
SISAV EQU 16
BPSAV EQU 18
DXSAV EQU 20
CXSAV EQU 22
BXSAV EQU 24
AXSAV EQU 26
SSCNTR EQU 28 NUMBER OF CALLS BEFORE DISPLAYS
SSTEP EQU 30
S1 EQU 32
S2 EQU 34
STEPCNT EQU 36 STEPCOUNTER TO BE USED
INTPRES EQU 38 WE ARE IN MONITOR FOLLOWING AN INT
INTDIS EQU 40 IF INTERRUPTS ARE TO BE DISABLED BEFORE RETURN
CONSPD EQU 42 CURRENT VALUE FROM SPEED TABLE
TABLE EQU 44 TOP OF RECOGNISED SYMBOLS
*
*
COMMBASE EQU #B0
CONIN EQU CONDR
DELAYTIME EQU 2
*
*
*
*
*
CTAB DB "!"
DB "R"
DB "M"
DB "I"
DB "G"
DB "D"
DB "L"
DB "E"
DB "X"
DB "C"
DB "F"
DB "V"
NCMDS EQU $-CTAB NO OF RECOGNISED COMMANDS
*
*
*
CADR
DW SCMD TTY SPEED COMMAND-CALLED BY B
DW RCMD RCMD-RETURN TO USER PROG
DW MCMD MCMD
DW ERROR ICMD
DW GCMD GO COMMAND
DW DCMD DCMD
DW LOAD LCMD
DW RVIEW REG DISPLAY COMMAND
DW XCMD REGISTER DISPLAY AND CHANGE
DW CCMD MEMORY DISPLAY AND CHANGE
DW FCMD FAST CONNECTION TO 1270
DW VCMD SET UP 1270 CONNECTION THEN AS FCMD
*
*
*
*
SGNON
DB 14,CR,LF,"RL8086 MON",CR,LF
IPMES DB 6,"IP/CS="
AXMES DB 4,",AX="
BPMES DB 4,",BP="
SPMES DB 4,",SP="
FSMES DB 4,",FS="
SIMES DB 4,",SI="
BXMES DB 4,",BX="
DIMES DB 4,",DI="
LSGNON EQU $-SGNON LENGTH OF SIGN ON MESSAGE
* MACRO DEFINITIONS
*
*
****************************************************************
*
*
*
*
PUT MAC
:@
MOV AL,!:1
CALL ECHO OUTPUT THE CH
EMP
*
*
SRET MAC
:@
STC SET CARRY FOR SUCCESS
RET
EMP
*
*
*
FRET MAC
:@
CLC CLEAR FOR FAILURE
RET
EMP
*
*
*
WRITE MAC
:@
MOV SI,!:1
CALL WRITES
EMP
*
*
EJT
ORG BEGIN+#100
*
*
*
**************************************************************
*
*
START
JMPS START1-BEGIN,MCSEG SET UP CORRECT IP&CS
START1
MOV DX,!MSEG NOTE THAT DX CANNOT BE SEEN AFTER RESET
MOV DS,DX RELOAD MONITOR DATA SEGMENT
MOV AXSAV,AX SAVE ALL THE REGISTERS
MOV BXSAV,BX FOLLOWING
MOV CXSAV,CX A RESTART
MOV BPSAV,BP
MOV SISAV,SI INCLUDE STACK
MOV DISAV,DI
MOV SPSAV,SP
MOV FSSAV,!0 CLEAR THE USERS FLAGS
MOV DSSAV,DX SET UP SEGMENTS
MOV ESSAV,DX TO POINT TO MONITOR SEGEMENTS
MOV CX,!7 CLEAR THE REST OF THE FLAGS
MOV SI,!SSCNTR IN THE MONITOR TABLE
START3 MOV (SI),!0 CLEAR
ADD SI,!2 TO TOP OF TABLE
LOOP START3
*
MOV AX,!0 SET UP THE INTERRUPT
MOV DS,AX LOCATIONS IN THE BOTTOM
MOV SI,AX OF MEMORY
MOV BX,!INTENT THIS IS THE DEFAULT TRPA LOCATION
MOV AX,!MCSEG AND THIS IS MONITOR CODE SEGMENT
START2
MOV (SI),BX
MOV 2(SI),AX
ADD SI,!4
CMP SI,!TOPINTLOC
JL START2
*
OUT COMMBASE+#F RESET 4 CHANNEL EXPANSION BOARD
*
MOV AX,!MSEG START OTHER SEGS AT FF800
MOV SS,AX
MOV AX,!MCSEG
MOV DS,AX
MOV ES,AX
MOV SP,!MSTAK START MONITOR STACK HERE
CLI TEMP TURN OFF INTS
*
*
*
MOV BX,B4800
MOV CONSPD,BX[SS]
CALL TTYON SET UP CONSOLE
*
*
MSGL
WRITE SGNON
*
*
*
*
*
****************************************************************
*
*
*****************************************************************
*
*
* COMMAND RECOGNISING ROUTINE
*
*
****************************************************************
*FUNCTION: GETCM
*INPUTS : NONE
*OUTPUTS : NONE
*CALLS : GETCH,ECHO,EEROR
*DESTROYS : A,C,DI,SI,FFS
*DESCRIPTION:GETM RECIEVES AN INPUT CH FROM THE USER AND TRIES TO LOCATE
* THIS CH IN THE COMMAND CHARACTER TABLE . IF SUCCESSFUL,
* THE ROUTINE CORRESPONDING TO THIS CH IS SELECTED FROM
* A TABLE OF COMMAND ROUTINE ADDRESSES, AND CONTROL IS
* TRANSFERRED . IF NO MATCH THEN ERROR.
*
*
*
GETCM MOV SP,!MSTAK ALWAYS WANT TO RESET SP TO MONITOR
MOV AX,!MSEG
MOV SS,AX
MOV AX,!MCSEG NB SCAW USES ES
MOV DS,AX
MOV ES,AX
PUT "." PROMPT CH TO TTY
CALL GETCH COMMAND CH TO A
CALL ECHO BACK TO USER
CMP AL,!ESC
JNE GCM20
MOV AX,INTPRES[SS] IF INTERRUPT PRESENT
CMP AX,!0 AND ESC HIT
JE GCM20 THEN RETURN TO USER
JMP INTRES ELSE IGNORE
GCM20
MOV CX,!NCMDS DI GETS LOOP & INDEX COUNT
MOV DI,!CTAB DI POINTS INTO COMM TABLE
CLD MAKE SURE INCREMENTS
REP LOOP THRO CX COMMANDS
SCAB DOES IT MATCH
JE GCM10 OK FOUND IT
JMP ERROR COMM IS ILLEGAL
GCM10
MOV SI,!NCMDS-1
SUB SI,CX
SHL SI EACH BIT IS 2 BYTES LONG
CALLI CADR(SI) NEXT INSTR COMES FROM COMM ROUTINE
JMP GETCM BACK FOR NEXT COMMAND
*
*
*
*
***********************************************************************
*
* ROUTINE : DUMP
* INPUTS : NONE
* OUTPUTS : NONE
* DESTROYS : A,BP,SI,CX
* DESCRIPTION : READS TWO HEX NUMBERS AND DUMPS THE MEMORY OFFSET
* BY S1 (USUALLY DEFAULTED TO USERS DI ).HALTS IF
* ON 16TH LINE BOUNDARY TO DISPLAY THE PAGE-CR CAUSES
* RETURN TO MONITOR ANY OTHER CH GIVES NEXT PAGE.
*
*
*
DCMD
PUSH ES USED AS DUMP SEGMENT REG
PUSH DS
MOV AX,!MSEG
MOV DS,AX
MOV CL,!2 GET TWO NUMBERS
CALL GETNM
JCC DCM15 FAILED TO GET CORRECT ANS
POP BP END ADD
POP SI START ADD
SAR SI MAKE SI EVEN
SHL SI AND LOWER
MOV ES,S1 LOAD SEG REG
DCM05
CALL CROUT NEWLINE
MOV AX,SI
CALL PUT4H TYPE THE ADDRESS
DCM10
PUT " " TYPE SPACER
MOV AX,(SI)[ES] PICK UP CONTENTS
XCHG AL,AH MAKE BYTES APPEAR CORRECT WAY ROUND
CALL PUT4H TYPE THEM
PUT " " TYPE SPACER
ADD SI,!2 NEXT WORD
CMP SI,BP FINISHED
JA DCM15 SO END
TEST SI,!#FF PAGE TYPED
JNZ DCM12 NO
PUT "?" QUERY AND CAUSES WAIT FOR CH
CALL GETCH HOLDS PAGE UP
CMP AL,!CR IF CR THEN BACK TO MON
JE DCM15 QUIT
DCM12
TEST SI,!#F AT END OF LINE
JZ DCM05 ANOTHER LINE
JMP DCM10 ANOTHER CONTENTS
DCM15
CALL CROUT ENDING
POP DS REPLACE SAVED SEGMENTS
POP ES
RET
*
*
*
*
*
*
***********************************************************************
*
* FUNCTION : GO
* DESCRIPTION : GETS SEG,INSTR POINTER AND GOES THERE
*
*
*
GCMD
MOV CL,!2 GET 2 NUMBERS
CALL GHXNM FROM INPUT
JCC GCMDERR TWAS IN ERROR
POP BX
POP AX
MOV CSSAV,BX[SS] SET UP USERS BLOCK
MOV IPSAV,AX[SS] FOR A RETURN
RCMD
JMP INTRES AND RETURN
GCMDERR
JMP ERROR AS ALWAYS
*
*
*
***********************************************************************
*
* ROUTINE : MOVE
* INPUTS NOTHING
*OUTPUTS NOTHING
* DESTROYS A,C,SI,DI,BP,FFS
* DESCRIPTION MOVES THE MEMORY POINTED TO BY S1/IST NO UPTO (INC)
* S1/2ND NO INTO S2/3RD NO. NB S1&S2 USUALLY DEFAULTED TO
* THE USERS DS.
*
*
*
MCMD
MOV CL,!3 GET THREE NUMBERS
CALL GETNM START-UPTO-DEST
JCC MERROR ERROR IN READ ROUTINE
POP DI DEST ADD
POP BP LAST SOURCE ADD
POP SI START SOURCE ADD
PUSH ES USED AS SOURCE SEG
PUSH DS USED AS DEST ADD
MOV AX,!MSEG
MOV DS,AX
MOV ES,S1 SET UP SEGS
MOV AX,S2
MOV DS,AX
MCM10
MOV AL,(SI)[ES] GET SOURCE BYTE
MOV (DI),AL PUT IT AWAY
INC SI NEXT LOC
INC DI
CMP SI,BP ALL DONE
JBE MCM10 NO SO AGAIN
POP DS
POP ES
CALL CROUT
RET
MERROR
JMP ERROR
*
*
*
*
******************************************************************
*
* ROUTINE : RCMD
* DESCRIP : RETURNS TO USER PROG
*
*
*
*
*
*
*****************************************************************
*
*
* SCMD : SETS UP TTY AT DESIRED SPEED
*
*
SCMD
XOR BP,BP COUNTER FOR NUMBER OF RATES TRIED
S05
CMP BP,!NRATES ALL DONE
JGE SCMD HAVEN'T FOUND SO TRY COMMAND AGAIN
MOV SI,!RATET POINTER TO START OF TABLE
ADD SI,BP
MOV BX,(SI) GET THE RATE
XOR DI,DI NUMBER OF SUCCESSFUL TRIES
ADD BP,!2 POINT TO THE NEXT RATE
CALL TTYSP SET UP THE CONSOLE
S10
CALL GETCH TRY TO READ A CH
CALL GETCH DO ANOTHER IN CASE THE FIRST WAS RUBBISH
CMP AL,!#5 IS IT CONTROL E?
JNE S05 NO SO ONTO NEXT
INC DI ANOTHER SUCCESS
CMP DI,!4
JL S10 NOT SECOND SO CHECK
MOV BP,(SI)
MOV CONSPD,BP[SS]
RET SUCCESS
*
*
*
*
EJT
*
*
*
**********************************************************
*
*
*
* UTILITY ROUTINES
*
**************************************************************************
*
* FUNCTION:BREAK
* INPUTS:NONE
* OUTPUTS: CARRY - 1 IF ESCAPE CHAR
* - 0 IF ANY OTHER CHAR OR NO CHAR PENDING
* CALLS:NOTHING
* DESTROYS: AL,F/F'S
* DESCRIPTION: BREAK IS USED TO SENSE AN ESCAPE CHAR FROM
* THE PENDING USER. IF NO CHAR IS PENDING OR IF
* THE PENDING CHAR IS NOT ESCAPE THEN A FAILURE
* RETURN (CARRY=0) IS TAKEN. IN THIS CASE THE
* PENDING CHAR(IF ANY) IS LOST. IF THE PENDING CHAR
* IS AN ESCAPE CHAR THEN BREAK TAKES A SUCSSESFUL RETURN
* CARRY=1
*
BREAK
IN CONST GET CONSOLE STATUS
TEST AL,!RBR SEE IF CHAR IS PENDING
JZ BREF NO TAKE FAILURE RETURN
IN CONDR YES PICK UP CHAR
AND AL,!PRTY0 STRIP OFF PARITY BIT
CMP AL,!BRCHR IS IT ESCAPE CHAR
JNE BREF FAILURE RET
SRET SUCCESS RET
BREF FRET FAILURE RET
*
*
**************************************************************************
*
*
* FUNCTION: WRITES
* INPUTS: SI - ADRESS OF STRING (IN BCPL FORMAT) I.E LENGTH,STRING
* OUTPUTS: STRING TO CONSOLE
* DESTROYS - SI IN MACRO FORM
* DESCRIPTION : WRITE OUT A CHRACTER STRING
*
WRITES
PUSH AX
PUSH CX
XOR CX,CX CLEAR CX
MOV CL,(SI) MOV COUNT INTO LOWER BYTE OF CX
INC SI POINT AT FIRST CHARACTER
WLOOP
MOV AL,(SI) NEXT CHARACTER => AL
CALL CO OUTPUT IT
INC SI BUMP CHARACTER POINTER
LOOP WLOOP FOR CX CHARACTERS
POP CX
POP AX
RET
*
*
************************************************************************
*
* FUNCTION:CI
* INPUTS : NONE
* OUTPUTS A CHAR FROM THE CONSOLE
* CALLS: NOTHING
* DESTROYS: AL, F/F'S
* DESCRIPTION:
* CI WAITS UNTIL A CHAR IS READY FROM THE CONSOLE AND RETURNS
* WITH THE CH IN AL
* THIS ROUTINE IS CALLED BY THE USER VIA A JMP TABLE IN RAM
*
CI
IN CONST GET STATUS OF THE CONSOLE
AND AL,!RBR CHECK FOR RECEIVE BUFFER READY
JZ CI NOT YET -- WAIT
IN CONDR READY SO GET CHAR
RET NB HAVENT GOT RID OF PARITY BIT
*
*
************************************************************************
*
* FUNCTION: CNVBN
* INPUTS: AL --ASCII CHAR '0'-'9' OR 'A'-'F'
* OUTPUTS AL -- 0 - F HEX
* CALLS : NOTHING
*DESTROYS : AL,FFS
* DESCRIPTION: CONVERTS CHAR TO HEX DOES NOT CHECK INPUT
*
CNVBN
SUB AL,!"0" SUB CODE FOR ZERO
CMP AL,!9 TEST FOR 0-9
JLE CNV05 OK SO RET
SUB AL,!7 THIS IS RIGHT FOR ASCII ONLY
CNV05 RET
*
*
************************************************************************
*
* FUNCTION: CO
* INPUTS: AL -- CHAR TO OUTPUT TO CONSOLE
* OUTPUTS : AL TO CONS
* CALLS : NOTHING
* DESTROYS F/F'S
*DESCRIPTION:
* CO WAITS TILL CONSOLE IS READY THEN WRITES CHAR
*
CO
PUSH AX
CO05 IN CONST GET STATUS OF CONSOLE
TEST AL,!TRDY IS IT READY TO GO
JZ CO05 NO THEN WAIT
POP AX REPLACE THE CH
OUT CONDR SEND TO CONSOLE
RET
*
************************************************************************
*
* FUNCTION : CROUT
* INPUTS : NONE
* OUTPUTS: NONE
* CALLS:ECHO
* DESTROYS :F/F'S
* DESCRIPTION:
* CROUT SENDS A CR ( AND HENCE A LF) TO CONSOLE
*
CROUT
PUT CR
RET
*
************************************************************************
*
* FUNCTION : ECHO
* INPUTS: AL - CHAR TO ECHO TO TERMINAL
* OUTPUTS: NONE
* DESTROYS :F/F'S
* DESCRIPTION:
* ECHO SENDS A SINGLE CHAR AS INPUT AND VIA THE MONTOR SENDS THAT CHAR
* TO THE USERS TERMINAL. A CR IS ECHOED AS CR + LF AND ESCAPE AS $
*
*
ECHO
PUSH AX SAVE ARG
CMP AL,!ESC
JNZ ECH05 NO BRANCH
MOV AL,!"$"
ECH05
CALL CO DO OUTPUT THRU MONITOR
CMP AL,!CR
JNE ECH10 NO NEED FOR SPECIAL ACTION
MOV AL,!LF YES ECHO LF ASWELL
CALL CO
ECH10
POP AX RESTORE ARG
RET
*
************************************************************************
*
* FUNCTION :ERROR
* INPUTS : NONE
* OUTPUTS: NONE
* CALLS: ECHO, CROUT, GETCM
* DESTROYS: F/F'S
* DESCRIPTION:
* ERROR PRINTS THE ERROR CHAR (CURRENTLY AN ASTERISK)
* FOLLOWED BY CR + LF
* AND THE RETURNS CONTROL TO THE COMMAND REGOGNISER
*
ERROR
PUT "*" SEND * TO CONSOLE
CALL CROUT NEWLINE
JMP GETCM TRY FOR ANOTHER COMMAND
*
************************************************************************
*
* FUNCTION : GETCH
* INPUTS: NONE
* OUTPUTS: AL -- CHAR FROM INPUT STREAM
* CALLS : CI
*
* DESTROYS AL,F/F
* DESCRIPTION:
* GETCH GETS NEXT CHAR FROM THE INPUT
*
GETCH
CALL CI GET CHAR
AND AL,!PRTY0 TURN OFF PARITY BIT
RET
*
*
*
************************************************************************
*
* FUNCTION GETHX
* INPUTS: NONE
* OUTPUTS : BP -- 16 BIT INTEGER
* AL - CHAR TERMINATING THE INTEGER
* AH - FF IF FIRST CH DELIMETER
* CARRY - 1 IF SUCCESS
* 0 IF FAILURE
* CALLS: ECHO,GETCH,VALDL,VALDG,CNVBN,ERROR
* DESTROYS: AX,BP,F/F'S
* DESCRIPTION:
* GETHX ACCEPTS A STREAM OF HEX DIGITS AS A 16 BIT INTEGER.IF MORE THAN
* 4 HEX DIGITS ARE ENTERED ONLY THE LAST 4 ARE USED. THE NUMBER ENDS
* WHEN A VALID DELEIMETER IS FOUND.THE DELIMETER IS ALSO RETURNED AS AN
* OUTPUT OF THE FUNCTION. ILLEGAL CHARS ( NOT HEX OR DELIMETERS) CAUSE
* AN FLAG. IF THE FIRST VALID CHAR IN INPUT IS NOT DELIMETER
* AH SET TO 0
*
GETHX
PUSH CX SAVE CX
MOV CL,!#FF FLAG FOR FIRST DIGIT
XOR BP,BP INIT ANS TO 0
GHX05
CALL GETCH GET A CHAR
GHX06
CALL ECHO ECHO IT
CALL VALDL SEE IF DELIMETER
JCS GHX15 YES SO END
CALL VALDG IF NOT DELIM WAS IT A DIGIT
JCC GHX20 NO SO INVALID DIGIT
CALL CNVBN CONVERT TO BINARY
MOV CX,!4 ROTATE ANS BY 1 DIGIT
GHX10
SHL BP,CX
MOV AH,!0 ADD IN THIS DIGIT
ADD BP,AX
B GHX05
GHX15
MOV AH,CL SET UP FIRST DIGIT FLAG
STC FLAG TO SAY NO ERROR
GHX20
POP CX RESTORE
RET
*
*
*
************************************************************************
*
* FUNCTION: GETNM
* INPUTS: CL- COUNT OF NUMBER TO BE FOUND IN INPUT STREAM
* OUTPUTS: TOP OF STACK: NUMBERS TO BE FOUND IN REVERSE ORDER
* CALLS: GETHX,HILO,ERROR
* DESTROYS : AX,BP,SI,DI,CX,FFS
* DESCRIPTION:
* GETNM FINDS A CNT OF NUMBERS BETWEEN 1 AND 3 INCLUSIVE IN THE
* INPUT STREAM AND RETURNS THEIR VALUES ON THE STACK
* IF 2 OR MORE ARE REQUIRED THEN THE FIRST MUST BE LESS THAN OR EQUAL
* TO 2ND OR 1ST IS SET EQ TO 2ND. THE LAST NUMBER MUST BE TERMINATED
* BY CR OR AN ERROR IS GIVEN-C IS SET
* REGS ARE STACKED IN REVERSE ORDER TO THAT READ IN
*
GETNM
MOV SI,SP SAVE CORRECT SP IF ROUTINE FAILS
AND CL,!3 FORCE TO MAX OF 3
JZ GNM30 IF 0 DONT BOTHER
MOV CH,CL SAVE NUMBER OF NUMBERS
GNM05
CALL GETHX GET A NUMBER FROM THE INPUT STREAM
JCC GNM30 ERROR IF NOT THERE TOO FEW NUMBERS
PUSH BP ELSE SAVE NUMBER ON STACK
DEC CL DECR ARG CNT
JZ GNM10 NO MORE NUMBERS WANTED
CMP AL,!CR WAS IT CR
JZ GNM30 ERROR IF SO TOO FEW
JMP GNM05 ELSE PROCESS NEXT NUMBER
GNM10
CMP AL,!CR WHEN CNT 0 CHECK LAST TERM
JNE GNM30 ERROR IF NOT CR
MOV BP,!#FFFF BP GETS LARGEST NUMBER
MOV AL,!3 MAKE SURE HAVE STACKED THREE NUMBERS
SUB AL,CH
GNM15
JZ GNM20 IF YES 3 NUMBERS WERE INPUT
PUSH BP IF NOT FILL OUT REST WITH FFFF
DEC AL
B GNM15 LOOP TILL DONE
GNM20
POP SI
POP BP GET THE 3 ARGS OUT
POP AX
CMP AX,BP SEE IF 1ST >= 2ND
JBE GNM25 NO -- BRANCH JMP IF OK
MOV AX,BP FORCE THEM =
GNM25
POP DI REMOVE RETURN ADDRESS
PUSH AX
PUSH BP
PUSH SI 3RD
PUSH DI PUT RET ADDRESS ON STACK
NEG CH
ADD CH,!3 FIND NO OF EXTRA REGS STACKED
GNM26
JZ GNM28 WHEN 0 FINISH
POP DI
POP BP TAKE EXTRA FROM UNDER RET ADD
PUSH DI
DEC CH
B GNM26 LOOP
GNM28
SRET SUCCESS
GNM30
MOV SP,SI REPLACE CORRECT SP
FRET FAILURE RET
*
*
*
******************************************************************
*
* GHXNM SAME AS GETNM BUT NO SWAPPING OF NUMBERS
*
*
*
GHXNM
MOV SI,SP SAVE CORRECT SP IF ROUTINE FAILS
AND CL,!3 FORCE TO MAX OF 3
JZ GXM30 IF 0 DONT BOTHER
MOV CH,CL SAVE NUMBER OF NUMBERS
GXM05
CALL GETHX GET A NUMBER FROM THE INPUT STREAM
JCC GXM30 ERROR IF NOT THERE TOO FEW NUMBERS
PUSH BP ELSE SAVE NUMBER ON STACK
DEC CL DECR ARG CNT
JZ GXM10 NO MORE NUMBERS WANTED
CMP AL,!CR WAS IT CR
JZ GXM30 ERROR IF SO TOO FEW
JMP GXM05 ELSE PROCESS NEXT NUMBER
GXM10
CMP AL,!CR WHEN CNT 0 CHECK LAST TERM
JNE GXM30 ERROR IF NOT CR
MOV BP,!#FFFF BP GETS LARGEST NUMBER
MOV AL,!3 MAKE SURE HAVE STACKED THREE NUMBERS
SUB AL,CH
GXM15
JZ GXM20 IF YES 3 NUMBERS WERE INPUT
PUSH BP IF NOT FILL OUT REST WITH FFFF
DEC AL
B GXM15 LOOP TILL DONE
GXM20
POP SI
POP BP GET THE 3 ARGS OUT
POP AX
GXM25
POP DI REMOVE RETURN ADDRESS
PUSH AX
PUSH BP
PUSH SI 3RD
PUSH DI PUT RET ADDRESS ON STACK
NEG CH
ADD CH,!3 FIND NO OF EXTRA REGS STACKED
GXM26
JZ GXM28 WHEN 0 FINISH
POP DI
POP BP TAKE EXTRA FROM UNDER RET ADD
PUSH DI
DEC CH
B GXM26 LOOP
GXM28
SRET SUCCESS
GXM30
MOV SP,SI REPLACE CORRECT SP
FRET FAILURE RET
*
*
*
*
************************************************************************
*
* FUNCTION NMOUT
* INPUTS: AL - 8 BIT INTEGER
* OUTPUTS: NONE
* CALLS : ECHO,PRVAL
* DESTROYS: F/F'S
* DESCRIPTION:
* NMOUT CONVERTS THE 8 BIT INTEGER INTO 2 ASCII CHARS AND PRINTS THEM
*
NMOUT
PUSH AX SAVE AX DESTROYED HERE
SHR AL
SHR AL
SHR AL
SHR AL
CALL PRVAL CONVERT TO ASCII
CALL ECHO TYPE
POP AX RESTORE
PUSH AX AND SAVE IT AGAIN
AND AL,!#F BOTTOM 4 BITS ONLY
CALL PRVAL
CALL ECHO
POP AX RESTORE AX
RET
*
***********************************************************************
*
* FUNCTION : PRVAL
* INPUTS : AL - INTEGER 0-F
*
* OUTPUTS: AL -ASCII CHAR
* CALLS: NOTHING
*DESCRIPTION:
* CONVERTS TO ASCII WITHOUT CHECK ON VALUE
*
PRVAL
ADD AL,!"0" CONVERT TO ASCII
CMP AL,!"9"
JLE PRV05 IF <10 OK
ADD AL,!7 WORKS ONLY FOR ASCII
PRV05 RET
*
************************************************************************
*
* FUNCTION: PUT4H
* INPUT : AX 16 BIT INTEGER
* OUTPUT : TYPES 4 HEX DIGITS
* DESTROYS : NOTHING ?
* DESCRIPTION : TYPES 4 HEX DIGITS
*
*
PUT4H
PUSH AX SAVE THE ARG
XCHG AL,AH TYPE TOP BITS FIRST
CALL NMOUT
POP AX
PUSH AX MAKE SURE ITS UNCHANGED
CALL NMOUT TYPE BOTTTOM BITS
POP AX
RET
****************************************************************
*
*
* FUNCTION : TTYON
* DESCRIP : SETS TTY SPEED TO BX
*
*
*
TTYSP
IN CONST
TEST AX,!1 OK TO PROCEED
JZ TTYSP
PUSH BX
MOV BX,!1
CALL DELAY
POP BX
MOV AL,!#40 SET CMD WORD BACK TO INSTRUCTION MODE
OUT CNCTL
TTYON
MOV AL,!CLKCTL
OUT TIMCTL
PUSH AX
POP AX
MOV AX,BX PUT IN SPEED READY FOR OUT
OUT TIM2
MOV AL,AH
OUT TIM2
MOV AL,!MODE
OUT CNCTL
PUSH AX
POP AX WASTE TIME FOR USART TO SET UP
MOV AL,!CMD
OUT CNCTL START IT OFF
PUSH AX
POP AX
RET
*
*
*
*****************************************************************
*
*
* FUNCTION : VALDG
* INPUTS: AL-- ASCII CHAR
* OUTPUTS: CARRY = 1 IF REPRESENTS A HEX DIGIT
* = 0 IF NOT
*
*CALLS : NOTHING
* DESTROYS: F/FS
* DESCRIPTION :
* CHECK FOR A VALID HEX DIGIT '0'-'9' AND 'A' TO 'F'
*
VALDG
CMP AL,!"0" AGAINST "0"
JB VDGF IF LOWER CANT BE VALID
CMP AL,!"9" WAS IT 0-9
JBE VDGS BETWEEN 0 AND 9
CMP AL,!"A" WAS IT A TO F
JB VDGF NO
CMP AL,!"F"
JA VDGF NO
VDGS SRET WAS A TO F INCLUSIVE
VDGF FRET FAILURE RET
*
************************************************************************
*
* FUNCTION : VALDL
* INPUTS : AL-- CHARACTER
* OUTPUTS: CARRY = 1 VALID DELIMETER
* =0 INVALID DELIMETER
* CALLS :NOTHING
* DESTROYS F/FS
* DESCRIPTION:
* VALID IF ( SPACE ,COMMA,CR) FAILURE IF NOT
*
VALDL
CMP AL,!"," COMMA
JZ VDLS SUCCESS
CMP AL,!"." ALSO PERIOD
JZ VDLS
CMP AL,!"/" ALSO A STOKE
JZ VDLS IS GOOD
CMP AL,!CR CARRIAGE RETURN
JZ VDLS SUCCESS
CMP AL,!" " SPACE
JZ VDLS
FRET ALL ELSE INVALID
VDLS SRET SUCCESS RET
*
************************************************************************
*
*
* FUNCTION: CCMD
* INPUTS: NONE
* OUTPUTS: NONE
* DESTROYS: PROBABLY EVERYTHING
* DESCRIPTION: ALOWWS THE USER TO LOOK AND MODIFY MEMORY
*
CCMD
CALL GETHX WHAT IS THE LOCATION
JCC CERR
MOV SI,BP FOR THE BYTE POINTER
CMP AL,!"/" WAS DELIMETER SLASH
JNE CC1 IF SO WE OVERRIDE SEGMENT
CALL GETHX WITH A VALUE AFTER THE SLASH
JCC CERR THIS REPLACES S1
MOV S1,BP[SS] CHANGE
CC1 MOV ES,S1[SS] ES IS USED TO ACCES MEMORY
*
CC0 CALL CROUT FRESH LINE
MOV AX,SI NOW OUTPUT THE LOCATION
CALL PUT4H
PUT "-" SEPERATE
PUT " "
MOV AL,(SI)[ES] THIS IS
CALL NMOUT THE BYTE
PUT " "
PUT "-" DO WE WANT TO CHANGE
CALL GETHX IF SO
JCC CC2 MUST BE SUCCESS
CMP AH,!#FF AND 1ST CHAR NOT DELIMETER
JE CC2 BEFORE WE DO
MOV BX,BP
MOV (SI),BL[ES] CHANGE IT
CC2
CMP AL,!CR IF RETURN
JNE CC3 TIME TO GO HOME
RET
CC3
CMP AL,!"↑" IF "↑" THEN
JNE CC4 MOVE BACK
DEC SI
JMP CC0
CC4
CMP AL,!"." IF "." THEN STAY
JNE CC5 AS YOU WERE
JMP CC0
CC5
INC SI IN ALL OTHER CASES
JMP CC0 GO TO NEXT
*
CERR
JMP ERROR
*
******************************************************
*
*
* FUNCTION : XCMD
* INPUT & OUTPUT : NONE
* DESTROYS : ALL
* DESCRIPTION: DISPLAYS USERS REGISTERS AND ALLOWS YOU TO CHANGE
*
XCMD
PUT "-" THIS ALLOWS
PUT " " THE USER
CALL GETCH TO SET
CALL ECHO EVERYTHING IN THE USER BLOCK
XCHG AH,AL
CALL GETCH
CALL ECHO GET 2 CHAR IDENTIFIER
XCHG AH,AL
*
MOV CX,!LTAB/2 NOW SCAN THE TABLE
MOV DI,!RTAB FOR A MATCH
CLD RIGHT DIRECTION
REP
SCAW
JNZ XERR DID NOT FIND MATCH
MOV SI,!LTAB/2 BYTE ADDRESSING
SUB SI,CX
DEC SI
ADD SI,SI COMPLICATED
PUT " "
MOV AX,SPSAV(SI)[SS] THIS SHOULD GET IT
CALL PUT4H DISPLAY IT
PUT " "
PUT "-"
CALL GETHX DO WE NEED A CHANGE
JCC XC1
CMP AH,!#FF
JE XC1
MOV SPSAV(SI),BP[SS] CHANGE IT
XC1
CMP AL,!CR IF DELIMETER RETURN
JNE XC2 WE HAVE FINISHED
RET
XC2
CALL CROUT NEWLINE
PUT " " NEW LOOK
PUT " "
JMP XCMD
*
XERR JMP ERROR
*
*
*********************************************************************
*
*
* FUNCTION: RVIEW
* INPUT & OUTPUT :NONE
* DESTROYS : ALL
* DESCRIPTION : DISPLAYS IP/CX,AX,SP,BP,SI,FLAGS
*
RVIEW
CALL CROUT FRESH LINE
WRITE IPMES
MOV AX,IPSAV[SS] NOTE THAT
CALL PUT4H AS USUAL WE USE
PUT "/" WE USE MONITOR
MOV AX,CSSAV[SS] TO ACCESS THE
CALL PUT4H USERS
WRITE SPMES REGISTER BLOCK
MOV AX,SPSAV[SS] VIA STACK SEGMENT
CALL PUT4H
WRITE AXMES
MOV AX,AXSAV[SS]
CALL PUT4H
WRITE BXMES
MOV AX,BXSAV[SS]
CALL PUT4H
WRITE BPMES
MOV AX,BPSAV[SS]
CALL PUT4H
WRITE SIMES
MOV AX,SISAV[SS]
CALL PUT4H
WRITE DIMES
MOV AX,DISAV[SS]
CALL PUT4H
WRITE FSMES
MOV AX,FSSAV[SS]
CALL PUT4H
CALL CROUT
RET
*
*
*
*************************************************************************
*
*
*
* INTENT :::: FOR ALL UNDEFINED AND INTERRUPT 3
* IF SSTEP IS SET THEN IT WILL CALL RVIEW EVERY SSCNTR TIMES
* SSCNTR-1 IN FACT
* IT COMPLETELY SAVES THE USERS ENVIROMENT INCLUDE HIS CORRECT STACK
* POSITION
* IT IS A LITTLE TRICKY AS IT MUST USE THE USERS STACK INITIALLY
* IT THEN COMPLETELY SWAPS TO THE MONITORS ENVIRONMENT
*
*
INTENT
PUSH DS WE MUST USE
PUSH AX THE USERS STACK INITIALLY
MOV AX,!MSEG NOW THE MONITORS
MOV DS,AX DATA SEGMENT
CMP SSTEP,!1 IF THE SINGLE STEP
JNE INT2 FLAG IS UNSET OR COUNTER IS 0
CMP STEPCNT,!0 THEN WE DIPLAY AND GO
JE INT2 THIS IS OK
DEC STEPCNT MAYBE OK NEXT TIME
JMP INTEXIT BUT OFF FOR NOW
INT2
MOV AX,SSCNTR NOW RELOAD COUNT
MOV STEPCNT,AX IT MAY WELL BE ZERO
*
POP AX AX RESTORED
MOV AXSAV,AX NOW WE CAN
MOV BXSAV,BX SAVE ALL THE
MOV CXSAV,CX THE USERS
MOV DXSAV,DX REGISTERS
MOV BPSAV,BP THAT ARE STRAIGHT
MOV SISAV,SI FORWARD
MOV DISAV,DI
MOV ESSAV,ES
MOV SSSAV,SS
*
POP AX THIS WAS THE USERS
MOV DSSAV,AX DATA SEGMENT
POP AX IP USER
POP BX CS -- USER
POP CX FLAGS -- USER
MOV IPSAV,AX
MOV CSSAV,BX
MOV FSSAV,CX
MOV SPSAV,SP AFTER ALL THIS SP IS CORRECT
MOV AX,DSSAV SET DEFAULT SEGMENT
MOV S1,AX POINTER 1 & 2
MOV S2,AX
MOV INTPRES,!1 INDICATE WE HAVE AN INTERRUPT
*
*
************************************************************
*
*
* NOW WE HAVE SAVED THE USERS ENVIRONMENT ENTIRELY
* WE CAN SET UP THE MONITOR ENVIRONMENT
* WITH NO FEARS FOR A SCREW UP
*
*
MOV AX,!MSEG NOTE THAT WE CAN USE
MOV SS,AX THE MONITOR STACK SEGMENT
MOV AX,!MCSEG FOR ACCESSING USER DATA BLOCK
MOV DS,AX
MOV ES,AX
MOV SP,!MSTAK RESET THE STACK
*
CALL RVIEW FOR A QUICK LOOK
JMP GETCM FOR FURTHER WORK
*
*
*************************************************************
*
*
INTEXIT
POP AX NOWT TO DO
POP DS THIS TIME
IRET
*
*
*******************************************************************
*
*
*
* INTRES:
* THIS RESETS THE USER ENVIRONMENT
* INCLUDES SETTING OR RESETTING THE SINGLE STEP COUNTER
*
INTRES
MOV AX,!MSEG SET UP DATA SEGMENT
MOV DS,AX FOR EASY ACCESS
CMP INTDIS,!1 SHOULD WE TURN OFF INTERRUPTS
JNE IR5 NOT IF RESET
AND FSSAV,!#FDFF OFF IT GOES
IR5
AND FSSAV,!#FEFF CLEAR SINGLE STEP BIT
CMP SSTEP,!1 IF WE WISH TO
JNE IR3 HAVE SINGLE STEP
OR FSSAV,!#0100 SET BIT ON
MOV SI,IPSAV THIS COMPLICATED BIT
MOV AX,CSSAV SEES IF THE NEXT INSTRUCTION IS
MOV ES,AX IS AN INT3 IF SO
IR4 MOV AL,(SI)[ES] IF SO AND IN SINGLE STEP
CMP AL,!INT3 WE IGNORE
JNE IR2 UNTIL NOT THIS INTRUCTION
INC SI
JMP IR4
IR2
MOV IPSAV,SI CLEVER STUFF HEY
IR3
MOV SP,SPSAV FIRST USERS STACK
MOV SS,SSSAV SET UP
PUSH FSSAV NOW RETURN
PUSH CSSAV
PUSH IPSAV
MOV ES,ESSAV
MOV DI,DISAV
MOV SI,SISAV
MOV BP,BPSAV
MOV DX,DXSAV
MOV CX,CXSAV
MOV BX,BXSAV
MOV AX,AXSAV
MOV INTPRES,!0 WE HAVE FINISHED
MOV DS,DSSAV AFTER THIS IT IS USER DATA SEGMENT
IRET
*
*
***********************************************************************
*
*
*
* USE THE 9.6 KB MAST LINK
*
* SELECT 'CONTROL BLOCK'
VCMD OUT #BC
* INITIALIZE PIT (TIMER)
* PIT 1, TIMER 3 ( SO IT USES BDG3 )
*
* SC1,SC0 = 0,0 COUNTER 3
* RL1,RL0 = 1,1 LOAD L.S. BYTE THEN M.S.
* M2,M1,M0 = 0,1,1 MODE 3 FOR B.R.G.
* BCD = 0 BINARY
* SO,
MOV AL,!#T00110110
* WRITE TO CONTROL (7)
OUT #B7
* FOR B.R. OF 9600 AND DIV. BY 1 CLOCK LOAD COUNTER WITH 128
MOV AX,CONSPD[SS]
MOV CL,!4
SHL AX,CL BECAUSE DIVIDE BY 1, NOT 16
OUT #B4
MOV AL,AH
MOV AL,AH WASTE TIME
OUT #B4
* B.R.G. IS NOW GOING
* SELECT 'DATA BLOCK'
OUT #BD
* INITIALIZE UART
MOV AL,!#40
OUT #B7 INTERNAL RESET
MOV BX,!2
CALL DELAY
* FIRST SEND MODE INSTRUCTION (7)
*
* S2,S1 = 0,1 1 STOP BIT
* EP = 1 EVEN PARITY
* PEN = 1 ENABLE PARITY
* L2,L1 = 1,0 7 BITS OF DATA
* B2,B1 = 0,1 BAUD RATE FACTOR = 1
* SO,
MOV AL,!#T01111001
OUT #B7
PUSH AX
POP AX
* SEND COMMAND INSTRUCTION (7)
*
* EH = 0 NOT HUNT MODE
* IR = 0 NOT INTERNAL RESET
* RTS = 1 RTS TRUE
* ER = 1 CLEAR ERROR FLAGS
* SBRK = 0 NOT BREAK
* RXE = 1 RECEIVE ENABLE
* DTR = 1 DTR ON TO START WITH
* TXEN = 1 TRANSMIT ENABLE
* SO,
MOV AL,!#T00110111
OUT #B7
PUSH AX
POP AX
*
FCMD MOV DX,!UST3
B DLL USE THE LINK
*
*
SETUP CLI ;DISABLE INTS
OUT COMMBASE+#0C SELECT CONTROL WORD
MOV AL,!#36 HOW TO READ
OUT COMMBASE+#03 FOR USART0
MOV AL,!#40 BR=1200 LSB
OUT COMMBASE+#00
MOV AL,!0 MSB
OUT COMMBASE+#00
OUT COMMBASE+#0D SELECT DATA WORD
MOV AL,!#40
OUT UST0 INTERNAL RESET
PUSH AX
POP AX
MOV AL,!#7A SET UP USART AS COMPUTER
OUT UST0
PUSH AX
POP AX
MOV AL,!#27 START IT OFF
OUT UST0
PUSH AX
POP AX
RET
*
*
*
*
LOAD CALL SETUP START UP COMMS
MOV DX,!UST0
DLL MOV AL,!#37 CLEAR TTY ERROR FLAGS
OUT CNCTL
DLL1 IN CONST CH FROM CONSOLE
TEST AL,!#20
JZ DLL2 NO SO IT IS CH
TEST AL,!#10 IF PARITY ERROR THEN IGNORE THE CH
JNE DLLA
MOV AL,!#2F SEND BREAK ON THE LINE
OUT
MOV BX,!DELAYTIME LOAD DELAY >300MS FOR GANDALF
CALL DELAY
DLLA
MOV AL,!#37 RESET FLAGS
OUT
CALL DELAY LET THINGS SETTLE
JMP DLL RESET TTY
DLL2
TEST AL,!RBR
JZ DLL10 NO SO CHECK LINK
IN CONIN GET IT
AND AL,!PRTY0 PARITY OFF
MOV BX,AX
CMP AL,!#01 IS IT CONT A
JZ FILL GET THE PROGRAM FROM LINK
CMP AL,!#02 IS IT CONT B
JZ GO YES BACK TO MONITOR
DLL5 IN SEND IT TO LINK
TEST AL,!1 IS IT READY
JZ DLL5 LOOP TILL IS
MOV AX,BX
DEC DX
OUT SEND TO LINK
INC DX
CMP DX,!UST3 IF 1270 CONN. THEN ECHO TO CONSOLE
JE DLL11
DLL10 IN ANYTHING FROM THE LINE
TEST AL,!2
JZ DLL1 NO SO CHECK CONSOLE
DEC DX
IN GET CH FROM LINK
INC DX
DLL11 AND AL,!PRTY0
CALL CO
JMP DLL1 GO AND LOOK AT CONSOLE
GO JMP GETCM START AGAIN
FILL
FILL1 CALL GETLIN GET CH FROM LINE
CMP AL,!"O" IS IT AN O
JNZ FILL1 LOOP UNTIL IT IS
FILL5 CALL GETLIN GET THE NEXT
CMP AL,!"R" IS IT THE R FROM "STORE"
JZ DLL1 IF SO BACK TO TRANSPARENT MODE
CMP AL,!"G" IS IT THE G FROM "PROG"
JZ FILL8 START OF PROGRAM
CMP AL,!"C" C INTROS OFFSET
JNZ FILL5 NOT TRUE CH SO BACK FOR ANOTHER
CALL RADD GET OFFSET
MOV CX,!4
SHR AX,CX FOR SEGMENT ACCESS
MOV ES,AX FROM EXTRA SEGEMNT
JMP FILL1 GET NEXT LINE
FILL8 CALL RADD GET TRUE ADD
MOV SI,AX POINTER FOR ACCESS VIA SEGMENT
FILL10 CALL RDATA GET THE CONTENTS
JCC FILL1 CARRY DENOTES CR
MOV (SI),AL[ES]
INC SI
JMP FILL10 GET NEXT CONTENTS
GETLIN IN CH IN LINE
TEST AL,!2
JZ GETLIN NO SO LOOP
DEC DX
IN
INC DX
AND AL,!PRTY0 STRIP OF PARITY
CALL CO
RET RETURN WITH CH IN C AND A
*RNO READS A VALID HEX DIGIT OR SETS CARRY IF CR
RNO CALL GETLIN GET A CH
CALL VALDG IS IT VALID HEX
JCC RNO1
RET
RNO1 CMP AL,!CR
JNZ RNO
CLC
RET
*RDATA GETS 2 HEX DIGITS INTO A
RDATA
PUSH CX
CALL RNO
JCC RDATA1
CALL CNVBN
SHL AX
SHL AX
SHL AX
SHL AX
MOV CX,AX
CALL RNO
JCC GO
CALL CNVBN
ADD AX,CX
STC
RDATA1 POP CX
RET
* RADD LOAD AN ADDRESS INTO AX
RADD
PUSH CX
CALL RDATA
MOV CH,AL
CALL RDATA
MOV AH,CH
POP CX
RET
*DELAY THE VALUE IN BX TIME 40 MSEC
DELAY PUSH BX
PUSH CX
DEL1 MOV CX,!0
LOOP $
DEC BX
JNZ DEL1
POP CX
POP BX
RET
*
*
*
*
**********************************************************************
*
*
* JUMP FROM POWER UP TO MONITOR
*
*
ORG #7F0 POWER UP START
JMPS START-BEGIN,MCSEG TO START OF MONITOR
*
*
*
END