📄 gwcom.asm
字号:
MOV [DI].CD_DSRTO,1000 ;set data-set-ready timeout to 1 second
MOV [DI].CD_RXSIZ,AX ;clear receive buffer size for default
MOV [DI].CD_TXSIZ,AX ;clear transmit buffer size for default
; The first character of each parameter is read. If a null field,
; it is ignored. If at the option string end, then return.
ParseLoop:
CALL GetOptChar ;read the first character in AL
JNC ParseNext ;if not a separator, then start processing
JNZ ParseLoop ;if comma, then just ignore it
JMP ParseEnd ;else process end of statement
; Test for valid prefix on parameter. To reduce code size, read the
; second character and use both for testing.
ParseNext:
MOV AH,AL ;move first character
CALL GetOptChar ;first character in AH, second in AL
; First, test for "RS". If so, then set RS flag and set default
; CSn value to zero.
CMP AX,"RS" ;test if RS
JNE ParseOP ;if not, try OP next
OR [DI].CD_CMFLG,CF_CMRTS ;set the RS flag in the DCB
TEST [DI].CD_CMFLG,CF_CMCTS ;test if CS value is still default
JNZ ParseTerm ;test for termination after parameter
MOV [DI].CD_CTSTO,0 ;set the CS timeout value to 0 (disable)
; For parameters that do not have a numeric argument that is
; processed with GetOptVal, the character after the parameter
; must be a terminator (comma or end-of-string).
ParseTerm:
CALL GetOptChar ;get what should be terminator
JC ParseLoop ;if so, then loop for the next parameter
ParseTermErr:
JMP B$ERR_BFN ;jump to report error in option string
; Second, test for "OP". If so, then read the following numeric
; value and put it in the DCB and set the flag.
ParseOP:
CMP AX,"OP" ;test for OP
JNE ParseDS ;if not, then test for DS
CALL GetOptVal ;get numeric value in DX
JNC ParseOPNoDef ;if numeric value specified, then jump
MOV DX,10000D ;otherwise set to 10 seconds
ParseOPNoDef:
MOV [DI].CD_OPNTO,DX ;put value in DCB
OR [DI].CD_CMFLG,CF_CMOPN ;set flag for OP parameter given
JMP SHORT ParseLoop ;jump to process next parameter
; Third, test for "DS". If so, then read the following numeric
; value and put it in the DCB.
ParseDS:
CMP AX,"DS" ;test for DS
JNE ParseCD ;if not, then test for CD
CALL GetOptVal ;get numeric value in DX
MOV [DI].CD_DSRTO,DX ;put value in DCB
JMP SHORT ParseLoop ;jump to process next parameter
; Fourth, test for "CD". If so, then read the following numeric
; value and put it in the DCB.
ParseCD:
CMP AX,"CD" ;test for CD
JNE ParseCS ;if not, then test for CS
CALL GetOptVal ;get numeric value in DX
MOV [DI].CD_RLSTO,DX ;put value in DCB
JMP SHORT ParseLoop ;jump to process next parameter
; Fifth, test for "CS". If so, then read the following numeric
; value and put it in the DCB.
ParseCS:
CMP AX,"CS" ;test for CS
JNE ParseRB ;if not, then test for RB
CALL GetOptVal ;get numeric value in DX
MOV [DI].CD_CTSTO,DX ;put value in DCB
OR [DI].CD_CMFLG,CF_CMCTS ;set flag for nondefault CS timeout
JMP SHORT ParseLoop ;jump to process next parameter
; Sixth, test for "RB". If so, then read the following numeric
; value and put it in the DCB.
ParseRB:
CMP AX,"RB" ;test for RB
JNE ParseTB ;if not, then test for TB
CALL GetOptVal ;get numeric value in DX
MOV [DI].CD_RXSIZ,DX ;put value in DCB
JMP SHORT ParseLoop ;jump to process next parameter
; Seventh, test for "TB". If so, then read the following numeric
; value and put it in the DCB.
ParseTB:
CMP AX,"TB" ;test for TB
JNE ParseLF ;if not, then test for LF
CALL GetOptVal ;get numeric value in DX
MOV [DI].CD_TXSIZ,DX ;put value in DCB
JMP ParseLoop ;jump to process next parameter
; Eighth, test for "LF". If so, then set the flag in the DCB.
ParseLF:
CMP AX,"LF" ;test for LF
JNE ParseBIN ;if not, then test for BIN
OR [DI].CD_CMFLG,CF_CMCLF ;set the LF flag
JMP SHORT ParseTerm ;jump to check for terminator
; Ninth, test for "BIN". If so, then set the flag in the DCB.
ParseBIN:
CMP AX,"BI" ;test for BI
JNE ParseASC ;if not, then test for ASC
CALL GetOptChar ;get the third character
CMP AL,"N" ;test if parameter was BIN
JNE ParseTermErr ;if not, then error
ParseCOD:
TEST [DI].CD_CMFLG,CF_CMCOD ;test if ASC or BIN specified before
JNZ ParseTermErr ;if so, then error
OR [DI].CD_CMFLG,CF_CMCOD ;set the flag for ASC or BIN specified
JMP ParseTerm ;jump to test for terminator
; Tenth, test for "ASC". If so, then clear the flag in the DCB.
ParseASC:
CMP AX,"AS" ;test for AS
JNE ParsePE ;if not, then test for PE
CALL GetOptChar ;get the third character
CMP AL,"C" ;test if parameter was ASC
JNE ParseTermErrJmp ;if not, then error
AND [DI].CD_CMFLG,NOT CF_CMBIN ;clear the binary mode flag
JMP SHORT ParseCOD ;jump to check CF_CMCOD in DCB
ParseTermErrJmp:
JMP ParseTermErr ;short jump to process error
; Finally, test for "PE". If so, then set the flag in the DCB.
ParsePE:
CMP AX,"PE" ;test for PE
JNE ParseTermErrJmp ;if not, then unknown parameter - error
OR [DI].CD_CMFLG,CF_CMPEN ;set the flag PE specified
JMP ParseTerm ;jump to test for terminator
; The end of the statement has been reached. If not specified,
; compute the open timeout value to be ten times the maximum of the
; other timeouts, with a maximum value of 64K-1 milliseconds.
ParseEnd:
TEST [DI].CD_CMFLG,CF_CMOPN ;test if nondefault OP timeout
JNZ ParseRet ;if so, then use the one specified
MOV AX,[DI].CD_RLSTO ;get the CD timeout value
CMP AX,[DI].CD_DSRTO ;test against the DS timeout value
JA ParseKeep1 ;jump to keep greater value in AX
MOV AX,[DI].CD_DSRTO ;else update the maximum value
ParseKeep1:
MOV CX,0FFFFH ;assume maximum value
MOV DX,10 ;factor to multiply maximum time
MUL DX ;compute OP timeout in DX:AX
JC ParseSetOP ;if over 64K-1, then jump to set max
MOV CX,AX ;set the product
ParseSetOP:
MOV [DI].CD_OPNTO,CX ;set the OP timeout value
ParseRet:
RET ;if statement end, then finished, so return
;***
; GetOptChar - get a character in the option string
;
; Purpose:
; [Rewritten as part of revision 6].
; The next character in the option string is read into AL.
; If lower case, it is mapped to upper case and the carry and
; zero flags are set accordingly. Blank and tab characters
; are ignored.
; Input:
; SI = pointer to next character in the option string.
; Outputs:
; SI = pointer to the following character (except for string end).
; AL = character (mapped if lower case).
; CF set and ZF set = end of string
; CF set and ZF clear = comma character
; CF clear and ZF clear = not comma or end of string
; Modifies:
; None.
; Exceptions:
; None.
;*****************************************************************************
GetOptChar:
LODSB ;get the next character from the string
CMP AL," " ;test if blank character
JE GetOptChar ;if so, then ignore it
CMP AL,ASCHT ;test if tab character
JE GetOptChar ;if so, then also ignore it
CMP AL,"," ;test if comma
JE GetOptStc ;if so, then return with CF set and ZF clear
CMP AL,"a" ;test if character is lower case
JB GetOptNoMap ;if not, then skip the mapping
ADD AL,"A"-"a" ;map lower case letter to upper
GetOptNoMap:
OR AL,AL ;test if at the end of the string
JNZ GetOptRet ;if not end, then return with CF and ZF clear
DEC SI ;backup pointer to the statement end
OR AL,AL ;clear ZF again for exit condition
GetOptStc:
STC ;set carry for end-of-statement or comma
GetOptRet:
RET ;near return to caller
;***
; GetOptVal - get value from option string
;
; Purpose:
; [Rewritten as part of revision 6].
; To read the option string for characters to be interpreted
; as decimal digits. A value from these digits is computed
; and returned. This routine then checks for a proper terminating
; character (either a comma or end-of-string) after the value.
; If no terminator, then an error is reported.
; Inputs:
; SI = pointer to option string at value.
; Outputs:
; SI = pointer to option string after the terminator.
; DX = computed value.
; CY set = null value (first character terminator).
; clear = nonnull value.
; Modifies:
; AX.
; Exceptions:
; B$ERR_BFN - bad file name if improper terminator.
;*****************************************************************************
GetOptVal:
PUSH BX ;save register
XOR DX,DX ;initialize result
CALL GetOptChar ;get the first character of the value
JC GetOptValRet ;return with CY set for null value
DEC SI ;back up over first character read
GetOptValLoop:
CALL GetOptChar ;get option string character in AL
CMC ;complement so CY clear for terminator
JNC GetOptValRet ;return with CY clear for nonull value
SUB AL,"0" ;subtract bias for decimal digit
CMP AL,9 ;test if digit or not
JA GetOptValErr ;if not digit or terminator, then error
CBW ;zero AH for word value
SHL DX,1 ;present result * 2
JC GetOptValErr ;jump if overflow error
MOV BX,DX ;save result * 2
SHL DX,1 ;present result * 4
JC GetOptValErr ;jump if overflow error
SHL DX,1 ;present result * 8
JC GetOptValErr ;jump if overflow error
ADD DX,BX ;present result * 10
JC GetOptValErr ;jump if overflow error
ADD DX,AX ;add in new digit - new value
JNC GetOptValLoop ;if no overflow, then loop for next
GetOptValErr:
JMP B$ERR_BFN ;if error, then bad file name
GetOptValRet:
POP BX ;restore register
RET ;near return to caller
;
;Written as part of revision [6]
;
;***
;B$ComAlloc - Allocate memory for a communications device
;
;Purpose:
; From high memory, allocate two blocks for use as communications
; queues, one for the receive queue and the other for the transmit
; queue. The size of the two queues is passed into this procedure
; as an arguement.
;
; If the size specified for the receive queue is 0, then the size
; given on the command line with the /C:xxx option is used. If this
; value is -1 (not specified), then the queue will be cbComBuf bytes
; long. If the size specified for the transmit queue is 0, then
; it will be cbComBuf bytes long.
;
; On exit, the DCB of the communications device that was passed
; in as a parameter will have the segment which contains the
; receive queue and the transmit queue. The queues will be the
; first (and only) things in the segments. The fields of the
; DCB are defined in comdcb.inc.
;
; For OS/2, this routine will also allocate a 2K-byte block for the
; stack of the thread.
;
;Entry:
; DI = communications device control block (DCB)
; [DI].CD_RXSIZ = size of the receive queue in bytes
; [DI].CD_TXSIZ = size of the transmit queue in bytes
;
;Exit:
; [DI].CD_RXSEG = segment of memory allocated for the receive queue
; [DI].CD_TXSEG = segment of memory allocated for the transmit queue
; [DI].CD_SPSIZ = size of the thread stack in bytes (2048+slop)
; [DI].CD_SPSEG = segment of memory allocated for the thread stack
;
;Uses:
; Per convention.
;
;Exceptions:
; B$ERR_DNA - device not available if /C:0 for compatibility
; This error will be given if the option's value is
; needed or not.
; B$ERR_OM - out of memory if allocation failed for any reason.
;****************************************************************************
PUBLIC B$ComAlloc
B$ComAlloc PROC NEAR
; Get the C parameter value for comm buffer size.
MOV AX,b$cbComBuffer ;get /C:nnnn value saved from command line
; If buffer size is zero, then error.
OR AX,AX ;test if zero buffer size
JZ ComAllocDNAErr ;if so, then give "device not available" error
; Compute the size of the receive queue. If [DI].CD_RXSIZ is
; nonzero, use the size specified in the RB[n] parameter.
MOV DX,[DI].CD_RXSIZ ;get the receive buffer size
OR DX,DX ;test if specified
JNZ ComAllocRB ;if so, then use it
; Use size in AX from command line, except for -1 where the
; default is cbComBuf bytes.
MOV DX,cbComBuf ;default size for receive buffer
CMP AX,-1 ;test if -1 for default
JE ComAllocRBSet ;if default, use cbComBuf bytes
MOV DX,AX ;move size from command line for use
ComAllocRBSet:
MOV [DI].CD_RXSIZ,DX ;set the block size
; Allocate the receive queue and set buffer segment in DCB.
ComAllocRB:
MOV AX,DX ;move the size into AX
XOR DX,DX ;size in bytes now in DX:AX
CALL B$FHHighAlloc ;allocate the comm buffer with segment in CX
JCXZ ComAllocOMErrR ;out of memory if couldn't allocate buffer
MOV [DI].CD_RXSEG,CX ;[8]set the DCB segment
; Compute the size of the transmit queue. If [DI].CD_TXSIZ is
; nonzero, use the size specified in the TB[n] parameter.
MOV AX,[DI].CD_TXSIZ ;get the transmit buffer size
OR AX,AX ;test if specified
JNZ ComAllocTB ;if so, then use it
; If not specified, use the size of cbComBuf bytes.
MOV AX,cbComBuf ;default size for transmit buffer
MOV [DI].CD_TXSIZ,AX ;set the default size of the buffer
; Allocate the transmit queue and set buffer segment in DCB.
ComAllocTB:
XOR DX,DX ;size in bytes now in DX:AX
CALL B$FHHighAlloc ;allocate the comm buffer with segment in CX
JCXZ ComAllocOMErrT ;out of memory allocation failed
MOV [DI].CD_TXSEG,CX ;[8]set the DCB segment
; Allocate the stack for the thread and set segment in DCB.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -