📄 inptty.asm
字号:
; turn user cursor off (in order to print prompt)
; save # of values in VALCNT
; save input flag ("?" and/or CR)
;
; (II) Parse each value
; print prompt with/out "? " <CR>
; ** read line
; clean the stack by using [b$StkBottom]
;
; loop each input value and check the type (B$FIN)
; Note that around the call to B$FIN (for as short a
; period as possible) the error vector is set such that
; all errors encounted will vector back here.
; if no error then
; push value into the stack
; else /* error happened */
; give error message
; reconstruct stack frame on the TOP OF THE STACK
; goto (II)
; (III) epilog
; give error if the number of values is not correct (goto
; error handling routine and start over)
; restore registers from memory location
; far jump to the caller
;
; Note: ** means stack frame has to be in stack.
;
; NOTE: This routine can take a far pointer to a movable item in a heap. This
; routine cannot directly or indirectly cause heap movement. (The interpeter
; places the parameter block in a far heap entry).
;
;Entry:
; Parameters in stack.
; sd sdPrompt
; int far*pBlock
;
; Refer the source head comments for the structure of Block.
;Exit:
; values are in stack.
;
; [b$DATAPT] = [b$StkBottom] points to the bottom of var list & stack
; NOTE: the direction of the list is auto-decrement.
;
; [BlockPt] contains the far pointer to the types list
; NOTE: the type list is the subset of the Block described above.
;
; [VALCNT] is the count of how many variables
;Uses:
; none
;Exceptions:
;
;*******************************************************************************
cProc B$INPP,<PUBLIC,FAR>
ParmSD sdPrompt ;sd of prompt string
ParmD pBlock ;far point to Block
;NOTE: we may use the symbols of off_pBlock
; and seg_pBlock
cBegin ;generate stack frame
MOV [SaveES],ES ;save ES
MOV [SaveSI],SI ;save SI
MOV [SaveDI],DI ;save DI
LEA BX,[BP+12] ;bottom of the stack and var list
MOV [b$DATAPT],BX ; [b$DATAPT] = [b$StkBottom]
MOV [b$StkBottom],BX
.erre ID_SSEQDS ; give error if SS <> DS
PUSH DS
POP ES ; let ES=DS
MOV SI,BP ; source addr
MOV DI,OFFSET DGROUP:SaveBP ; destination addr
MOV CX,3 ; 3 words
REP MOVSW ; save in data area, stack frame still in
; stack
MOV [b$PTRFIL],CX ; Set output to TTY (CX=0)
GetpSD BX,sdPrompt ;BX = psdPrompt
MOV [PROMPT],BX ;Save prompt string descriptor address
LES DI,pBlock ;ES:DI points to the block
MOV AX,ES:[DI] ;get block length
DEC AX ; block length is n+1
MOV [VALCNT],AX ;Remember number of values
INC DI
INC DI ;increment the pointer
MOV AL,ES:[DI] ;get the flag byte
MOV [INFLG],AL ;save flag byte
INC DI ;so DI points to the list of types now
MOV [BlockOff],DI
MOV [BlockSeg],ES ;save segment:offset to the Block
PrtPrompt: ;Enter here if error to re-prompt and
; re-read data
MOV BX,[PROMPT] ;BX=*sd of Prompt
CALL B$TYPSTR ;Print the prompt
TEST [INFLG],FINP_QSupress ;Need a "?" after prompt?
JNZ GetLin ;Brif not
MOV AL,"?" ;output "?"
CALL B$$WCHT
MOV AL," " ; and one blank
CALL B$$WCHT
GetLin:
CALL B$RDLIN ;get input line
TEST [INFLG],FINP_CrLf ;is it INPUT "semi-colon" ?
JNZ CleanStk ;Brif yes, don't send <CR><LF>
CALL B$INPCRLF ; force CR to all places where input was
; written (screen and/or redirected file)
CleanStk:
MOV SP,[b$StkBottom] ; clean the stack
; at this point, stack frame is destroyed.
; Since B$FIN return error code and error
; handler will restore the stack frame, it
; should be fine.
MOV AX,[VALCNT] ;get # of types
MOV [TYPCNT],AX ;Initialize count of values
MOV SI,OFFSET DGROUP:b$Buf1
;DS:SI points to the value list
LES DI,[BlockPt] ;ES:DI points to the type list
; At this point, [TYPCNT] has the number of values
; ES:DI points to the next type in the type list
; DS:SI points to the next input in the input stream
; stack is ready to put values.
EachVal:
MOV AL,ES:[DI] ;get next type
INC DI ;increment the pointer
MOV [b$VTYP],AL ;save the type (used by B$FIN)
MOV [b$errvec],DK_TEXTOFFSET InpErr ; set err vec
PUSH ES
PUSH DS ; set ES = segment of source
POP ES
INC [b$curlevel] ; Increment level for possible dealloc
CALL B$FIN ;get number or string (AL=Next Char)
DEC [b$curlevel] ; restore b$curlevel
POP ES
MOV [b$errvec],0 ; reset error vector
MOV CL,[b$VTYP] ;get the type
AND CL,0FH ;get rid of upper half
CMP CL,VT_R4 ;is 2 byte value ?
MOV BX,OFFSET DGROUP:B$AC
;BX has the result
JB PushAC ;Don't do high word if integer or string
PUSH [BX+2] ;Push highest word
PushAC:
PUSH [BX]
JBE NextVal ;Only push low words if D.P.
PUSH [BX-2]
PUSH [BX-4]
NextVal:
DEC [TYPCNT] ;any values left?
JZ ChkEnd ;Brif no more
CMP AL,"," ;values must be separated by ","
JZ EachVal ;process next value
;Come here to restart if any error occurred
RedoFromStart:
CALL B$$TCR ;force CR/LF
MOV AX,MS_REDO ;message number
cCall B$PUTNUM ; output message
CALL B$$TCR ;force CR/LF
MOV AX,[b$curlevel] ; setup for string temp deallocation...
INC AX ; ...only above current level!
CALL B$STDALCALLTMP ; deallocate all string temps.
MOV SP,[b$DATAPT] ;roughly clean the stack, this is only to
; avoid stack overflow when we restore the
; stack frame. the thorough clean will be
; done after read line.
PUSH [RetSeg] ;restore stack fram on stack
PUSH [RetOff]
PUSH [SaveBP]
MOV BP,SP
JMP PrtPrompt ;redo from start
;Come here from error trap if overflow in $FIN
InpErr: ; give error message
DEC [b$curlevel] ; restore [b$curlevel] after B$FIN error
MOV [b$errvec],0 ; don't allow infinite loop
PUSH BX ; save error number
CALL B$$TCR ;force CR/LF
POP AX ; get back error number
cCall B$PUTNUM ; output message
JMP SHORT RedoFromStart ; redo from start
ChkEnd:
OR AL,AL ;Did we reach end of line?
JNZ RedoFromStart ; Brif not, redo from the start
MOV BX,[PROMPT] ; BX = pointer to prompt string
cCall B$STDALCTMP ; deallocate it if it was temp
MOV [b$GetOneVal],OFFSET TTYInpVal
;set up for get one input item
MOV [b$FInput],InpTTY
;set input flag
MOV DI,[SaveDI] ;restore registers
MOV SI,[SaveSI]
MOV ES,[SaveES]
MOV BP,[SaveBP]
JMP [RetAddr] ;return to caller
cEnd nogen ;no code generated
SUBTTL TTY input supporting routine -- TTYInpVal
page
;***
;TTYInpVal -- get one input value
;
;Purpose:
; This routine gets one value from the buffer (in stack).
;
; After the input preamble, the succeeding calls will assign values
; into variables. The functionality of those assignment routines,
; B$RD<type>, may be roughly split into two parts -- namely, getting
; one value and then assigning it to the variable. In BASCOM 3.0,
; those assignment routines are shared by READ stmt, input from TTY
; and input from a disk file (or a device). Generally speaking,
; the second part of the assignment routines DOESN'T discriminate
; among the statements which share its use. However, the first part
; of the assignment routines MUST discriminate among the statements
; which share its use. In order to achieve this, the first part of
; the assignment routines uses an indirect call, CALL [b$GetOneVal],
; to get one value. [b$GetOneVal] is default to the address of
; ReadVal, which gets one value for READ stmt, or contains either
; the address of TTYInpVal for TTY input or the address of DskInpVal
; for disk (device) input.
;
;Entry:
; [b$VTYP] = types
; [b$DATAPT] points to the var list
;Exit:
; [SI] = pointer to the value
; [b$DATAPT] is updated
;Uses:
; none
;Exceptions:
; none
;*******************************************************************************
cProc TTYInpVal,<NEAR> ;assume DS=SS, ES=DS when enter
cBegin
.erre ID_SSEQDS ;assume SS=DS (used in B$RD<type>)
MOV SI,[b$DATAPT] ;get pointer to next value
MOV AL,[b$VTYP] ; AL has the type
CBW ;AX has the type
AND AL,0EH ;AX has the length
SUB SI,AX ;SI points to the begining of the source
MOV [b$DATAPT],SI ;save for next call
cEnd ;return to caller
SUBTTL RANDOMIZE interface -- B$RNZ0
page
;***
;B$RNZ0 -- randomize without parameter specified.
;void B$RNZ0(void)
;
;Purpose:
; Reseeds the random number generator.
; Moved here from RANDOM.ASM [21]
;
;Entry:
; This routine prompts for the user to enter the new random number seed'
;
;Exit:
; User specified seed is stored in b$RndVar+1 (the middle word of the random
; number (DWORD)).
;
;Uses:
; Per convention
;
;Exceptions:
; B$ERR_OV -- overflow (in B$INPP)
;
;*******************************************************************************
cProc B$RNZ0,<PUBLIC,FAR,FORCEFRAME>
cBegin
MOV AX,MS_SEED
cCall B$PUTNUM ;Output seed message
MOV AX,OFFSET DGROUP:b$nuldes
PUSH AX ;push *sd of prompt
PUSH DS ;far pointer
MOV AX,OFFSET DGROUP:RandpBlock
PUSH AX ;push *pBlock
cCall B$INPP ;on return, input value is in stack
PUSH DS
MOV AX,OFFSET DGROUP:b$RndVar+1 ;destination
PUSH AX
cCall B$RDI2 ;read user's seed into destination
cCall B$PEOS ;reset flags & variables
cEnd ;exit to caller
sEnd ;DK_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -