📄 iotty.asm
字号:
; [DX] == prospective destination char. (cursor) position
TEST TEMPFLAG,SCN_CHR ; print char on screen?
JZ SCNOTC_XIT ; brif not
;Force CR if char in AX won't fit
PUSH AX ; save char
CALL B$CHKLASTCOL ; DH past last column of screen?
JBE NO_WRAP ; brif not -- no wrap required
CALL B$SCNCRLF ; output a CR/LF (updates DX)
NO_WRAP:
CALL B$SCROUT ; Send char in AX to BIOS at DX posn
INC DH ; increment cursor location
CALL B$UPDATE_CSR ; update cursor variables, and display
POP AX ; restore char
SCNOTC_XIT:
TEST TEMPFLAG,LPR_CHR ; Is printer echo wanted?
JNE SCNOTLE ; Brif want to echo
SCNOTLE_RETURN:
POP DX ; end of SCNOUT
POP AX ;NOTE: caller must push AX ...
RET ; end of B$TTY_SOUT
REDOUT:
; Here if char to go to redirected file. Map and output char to stdout.
PUSH BX ;save across next two calls
CALL REDMAP ; do redirection mapping
CALL PUTSTD ; Put char to stdout (if char exists)
POP BX
JMP SHORT REDOUT_RETURN ; Jump back to main code sequence
SCNOTLE:
;here if want to echo to line printer
CMP AX,0FF0DH ;test if code for CR
JNE SCNOTLE_NO_CR ;if not, then jump
XOR AH,AH ;make one-byte char for printer
SCNOTLE_NO_CR:
CALL [b$pLPTECHO] ;Echo to line printer if necessary
JMP SHORT SCNOTLE_RETURN
CTLDP1_1:
;here if function key display mode
CMP AH,1 ; Set PSW.C if two byte character
CMC
cCALL B$FKYMAP ; Map function key display character
JMP SHORT CTLEDT
CALL_PRTMAP2:
;here if character in AL is <= 31d
TEST b$IOFLAG,F_KDSP ; Test for function key display mode
JNZ CTLDP1_1 ; BRIF function key display mode
CALL_PRTMAP1:
;here if we don't have a normal char, i.e., it must be mapped
TEST b$IOFLAG,F_EDIT ; Test for Screen Edit mode
JNZ CTLPRN ; BRIF edit mode
CMP AH,1 ; Set PSW.C if one byte character
CMC ; Set PSW.C if two byte character
cCALL B$PRTMAP ; Map print function/output character codes
CTLEDT: JZ SCNOTC_XIT ; Ignore this character
; Print or perform the editor function
CTLPRN:
CMP AH,255 ; Is it an editor function (&HFF)?
JE NOT_CTLDSX ;if so, then jump around
JMP CTLDSX ;if not, near jump
NOT_CTLDSX:
XOR AH,AH ; Clear (no longer needed) editor function flag
CMP AL,177O ; Delete function?
JNZ CTLNDL ; BRIF not DEL
MOV AL," " ; DEL code
CTLNDL: CMP AL,255 ;++Compiler ignores 0FFh
JZ SCNOTC_XIT ; BRIF "mark line for deletion" - don't print
CMP AL," "+1 ; Test for legal function code
JNB CTLEND
TEST TEMPFLAG,SCN_CHR; screen char?
JZ CTLEND ; brif not -- don't process control char
PUSH AX
; get proper index into FUNTAB -- asumes AL in range [0..31]
SUB AL,7 ; adjust so ascii [7..13] = [0..6]
CMP AL,6 ; ascii chars [7..13]?
JBE TBL_ADJ ; brif so -- table entry = [0..6]
SUB AL,14 ; adjust so ascii [28..31] = [7..10]
CMP AL,7 ; < ascii char 28?
JL CTLIGN ; brif so -- don't process char
CMP AL,10 ; ascii chars [28..31]?
JG CTLIGN ; brif not -- don't process char
TBL_ADJ:
PUSH BX
PUSH CX
ADD AX,AX ; Two bytes per entry
XCHG BX,AX
MOV AX,OFFSET CS:CTLDPX
PUSH AX ; Put CTLPDX: as return address on stack
CLC
JMP WORD PTR CS:FUNTAB[BX] ; Go do control routine
;All control chars come here after processing
; Update b$CURSOR, display new cursor, restore registers, return
CTLDPX:
CALL B$SCNLOC ; update B$CURSOR and display user cursor
POP CX
POP BX
CTLIGN:
POP AX
CTLEND: JMP SCNOTC_XIT ; do not to print this char to screen
;--------------------------------------------------------------------------
; Control character processing routines.
; All routines will return to CTLDPX.
;-- END SUBROUTINE SCNOUT
PAGE
SUBTTL Control Character processing
;CONTROL CHARACTER DISPATCH TABLE
;--
;Interpreter supports more control characters than compiler.
; Dispatch address Action (compiler ignores some) [13]
FUNTAB:
DW OFFSET B$BLEEP ; ^G - Beep
DW 0 ; unused position
DW OFFSET LTAB ; ^I - Destructive tab
DW OFFSET B$SCNCRLF ; ^J - Linefeed outputs CR/LF.
DW OFFSET WHOME ; ^K - Home within window
DW OFFSET CCLRSN ; ^L - Clear window, home cursor
DW OFFSET B$SCNCRLF ; ^M - carriage return
DW OFFSET WCSADV ; ^\ - Cursor advance within window
DW OFFSET WCSREG ; ^] - Cursor regress within window
DW OFFSET WCSUP ; ^^ - Cursor up within window
DW OFFSET WCSDWN ; ^_ - Cursor down within window
;***
;LPTECHO
;Purpose:
; Echo to the line printer.
; Added with revision [32].
;Entry:
; [AX] = character code
;Exit:
; none
;Modifies:
; None ([AX-DX] is preserved)
;****
cProc LPTECHO,<NEAR>,<AX,BX,CX,DX> ; preserve the world
cBegin
EchoAnother:
PUSH AX ;store byte in stack
MOV DX,SP ;[DS:DX] points to data to be output
.ERRE ID_SSEQDS ;assumes DS=SS
MOV BX,0004H ;file handle for stdprn
MOV CX,1 ;[CX] = # of bytes to be written
MOV AH,40H ;write operation
INT 21H ;do the write
POP AX ;even stack and restore AX
JNC LPTECHOExit ;jump if no error on write
JMP B$ERR_IOE ;give generic Device I/O Error
LPTECHOExit:
CMP AL,ASCCR ; just printed a CR?
MOV AL,ASCLF ; Assume so -- then we want a LF, too
JE EchoAnother ; brif CR -- add a Line feed
cEnd
;***
; PUTSTD - Put character to redirected standard output.
;
; Purpose:
; Writes a char to redirected stdout. If given character is a <cr>, [13]
; put out an <lf> also, as stdout needs one. Adjust the redirected [13]
; file cursor position (used to do line wrapping) appropriately. [13]
;
; Entry: [BX] = character (or zero)
; Exit: none
; Modifies:
; F, AX
;****
PUTSTD:
OR BX,BX ; Test to see if character exists
JZ PUTSTDX ; BRIF not
MOV AX,BX ; place char in AX as well
CMP AX,0AH ; about to output an <lf>?
je PUT_CR_FIRST ; brif <lf> to put a <cr> first
PUTSTD2:
CLC ;PWS.C reset indicates a 1 byte character
CALL B$STDPUT ; Write the character
MOV AX,BX ; restore character into AX
CMP AL,9 ; ASCII code < 9 (HT)?
JB INC_CSR ; brif if so -- increment cursor.
JE TAB_CHAR ; brif HT
CMP AL,0DH ; <lf>,<vt>,<ff>,<cr> ?
JE PUT_LF_TOO ; brif <cr> to put an <lf> too
JBE RESET_CSR ; brif <LF>,<VT>, or <FF>
INC_CSR:
INC b$REDCSRX ; increment redirected file cursor
PUTSTDX:
RET
PUT_CR_FIRST: ;here if we're about to put out an lf
MOV AX,0DH ; output a <cr> first
CLC ;Writing a single byte
CALL B$STDPUT ; write it out
MOV AX,0AH ; restore <lf>
JMP SHORT PUTSTD2
PUT_LF_TOO: ;here if we've just sent a <cr> to stdout and
;need to put in an <lf> now
MOV AX,0Ah ;put <lf> in AX
CLC ;Writing a single byte
CALL B$STDPUT ; write it out, and reset cursor position
RESET_CSR:
XOR AX,AX ; reset redirected file cursor to 1 for
JMP SHORT TAB_DONE ; <LF>,<VT>,<FF>,<CR>
TAB_CHAR: ; adjust cursor when TAB printed
MOV AL,b$REDCSRX ; load redirected file cursor (1-relative)
ADD AL,8 ; move to next modulo-8 position.
AND AL,0F8H
TAB_DONE:
INC AX ; make it 1-relative
MOV b$REDCSRX,AL ; store redirected file cursor
RET ; and return from PUTSTD
;***
; B$CHKLASTCOL -- check for last column on screen. Added with revision [19]
;
;Purpose:
; Sets flags according to whether DH is [<,=,>] the last printable
; screen location.
;
;Entry:
; DH = 1-relative screen column
;Exit:
; Flags set as if CMP DH,LAST_POS was done.
;Uses:
; None
;Preserves:
; All
;Exceptions:
; None
;
;******************************************************************************
cProc B$CHKLASTCOL,<PUBLIC,NEAR>
cBegin
CMP b$PTRFIL,0 ; Test if TTY (=0) or SCRN: (>0)
JE CHK_PHYS ; If TTY then check physical width
CMP DH,b$SCRNWIDTH ; Test if over logical (SCRN:) width
JAE CHK_EXIT ; Brif if greater than or equal
CHK_PHYS:
CMP DH,b$CRTWIDTH ; Check for last physical column
CHK_EXIT:
cEnd
;***
; B$UPDATE_CSR -- Update cursor after a screen write.
; Added with revision [19]
;
;Purpose:
; Updates the high-level cursor position, and displays the user
; cursor at the appropriate place. If we have just printed into
; the last column of the screen, the cursor is NOT displayed at
; the first position of the next line. Instead, it is backed up
; on top of the character just written.
;
;Entry:
; DX = new cursor position
;Exit:
; b$CURSOR updated
;
; DX = position at which cursor was displayed
;Uses:
; None
;Preserves:
; All
;Exceptions:
; None
;
;******************************************************************************
cProc B$UPDATE_CSR,<PUBLIC,NEAR>
cBegin
MOV b$CURSOR,DX ; update logical cursor b$CURSOR
CALL B$CHKLASTCOL ; past last column?
JBE NO_DEC ; brif not
DEC DH ; back up one position to display cursor
NO_DEC:
JMP B$USRCSR ; Redisplay user cursor and return
cEnd <nogen>
;***
; CHKCHAR -- Sets fields of DL to facilitate complicated checks. Added with
; revision [13].
;
; Purpose:
; Decide whether a character should be printed on the screen, to the
; redirected file, and/or to the printer, according to the following chart:
;
;------------------------------------------------------------------------
; | | | | INPUT statement |
; Redirection | FKEY | SCRN: | CONS: | with edits | without edits |
;---------------|-------|-------|-------|---------------|---------------|
; No redirection| S | S,P | S,P | S | S,P |
; Red OUT | --- | S,P | F | S | F,P |
; Red INP | S | S,P | S,P | S | S,P |
; Red INP & OUT | --- | S,P | F | --- | F |
;------------------------------------------------------------------------
;
; S = print char to screen
; P = print char to printer
; F = print char to redirected output
;
; Function key display when F_KDSP.
; Printing to SCRN: when b$PTRFIL <> 0.
; INPUT statement with user edits when IN_INPUT.
; INPUT statement without user edits when
; (F_EDIT and NOT IN_INPUT).
; Printing to CONS: at all other times.
;
;
; Algorithm summary:
;
; Char should be printed to redirected file (RED_CHR) if:
; RED_OUT and NOT (SCRN: or IN_INPUT or F_KDSP)
;
; Character should be printed to the screen (SCN_CHR) if:
; SCRN: or NOT RED_OUT or (NOT RED_INP and IN_INPUT)
;
; Character should be echoed to the printer (LPR_CHR) if:
; LPR_ECHO and NOT F_KDSP and NOT IN_INPUT and
; (SCRN: or NOT RED_OUT or
; (RED_OUT and NOT IN_INPUT and F_EDIT))
; Input:
; b$PTRFIL set correctly.
; Exit:
; SCN_CHR, RED_CHR, and LPR_CHR fields of DL set correctly.
; Modifies:
; DX, F
;****
cProc CHKCHAR,<NEAR>,<AX>
cBegin
XOR DX,DX ; initially all flags are false
MOV AL,b$IOFLAG ; keep b$IOFLAG in AL
TEST AL,RED_OUT ; is output redirected?
JZ SCN_CHAR ; brif not -- screen char
CMP b$PTRFIL,DX ; Test if TTY (=0) or SCRN: (>0)
JNZ SCN_CHAR ; brif SCRN: -- screen char
TEST AL,F_KDSP OR IN_INPUT ; function key display or
; INPUT statement?
JNZ CHK_SCN ; brif so -- not a redir char
OR DL,RED_CHR ; set bit to indicate redir char
JMP SHORT CHK_LPR ; skip check for screen char
CHK_SCN: ; RED_OUT = TRUE here
TEST AL,RED_INP ; redirected input?
JNZ CHK_LPR ; brif so -- not screen char
TEST AL,IN_INPUT ; INPUT statement?
JZ CHK_LPR ; brif not -- not screen char
SCN_CHAR:
OR DL,SCN_CHR ; set bit to indicate screen char
CHK_LPR:
TEST AL,LPR_ECHO ; printer echo wanted?
JZ CHKCHAR_EXIT ; brif not -- not a printer char
TEST AL,F_KDSP OR IN_INPUT ; function key display or IN_INPUT?
JNZ CHKCHAR_EXIT ; brif so -- not a printer char
CMP b$PTRFIL,0 ; Test if TTY (=0) or SCRN: (>0)
JNZ LPR_CHAR ; brif SCRN: -- printer char
TEST AL,RED_OUT ; redirected output?
JZ LPR_CHAR ; brif not -- printer char
AND AL,RED_INP OR F_EDIT ; redisplaying line and not
CMP AL,F_EDIT ; redirected input ?
JNZ CHKCHAR_EXIT ; brif not -- not a printer char
LPR_CHAR:
OR DL,LPR_CHR ; set bit to indicate printer char
CHKCHAR_EXIT:
cEnd
;***
; REDMAP - Map character for redirected std. output file
;
; Purpose:
; Given a character to be printed to redirected stdout, return
; the mapped character in BX or 0 character should be ignored.
; Input:
; [AX] = unmapped control character for screen
; Output:
; [BX] = mapped char for std output (0 if it should be ignored)
; may be a 1- or a 2-byte character
; Modifies:
; F
;****
REDMAP: PUSH AX
XOR BX,BX ;Assume no character for standard output
CMP AH,1 ;Set PSW.C for two byte character
CMC
cCALL B$PRTMAP ; Map as if a print statement
JZ REDMAX ;No character to print
MOV BX,AX ;Assume character will be used as mapped
JNB REDMAX ;Print character as mapped
CMP AH,255D ;Test for control character
JNZ REDMAX ;Must be KANJI or other FK_KANJI
XOR BH,BH ;Map to single byte char
REDMAX:
POP AX
RET
PAGE
SUBTTL CONTROL CHARACTER ROUTINES - Beep, form feed, home, backspace, tab.
;***
; B$BEEP - BEEP stmt
;
; Purpose:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -