Intellec8/MOD 80 Monitor (2/2)
From
Mr. Emmanuel Roche, France@21:1/5 to
All on Tue Aug 31 23:26:45 2021
[continued from previous message]
; Convert binary number to a string of ASCII digits
; HL - binary number
; DE - divisor (descending powers of 10)
; B - leading zero suppression character
; A, C - temporaries
digit: mvi c,zero ; Initialize character
dg0: mov a,l ; Sub denom (DE) from numerator (HL)
sub e
mov l,a
mov a,h
sbb d
mov h,a
jc dg1 ; Negative result, all done
inr c ; Count number of subtracts
jmp dg0
dg1: dad d ; Adjust HL
mov a,c
cpi zero ; Check for leading zero suppression
jnz dg3
mov c,b
dg2: jmp po ; Punch character
dg3: mvi b,zero
jmp dg2
;--------------------------------
; Encode a BNPF word and punch it
encode: mvi c,upB ; Punch a 'B'
call po
mvi b,08h ; 8-bit count
mov a,m ; Get data
en0: rlc ; Rotate to set Carry
push psw ; Save intermediate result
mvi a,00h ; Compute either 'P' or 'N'
ral ; based on following algorithm:
ral ; char = 'N + 2*Carry
adi upN ; char = 'N' if Carry = 0
mov c,a ; char = 'P' if Carry = 1
call po
pop psw
dcr b
jnz en0
mvi c,upF
call po
mvi c,space
jmp po
;--------------------------------
; Evaluate expression: <expr>,<expr>,<expr>
;
; The C register contains the number of parameters required
; (1, 2, or 3). Parameters are returned on the Stack.
expr: lxi h,0000H ; Initial value of parameter
ex0: call ti ; Get a character
ex1: mov b,a ; Save delimiter character
call nibble ; Convert to hex
jc ex2 ; Not legal char, treat as delimiter
dad h ; *2
dad h ; *4
dad h ; *8
dad h ; *16
ora l
mov l,a
jmp ex0 ; Get another character
ex2: xthl ; Get return address off stack
; Put HL on
push h ; Replace return address
mov a,b
call p2c ; Test delimiter character
jnc ex3
dcr c ; CR entered
jnz Ler ; Too few params
ret
ex3: jnz Ler ; Illegal delimiter
dcr c
jnz expr
ret
exp: ; Entry point for conditional parameters
mvi c,01H
lxi h,0000H
jmp ex1
;--------------------------------
; Compare HL with DE
; If HL < DE then Carry = 0
; If HL = DE then Carry = 0
; If HL > DE then Carry = 1
hilo: inx h ; Bump HL
mov a,h ; Test for HL = 0
ora l
stc
rz
mov a,e ; DE - HL, set/reset Carry
sub l
mov a,d
sbb h
ret ; Return
;--------------------------------
; Convert nibble in A to ASCII in A
; and print on console device.
hxd: call conv
jmp co
;--------------------------------
; Externally-referenced routine
;
; I/O system status code
; Status byte returned in A
; Stack usage: 2 bytes
iochk: lda iobyt ; Get status byte
ret ; Return
;--------------------------------
; Externally-referenced routine
;
; Set I/O configuration
; Value expected in C
; Stack usage: 2 bytes
ioset: push h ; Save HL
lxi h,iobyt ; point HL at IOBYT
mov m,c
pop h ; Restore HL
ret ; Return
;--------------------------------
; Print contents of HL in hex on console device
Ladr: mov a,h ; Print MSB
call Lbyte
mov a,l ; Print LSB
jmp Lbyte
;--------------------------------
; List a byte as 2 ASCII characters
Lbyte: push psw ; Save a copy of A
rrc
rrc
rrc
rrc
ani 00001111B ; Upper 4 bits
call hxd
pop psw ; Retrieve original value
ani 00001111B ; Lower 4 bits
jmp hxd
;--------------------------------
; Punch 6 inches of leader
lead: mvi b,60 ; Set to punch 6 inches of NULLs
le0: mvi c,00H ; (NULL is already a label)
call po
dcr b
jnz le0
ret ; Return
;--------------------------------
; Externally-referenced routine
;
; List Output code
; Value expected in C, A and Flags modified
; Stack usage: 2 bytes
lo: lda iobyt ; Get status byte
ani LOW NOT Lmsk ; Get list bits
jz TTYout ; List = TTY
cpi lcrt
jz CRTout ; List = CRT
cpi Luse1 ; Test for user-defined list devices
jz L1loc ; Branch to user devices
jmp L2loc
;--------------------------------
; Externally-referenced routine
;
; Return address of end of memory to user
; Value returned in (B, A)
; Stack usage: 2 bytes
memck: push h
call MemSiz
mov b,h
mvi a,0c0h
pop h
ret
;--------------------------------
; Find end of memory, set stack
MemSiz: push b ; Save BC
lxi h,00ffH ; Find end of memory
mem0: dcr h
mov a,m ; Fetch contents of memory
cma ; Invert it
mov m,a ; Attempt to write into memory
cmp m ; Is location Read/Write?
cma ; Invert again
mov m,a ; Write data back
jnz mem0 ; Yes: continue
inx h ; Point to first non-RAM location
IF debug
mvi h,2 ; Set stack at 200H for debug
ENDIF
lxi b,exit-endx ; Compute top of new stack
dad b
pop b ; Restore BC
ret ; Return
;--------------------------------
; Decode ASCII char in A into hex digit in A
; Filter out all characters not in the sequence (0-9, A-F)
; Return Carry=1 for illegal characters.
nibble: sui zero
rc ; Filter out 0-2FH
adi zero-(upF+1)
rc ; Filter out 47H-0FFH
adi 6
jp ni0 ; Take branch for A-F
adi 7
rc ; Filter out 3AH-40H
ni0: adi 10
ora a ; Clear error flag
ret ; Return
;--------------------------------
; Punch contents of HL in hex on punch device
padr: mov a,h
call pbyte
mov a,l
jmp pbyte
;--------------------------------
; Punch A byte as 2 ASCII characters
pbyte: push psw
rrc
rrc
rrc
rrc
ani 00001111B
call conv
call po
pop psw
push psw
ani 00001111B
call conv
call po
pop psw
add d
mov d,a
ret ; Return
;--------------------------------
; Test for null input parameter
pchk: call ti ; Get a character
p2c: cpi space
rz
cpi comma
rz
cpi cr
stc
cmc
rnz
stc
ret
;--------------------------------
; Punch CR, LF
peol: mvi c,cr
call po
mvi c,lf
jmp po
;--------------------------------
; Pulse a PROM location
; HL points to data in memory
; PROM address is already set
pgrm: mov a,m ; Get data from memory
cma ; Invert it
out pdo ; Output it
mvi a,progo ; Pulse PROM programmer
out promc
mvi a,prono
out promc
push b ; Delay 20 ms. for programmer settling
mvi b,Ldly
pg0: call delay
dcr b
jnz pg0
pop b
ret
;--------------------------------
; Externally-referenced routine
;
; Punch Output code, value expected in C
; A, Flags and X modified
; Stack usage: 2 bytes
po: lda iobyt ; Get status byte
ani LOW NOT Pmsk ; Get punch bits
jz TTYout ; No: punch = TTY
cpi pptp ; Test for PTP
jnz po1 ; Test for user device(s)
po0: ; Punch = PTP
in ptps ; Get Status
ani prdy ; Check status
jz po0 ; Loop until ready
mov a,c
out ptpo
mvi a,ptpgo ; Start Punch
out ptpc
mvi a,ptpno ; Stop Punch
out ptpc
ret
po1: cpi puse1
jz P1loc
jmp P2loc
;--------------------------------
; Externally-referenced routine
;
; Reader Input code
; Value returned in A, Flags modified
; Stack usage: 8 bytes
ri: push h ; Save HL
lxi h,iobyt ; Point HL at IOBYT
mov a,m
ani LOW NOT Rmsk ; Reader = PTR?
jnz ri3 ; Branch to PTR routine
mvi a,ttygo ; Reader = TTY
out ttc
mvi a,ttyno
out ttc
mvi h,tout ; Set reader TimeOUT timer
ri0: in tts
ani ttyda
jz ri2 ; Data is ready
call delay ; Delay 1.0 ms.
dcr h
jnz ri0
ri1: xra a
stc ; Set Carry indicating EOF
pop h
ret ; Return
ri2: in tti
cma
ora a ; Clear Carry
pop h
ret ; Return
ri3: cpi rptr ; PTR routine
jnz ri6
mvi a,ptrgo ; Start PTR
out ptrc
mvi a,ptrno ; Stop PTR
out ptrc
mvi h,tout ; Set reader TimeOUT timer
ri4: in ptrs
ani ptrda
jnz ri5
call delay
dcr h
jnz ri4
jmp ri1
ri5: in ptri ; Get the data
ora a
pop h
ret ; Return
ri6: pop h
cpi Ruse1
jz R1loc
jmp R2loc
;--------------------------------
; Get character from reader, mask off parity bit
rix: call ri
jc Ler ; Reader timeout error
ani 01111111B
ret ; Return
;--------------------------------
; Restart 1 code (programmed breakpoint)
;
; This routine is entered via a Restart 1 (RST 1) instruction
; The instruction is encountered either in the user program
; (as a breakpoint) or is input via a console interrupt.
; This routine saves the state of the calling process, and
; turns control over to the Monitor.
restart:push h ; Save machine state
push d
push b
push psw
call MemSiz ; HL = new Stack Pointer
xchg
fetch 10 ; Compute original Stack Pointer
mvi b,04h ; Count for transfer of machine state
; to storage (move the Stack).
xchg
rst0: dcx h
mov m,d
dcx h
mov m,e
pop d
dcr b
jnz rst0
pop b ; Get old PC = BC, old HL = DE
dcx b ; Decrement to point at trapped code
sphl ; New Stack value
fetch Tloc
mov a,m ; Test if this is a programmed restart
sub c ; or a console restart.
inx h
jnz rst1
mov a,m
sub b
jz rst3
rst1: inx h
inx h
mov a,m
sub c
jnz rst2
inx h
mov a,m
sub b
jz rst3
rst2: inx b
rst3: fetch Lloc
mov m,e
inx h
mov m,d ; Save old HL
inx h
inx h
mov m,c ; Save old PC
inx h
mov m,b
push b
mvi c,star
call co
pop h ; Retrieve old PC for display
call Ladr ; Display PC
fetch Tloc ; Clear traps
mvi d,02h ; Set count for 2 traps
rst4: mov c,m ; Get LSB of address
mvi m,00h ; Clear memory
inx h
mov b,m ; Get MSB of address
mvi m,00h
inx h
mov a,c
ora b ; Test for valid trap
jz rst5 ; Address = 0, no trap to restore
mov a,m ; Get opcode byte
stax b ; Replace it
rst5: inx h ; Point to next trap address
dcr d
jnz rst4 ; Repeat for trap 2
jmp start
;--------------------------------
; Input from console, echoed and returned in A
ti: call ci
ani 01111111B
push b
mov c,a
call co
mov a,c
pop b
ret ; Return
;--------------------------------
; Master I/O device table
; 4 bytes/entry
;
; Byte 0 = identifying character
; Byte 1 = logical device mask
; Bytes 2,3 = subordinate physical device table
Ltbl: db 'C',Cmsk ; C - console
dw act
db 'R',Rmsk ; R - reader
dw art
db 'P',Pmsk ; P - punch
dw apt
db 'L',Lmsk ; L - list
dw alt
;--------------------------------
; I/O system physical device tables
; 2 bytes/entry
;
; Byte 0 = identifying character
; Byte 1 = device select bit pattern
act: db 'T',ctty ; Console = TTY
db 'C',ccrt ; Console = CRT
db 'B',batch ; Batch mode console = Read, List
db '1',Cuse ; User-defined console device
art: db 'T',rtty ; Reader = TTY
db 'P',rptr ; Reader = PTR
db '1',Ruse1 ; User-defined reader device 1
db '2',Ruse2 ; User-defined reader device 2
apt: db 'T',ptty ; Punch = TTY
db 'P',pptp ; Punch = PTP
db '1',Puse1 ; User-defined punch device 1
db '2',Puse2 ; User-defined punch device 2
alt: db 'T',ltty ; List = TTY
db 'C',lcrt ; List = CRT
db '1',Luse1 ; User-defined list device 1
db '2',Luse2 ; User-defined list device 2
;--------------------------------
; Exit code template, to be executed in RAM
;
; db E pop D ; Monitor work stack origin
; db D
; db C pop B
; db B
; db Flags pop PSW
; db A
; db SPL pop H
; db SPO SPHL
exit: ; Monitor stack origin
pop d ; Restore DE
pop b ; Restore BC
pop psw ; Restore A and Flags
pop h ; Restore original stack value
sphl
ei ; Enable Interrupts
lxi h,$-$ ; Restore HL
HLx EQU $-2
jmp $-$ ; Return to interrupted code
PCx EQU $-2
t1a: dw 0000h ; Trap 1 Address
db 00h ; Trap 1 value
dw 0000h ; Trap 2 Address
db 00h ; Trap 2 Value
endx:
;--------------------------------
; Displacement of register location from SP (level 0)
Aloc EQU 5
Bloc EQU 3
Cloc EQU 2
Dloc EQU 1
Eloc EQU 0
Floc EQU 4
Hloc EQU HLx-exit+9
Lloc EQU HLx-exit+8
Ploc EQU PCx-exit+9
Sloc EQU 7
Tloc EQU t1a-exit+8
;--------------------------------
; Table for accessing registers
; Table contains:
; (1) Register identifier
; (2) Stack Pointer displacement
; (3) Precision
actbl: db 'A', Aloc, 1
db 'B', Bloc, 1
db 'C', Cloc, 1
db 'D', Dloc, 1
db 'E', Eloc, 1
db 'F', Floc, 1
db 'H', Hloc, 1
db 'L', Lloc, 1
db 'M', Hloc, 2
db 'P', Ploc, 2
db 'S', Sloc, 2
db -1
;--------------------------------
; End of program
END
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)