Category : Assembly Language Source Code
Archive   : KRMTSRCE.ZIP
Filename : MSSTER.ASM

 
Output of file : MSSTER.ASM contained in archive : KRMTSRCE.ZIP
NAME msster
; File MSSTER.ASM
; Last edit 12 June 1988
; 1 July 1988 Version 2.31
; 12 June 1988 Add error recovery if serial port fails to initialize
; 29 May 1988 Cleanup one letter Connect dispatch routines
; 27 Feb 1988 Add capability of stdin being a file. [jrd]
; 27 Jan 1988 Remove serrst call, done now in mssker idle loop. [jrd]
; 1 Jan 1988 version 2.30

public clscpt, defkey, clscpi, ploghnd, sloghnd, tloghnd
public dopar, shokey, cptchr, pktcpt, targ
public kbdflg, shkadr, telnet, ttyact
public cnvlin, katoi, decout, valout, atoi, cnvstr
include mssdef.h

braceop equ 7bh ; opening curly brace
bracecl equ 7dh ; closing curly brace

datas segment public 'datas'
extrn flags:byte, trans:byte, buff:byte, portval:word

targ termarg <0,1,80,24,cptchr,2dch,0,scntab,deftab,0,,parnon>
crlf db cr,lf,'$'
tmsg1 db cr,lf,'(Connecting to host, type $'
tmsg3 db ' C to return to PC)',cr,lf,cr,lf,cr,lf,'$'
erms25 db cr,lf,'?Input must be numeric$'
erms22 db cr,lf,'?No open logging file$'
erms23 db cr,lf,'?Error writing session log, suspending capture.'
db cr,lf,'$'
erms24 db cr,lf,'?Error writing Packet log$'
esctl db 'Control-$'

inthlp db cr,lf,' ? This message F Dump screen to file'
db cr,lf,' C Close the connection P Push to DOS'
db cr,lf,' S Status of the connection Q Quit logging'
db cr,lf,' M Toggle mode line R Resume logging'
db cr,lf,' B Send a Break 0 Send a null'
db cr,lf,' L Send a long 1.8 s Break H Hangup phone'
db cr,lf,' Typing the escape character will send it to the host'
db 0 ; this short-form obscures less screen area [jrd]

intprm db 'Command> $'
intclet db 'B','C','F','H','L' ; single letter commands
db 'M','P','Q','R','S' ; must parallel dispatch table intcjmp
db '?','0'
numlet equ $ - intclet ; number of entries
intcjmp dw intchb,intchc,intchf,intchh,intchl
dw intchm,intchp,intchq,intchr,intchs
dw intchu,intchn

pktbuf db cptsiz dup (?) ; packet logging buffer
pktbp dw pktbuf ; buffer pointer to next free byte
pktlft dw cptsiz ; number free bytes left
capbuf db cptsiz dup (?) ; session logging buffer
capbp dw capbuf ; buffer pointer to next free byte
caplft dw cptsiz ; number free bytes left

ploghnd dw -1 ; packet logging handle
sloghnd dw -1 ; session logging handle
tloghnd dw -1 ; transaction logging handle

clotab db 4
mkeyw 'All',logpkt+logses+logtrn
mkeyw 'Packets',logpkt
mkeyw 'Session',logses
mkeyw 'Transaction',logtrn

clseslog db cr,lf,' Closing Session log$'
clpktlog db cr,lf,' Closing Packet log$'
cltrnlog db cr,lf,' Closing Transaction log$'
clohlp db cr,lf,' One of the following log files:'
db cr,lf,' ALL, Packets, Session, Transaction$'
scntab dw 0
deftab dw 0
sttmsg db cr,lf,'Type space to continue ...$'
kbdflg db 0 ; non-zero means char here from Term
ttyact db 0 ; Connect mode active, if non-zero
shkadr dw 0 ; offset of replacement Show Key cmd
ten dw 10 ; multiplier for setatoi
nbase dw ? ; currently active number base
numset db '0123456789ABCDEF' ; number conversion alphabet
tmp db ?
datas ends

code segment public 'code'
extrn comnd:near, outchr:near, stat0:near, iseof:near
extrn clrbuf:near, term:near, strlen:near
extrn prtchr:near, ihostr:near
extrn beep:near, puthlp:near, getbaud:near, serhng:near
extrn serini:near,serrst:near, sendbr:near, showkey:near
extrn fpush:near, dumpscr:near, pcwait:near, sendbl:near
assume cs:code, ds:datas

; the show key command
shokey proc near
cmp shkadr,0 ; keyboard translator present?
je shokey1 ; e = no, use regular routines
mov bx,shkadr ; get offset of replacement routine
jmp bx ; and execute it rather than us
shokey1:jmp rskp ; and return
shokey endp
; enter with ax/scan code to define, si/ pointer to definition, cx/ length
; of definition. Defines it in definition table. Obsolete.
defkey proc near
ret
defkey endp

; This is the CONNECT command

TELNET PROC NEAR
mov ah,cmcfm
call comnd ; Get a confirm
jmp r ; Didn't get a confirm
mov ah,prstr ; Output
mov dx,offset crlf ; a crlf
int dos
cmp flags.vtflg,0 ; emulating a terminal?
jne teln1 ; ne= yes, skip flashing message
call domsg ; Reassure user
teln1: mov al,0 ; initial flags
mov ttyact,1 ; say telnet is active
cmp flags.modflg,0 ; mode line enabled?
jne tel010 ; yes, go on
or al,modoff ; no, make sure it stays off

tel010: or al,havtt ; defaults (!)
test flags.debug,logses ; debug mode?
jz tel0 ; z = no, keep going
or al,trnctl ; yes, show control chars
tel0: cmp flags.vtflg,0 ; emulating a terminal?
je tel1 ; e = no
or al,emheath ; say emulating some kind of terminal
tel1: mov bx,portval
cmp [bx].ecoflg,0 ; echoing?
jz tel2
or al,lclecho
tel2: call getbaud ; pickup current baud rate for port
mov targ.flgs,al ; store flags
mov ah,flags.comflg ; COMs port identifier
mov targ.prt,ah ; Port 1 or 2, etc
mov ah,trans.escchr ; escape character
mov targ.escc,ah
mov ah,[bx].parflg ; parity flag
mov targ.parity,ah
mov ax,[bx].baud ; baud rate identifier
mov targ.baudb,al
xor ah,ah
test flags.capflg,logses ; select session logging flag bit
jz tel3 ; z = no logging
mov ah,capt ; set capture flag
tel3: or targ.flgs,ah

TEM: call serini ; init serial port
jnc tem0 ; nc = success
mov ttyact,0 ; say we are no longer active
jmp rskp ; and exit Connect mode

tem0: mov dx,offset crlf ; give user an indication that we are
mov ah,prstr ; entering terminal mode
int dos
mov ax,offset targ ; Point to terminal arguments
call term ; Call the main Terminal procedure
or targ.flgs,scrsam ; assume screen is the same
tem1: mov al,kbdflg ; get the char from Term, if any
mov kbdflg,0 ; clear the flag
cmp al,0 ; was there a char from Term?
jne intch2 ; ne = yes, else ask for one from kbd

intchar:call iseof ; stdin at eof?
jnc intch1 ; nc = not eof, get more
mov al,'C' ; use C when file is empty
jmp intchc ; to provide an exit
intch1: mov ah,coninq ; read keyboard, no echo
int dos ; get a char
cmp al,0 ; scan code indicator?
jne intch2 ; ne = no, ascii
mov ah,coninq ; read and discard scan code
int dos
jmp short intch1 ; try again
intch2: cmp al,' ' ; space?
je tem ; e = yes, ignore it
cmp al,cr ; check ^M (cr) against plain ascii M
je tem ; exit on cr
cmp al,trans.escchr ; Is it the escape char?
jne intch3 ; ne = no
mov ah,al
call outchr
nop
nop
nop
jmp tem ; Return, we are done here
intch3: push es
push ds
pop es
mov di,offset intclet ; command letters
mov cx,numlet ; quantity of them
cmp al,' ' ; control code?
jae intch3a ; ae = no
or al,40H ; convert control chars to printable
intch3a:cmp al,96 ; lower case?
jb intch3b ; b = no
and al,not (20h) ; move to upper case
intch3b:cld
repne scasb ; find the matching letter
pop es
jne intch4 ; ne = not found, beep and get another
dec di ; back up to letter
sub di,offset intclet ; get letter number
shl di,1 ; make it a word index
jmp intcjmp[di] ; dispatch to it
intch4: call beep ; say illegal character
jmp intchar

intchb: call sendbr ; 'B' send a break
jmp tem ; And return

intchc: mov ttyact,0 ; 'C' say we are no longer active
;;; call serrst ; reset serial port
jmp rskp ; and exit Connect mode

intchf: call dumpscr ; 'F' dump screen, use msy routine
jmp tem ; and return

intchh: call serhng ; 'H' hangup phone
call serrst ; turn off port
jmp tem

intchl: call sendbl ; 'L' send a long break
jmp tem

intchm: cmp flags.modflg,1 ; 'M' toggle mode line, enabled?
jne intchma ; ne = no, leave it alone
xor targ.flgs,modoff ; enabled, toggle its state
intchma:jmp tem ; and reconnect

intchp: push bx ; 'P' push to DOS
mov bx,portval
mov ah,byte ptr [bx].flowc ; get XOFF char, or null
pop bx
or ah,ah ; check for null (no flow control)
jz intchpa ; z = null, don't send one
call outchr ; send XOFF to host while we are away
nop
nop
nop
intchpa:call serrst ; turn off serial interrupts
call fpush ; try pushing
nop
nop
nop
mov dx,offset sttmsg ; say we have returned
mov ah,prstr
int dos
call serini ; init serial port again
jc intchc ; nc = failure
call ihostr ; XON the host (if using flow control)
jmp intchsb ; wait for a space

intchq: test targ.flgs,capt ; 'Q' suspend logging. Logging active?
jz intchq1 ; z = no
and targ.flgs,not capt ; stop capturing
intchq1:jmp tem ; and resume

intchr: test flags.capflg,logses ; 'R' resume logging. Can we capture?
jz intchr1 ; z = no
test targ.flgs,capt ; already capturing?
jnz intchr1 ; yes, can't toggle back on then
or targ.flgs,capt ; else turn flag on
intchr1:jmp tem ; and resume

intchs: call stat0 ; 'S' status, call stat0
call puthlp ; put help on screen
mov dx,offset sttmsg
mov ah,prstr
int dos
intchsa:call iseof ; is stdin at eof?
jnc intchsb ; nc = not eof, get more
jmp tem ; resume if EOF
intchsb:mov ah,coninq ; console input, no echo
int dos
cmp al,' ' ; space?
jne intchsa
and targ.flgs,not scrsam ; remember screen changed
jmp tem

intchu: mov ax,offset inthlp ; '?' get help message
call puthlp ; write help msg
mov dx,offset intprm
mov ah,prstr ; Print it
int dos
and targ.flgs,not scrsam ; remember screen changed
jmp intchar ; Get another char

intchn: mov ah,0 ; '0' send a null
call outchr
nop
nop
nop
jmp tem
TELNET ENDP
; Reassure user about connection to the host. Tell him what escape sequence
; to use to return and the communications port and baud; rate being used

DOMSG PROC NEAR
mov ah,prstr
mov dx,offset tmsg1
int dos
call escprt
mov ah,prstr
mov dx,offset tmsg3
int dos
ret
DOMSG ENDP

; print the escape character in readable format.

ESCPRT PROC NEAR
mov dl,trans.escchr
cmp dl,' '
jge escpr2
push dx
mov ah,prstr
mov dx,offset esctl
int dos
pop dx
add dl,040H ; Make it printable
escpr2: mov ah,conout
int dos
ret
ESCPRT ENDP


; Set parity for character in Register AL

dopar: push bx
mov bx,portval
mov bl,[bx].parflg ; get parity flag byte
cmp bl,parnon ; No parity?
je parret ; Just return
and al,07FH ; Strip parity. Same as Space parity
cmp bl,parspc ; Space parity?
je parret ; e = yes, then we are done here
cmp bl,parevn ; Even parity?
jne dopar0 ; ne = no
or al,al
jpe parret ; pe = even parity now
xor al,080H ; Make it even parity
jmp short parret
dopar0: cmp bl,parmrk ; Mark parity?
jne dopar1 ; ne = no
or al,080H ; Turn on the parity bit
jmp short parret
dopar1: cmp bl,parodd ; Odd parity?
or al,al
jpo parret ; Already odd, leave it
xor al,080H ; Make it odd parity
parret: pop bx
ret

cptchr proc near ; session capture routine, char in al
push di
mov di,capbp ; buffer pointer
mov byte ptr [di],al
inc capbp
pop di
dec caplft ; decrement chars remaining
jg cptch1 ; more room, forget this part
call cptdmp ; dump the info
cptch1: ret
cptchr endp

cptdmp proc near ; empty the capture buffer
push ax
push bx
push cx
push dx
mov bx,sloghnd ; get file handle
cmp bx,0 ; is file open?
jle cptdm1 ; le = no, skip it
mov cx,cptsiz ; original buffer size
sub cx,caplft ; minus number remaining
jl cptdm2 ; means error
jcxz cptdm1 ; z = nothing to do
mov dx,offset capbuf ; the capture routine buffer
mov ah,write2 ; write with filehandle
int dos ; write out the block
jc cptdm2 ; carry set means error
mov capbp,offset capbuf
mov caplft,cptsiz ; init buffer ptr & chrs left
jmp short cptdm1
cptdm2: and targ.flgs,not capt ; so please stop capturing
mov dx,offset erms23 ; tell user the bad news
mov ah,prstr
int dos
cptdm1: pop dx
pop cx
pop bx
pop ax
ret
cptdmp endp

pktcpt proc near ; packet log routine, char in al
push di
mov di,pktbp
mov [di],al ; store char in buffer
inc pktbp ; move pointer to next free byte
pop di
dec pktlft ; decrement chars remaining
jg pktcp1 ; more room, forget this part
call pktdmp ; dump the info
pktcp1: ret
pktcpt endp

pktdmp proc near ; empty the capture buffer
push ax
push bx
push cx
push dx
mov bx,ploghnd ; get file handle
cmp bx,0 ; is file open?
jle cptdm1 ; le = no, skip it
mov cx,cptsiz ; original buffer size
sub cx,pktlft ; minus number remaining
jl pktdm2 ; l means error
jcxz pktdm1 ; z = nothing to do
mov dx,offset pktbuf ; the capture routine buffer
mov ah,write2 ; write with filehandle
int dos ; write out the block
jc pktdm2 ; carry set means error
mov pktbp,offset pktbuf
mov pktlft,cptsiz ; init buffer ptr & chrs left
jmp short pktdm1
pktdm2: and targ.flgs,not capt ; so please stop capturing
mov dx,offset erms24 ; tell user the bad news
mov ah,prstr
int dos
call clscp4 ; close the packet log
pktdm1: pop dx
pop cx
pop bx
pop ax
ret
pktdmp endp

; CLOSE command

clscpt proc near
mov ah,cmkey
mov dx,offset clotab ; close table
mov bx,offset clohlp ; help
call comnd
jmp r
nop
mov tmp,bl
mov ah,cmcfm
call comnd
jmp r
mov bl,tmp
test flags.capflg,0FFH ; are any kinds active?
jz clscp1 ; z = no
cmp bl,logpkt+logses+logtrn ; close all?
je clscpi ; e = yes
cmp bl,logpkt ; just packet?
je clscp4
cmp bl,logses ; just session?
je clscp6
cmp bl,logtrn ; just session?
je clscp8
clscp1: mov dx,offset erms22 ; say none active
mov ah,prstr
int dos
jmp rskp
; CLSCPI called at Kermit exit
CLSCPI: call clscp4 ; close packet log
call clscp6 ; close session log
call clscp8 ; close transaction log
jmp rskp ; return success

clscp4: push bx ; PACKET LOG
mov bx,ploghnd ; packet log handle
cmp bx,0 ; is it open?
jle clscp5 ; e = no
call pktdmp ; dump buffer
mov ah,close2
int dos
mov ah,prstr
mov dx,offset clpktlog ; tell what we are doing
int dos
clscp5: mov ploghnd,-1 ; say handle is invalid
pop bx
and flags.capflg,not logpkt ; say this log is closed
ret

clscp6: push bx ; SESSION LOG
mov bx,sloghnd ; session log handle
cmp bx,0 ; is it open?
jle clscp7 ; e = no
call cptdmp ; dump buffer
mov ah,close2
int dos
mov ah,prstr
mov dx,offset clseslog ; tell what we are doing
int dos
clscp7: mov sloghnd,-1 ; say handle is invalid
pop bx
and flags.capflg,not logses ; say this log is closed
ret

clscp8: push bx ; TRANSACTION LOG
mov bx,tloghnd ; transaction log handle
cmp bx,0 ; is it open?
jle clscp9 ; e = no
mov ah,close2
int dos
mov ah,prstr
mov dx,offset cltrnlog ; tell what we are doing
int dos
clscp9: mov tloghnd,-1 ; say handle is invalid
pop bx
and flags.capflg,not logtrn ; say this log is closed
ret
clscpt endp

; worker: copy line from si to di, first removing trailing spaces, second
; parsing out curly braced strings, then third converting \{b##} in strings
; to binary numbers. Returns carry set if error; else carry clear, with byte
; count in cx. Braces are optional but must occur in pairs.
; Items which cannot be converted to legal numbers are copied verbatium
; to the output string (ex: \{c} is copied as \{c} but \{x0d} is hex 0dh).
cnvlin proc near
push ax
push si ; source ptr
push di ; destination ptr
push es ; end of save regs
push ds ; move ds into es
pop es ; use datas segment for es:di
call cnvstr ; trim trailing, parse curly braces
xor cx,cx ; initialize returned byte count
cnvln1: cmp byte ptr [si],0 ; at end of string?
je cnvln2 ; e = yes, exit
call katoi ; read char, convert ascii to binary
cld
stosb ; save the char
inc cx ; and count it
or ah,ah ; is returned number > 255?
jz cnvln1 ; z = no, do more chars
push ax
stosb ; save high order byte next
pop ax
inc cx
jmp short cnvln1 ; do more chars
cnvln2: mov byte ptr [di],0 ; plant terminator
clc ; clear c bit, success
cnvlnx: pop es ; restore regs
pop di ; destination ptr
pop si ; source ptr
pop ax
ret
cnvlin endp

; Convert string by first remove trailing spaces and then removing surrounding
; curly brace delimiter pair. Converts text in place.
; Enter with source ptr in si.
; Preserves all registers, uses byte tmp. 9 Oct 1987 [jrd]
;
cnvstr proc near
push ax
push cx
push dx
push si ; save start of source string
push di
push es
; 1. Trim trailing spaces
mov dx,si ; source address
call strlen ; get current length to cx
jcxz cnvst4 ; z = nothing there
mov di,si ; set di to source address
add di,cx ; start at end of string
dec di ; ignore terminator
mov al,spc ; scan while spaces
push ds
pop es ; set es to datas segment
std ; search backward
repe scasb ; scan off trailing spaces
mov byte ptr [di+2],0 ; terminate string after last text
cld
mov di,si ; set destination address to source
; 2. Parse off curly brace delimiters
cmp byte ptr [si],braceop ; opening brace?
jne cnvst4 ; ne = no, ignore brace-matching code
inc si ; skip opening brace
mov dl,braceop ; opening brace (we count them up)
mov dh,bracecl ; closing brace (we count them down)
mov tmp,1 ; we are at brace level 1
cnvst1: cld ; search forward
lodsb ; read a string char
stosb ; store char (skips opening brace)
cmp al,0 ; at end of string?
je cnvst4 ; e = yes, we are done
cmp al,dl ; an opening brace?
jne cnvst2 ; ne = no
inc tmp ; yes, increment brace level
jmp short cnvst1 ; and continue scanning

cnvst2: cmp al,dh ; closing brace?
jne cnvst1 ; ne = no, continue scanning
dec tmp ; yes, decrement brace level
cmp byte ptr [si],0 ; have we just read the last char?
jne cnvst3 ; no, continue scanning
mov tmp,0 ; yes, this is the closing brace
cnvst3: cmp tmp,0 ; at level 0?
jne cnvst1 ; ne = no, #opening > #closing braces
mov byte ptr [di-1],0 ; plant terminator on closing brace

cnvst4: pop es ; recover original registers
pop di
pop si
pop dx
pop cx
pop ax
ret
cnvstr endp

; Convert ascii strings of the form "\{bnnn}" to a binary word in ax.
; The braces are optional but must occur in pairs. Numeric base indicator "b"
; is O or o or X or x or D or d or missing, for octal, hex, or decimal (def).
; Enter with si pointing at "\".
; Returns binary value in ax with carry clear and si to right of "}" or at
; terminating non-numeric char if successful; otherwise, a failure,
; return carry set with si = entry value + 1 and first read char in al.

katoi proc near
cld
lodsb ; get first char
xor ah,ah ; clear high order field
push cx ; save working reg
push si ; save entry si+1
push bx
push ax ; save read char
KATOI1: cmp al,0 ; end of text? ENTRY POINT FOR ATOI
je katoi1a ; e = yes, exit failure
cmp al,'\' ; escape char?
je katoi1b ; e = yes
katoi1a:jmp katoix ; common jump point to exit failure
katoi1b:lodsb ; get next char, maybe brace
cmp al,0 ; premature end?
je katoi1a ; e = yes, exit failure
xor bx,bx ; no conv yet, assume no opening brace
cmp al,braceop ; opening brace?
jne katoi2 ; ne = no, have number or base
mov bl,bracecl ; remember a closing brace is needed
lodsb ; get number base, if any
katoi2: xor cx,cx ; temporary place for binary value
mov nbase,10 ; assume decimal numbers
cmp al,0 ; premature end?
je katoix ; e = yes, exit failure
cmp al,'a' ; lower case?
jb katoi3 ; b = no
cmp al,'z' ; in range of lower case?
ja katoi3 ; a = no
and al,5fh ; map to upper case
katoi3: cmp al,'O' ; octal?
jne katoi4 ; ne = no
mov nbase,8 ; set number base
jmp short katoi6
katoi4: cmp al,'X' ; hex?
jne katoi5 ; ne = no
mov nbase,16
jmp short katoi6
katoi5: cmp al,'D' ; decimal?
jne katoi7 ; ne = no base char, assume decimal
mov nbase,10
katoi6: lodsb ; get a digit
katoi7: cmp al,0 ; premature end?
je katoi8a ; e = yes, use it as a normal end
cmp al,bl ; closing brace?
je katoi9 ; e = yes
call cnvdig ; convert ascii to binary digit
jc katoi8 ; c = cannot convert
inc bh ; say we did a successful conversion
xor ah,ah ; clear high order value
push ax ; save this byte's value
xchg ax,cx ; put binary summation in ax
mul nbase ; scale up current sum
xchg ax,cx ; put binary back in cx
pop ax ; recover binary digit
add cx,ax ; form running sum
jc katoix ; c = overflow error, exit
cmp dx,0 ; overflow?
jne katoix ; ne = yes, exit with error
jmp short katoi6 ; get more

katoi8: cmp bl,0 ; closing brace needed?
jne katoix ; ne = yes, but not found
katoi8a:dec si ; backup to reread terminator
katoi9: cmp bh,0 ; did we do any conversion?
je katoix ; e = no, exit failure
pop ax ; throw away old saved ax
pop bx ; restore bx
pop ax ; throw away starting si, keep current
mov ax,cx ; return final value in ax
pop cx ; restore old cx
clc ; clear carry for success
ret
katoix: pop ax ; restore first read al
pop bx
pop si ; restore start value + 1
pop cx ; restore old cx
stc ; set carry for failure
ret
katoi endp

cnvdig proc near ; convert ascii code in al to binary
push cx ; return carry set if cannot
push es ; nbase has numeric base
push di
push ax
cmp al,'a' ; lower case?
jb cnvdig1 ; b = no
cmp al,'f' ; highest hex digit
ja cnvdigx ; a = illegal symbol
sub al,'a'-'A' ; convert 'a' to 'f' to upper case
cnvdig1:mov di,offset numset ; set of legal number symbols
mov cx,nbase ; number of legal symbols in this base
cmp cx,cx ; preset z flag
push ds
pop es ; point es at data segment
cld ; scan forward
repne scasb ; find character in set
jne cnvdigx ; ne = not found
cnvdig2:inc cx ; offset auto-dec of repne scasb above
sub cx,nbase ; counted off minus length
neg cx ; two's complement = final value
pop ax ; saved ax
mov ax,cx ; return binary in al
clc ; c clear for success
jmp short cnvdixx ; exit
cnvdigx:stc ; c set for failure
pop ax
cnvdixx:pop di
pop es
pop cx
ret
cnvdig endp

decout proc near ; display decimal number in ax
push ax
push cx
push dx
mov cx,10 ; set the numeric base
call valout ; convert and output value
pop dx
pop cx
pop ax
ret
decout endp

valout proc near ; output number in ax using base in cx
; corrupts ax and dx
xor dx,dx ; clear high word of numerator
div cx ; (ax / cx), remainder = dx, quotient = ax
push dx ; save remainder for outputting later
or ax,ax ; any quotient left?
jz valout1 ; z = no
call valout ; yes, recurse
valout1:pop dx ; get remainder
add dl,'0' ; make digit printable
cmp dl,'9' ; above 9?
jbe valout2 ; be = no
add dl,'A'-1-'9' ; use 'A'--'F' for values above 9
valout2:mov ah,conout
int dos
ret
valout endp

; Convert input in buffer pointed to by SI to real number which is returned
; in AX. Enter with string size in AH.
; Return on failure, return skip on success. Revised by [jrd]
ATOI PROC NEAR
mov bx,0 ; high order of this stays 0
mov tmp,0 ; No input yet
mov cl,ah ; Number of chars of input
mov ch,0 ; size of string
mov ax,0 ; init sum
cld
atoi0: jcxz atoi4 ; Fail on no input
lodsb ; get an input char
dec cx ; count number remaining
cmp al,' ' ; leading space?
je atoi0 ; e = yes, skip it
cmp al,',' ; comma separator?
je atoi0 ; e = yes, skip it
dec si ; back up source pointer for reread below
inc cx ; and readjust byte counter
mov ax,0 ; clear sum
atoi1: push ax ; save sum
lodsb ; read a byte into al
mov bl,al ; put it into bl
pop ax ; regain sum
cmp bl,'9' ; check range for '0' to '9'
ja atoi2 ; above '9'
cmp bl,'0'
jb atoi2 ; below '0'
sub bl,'0' ; take away ascii bias
mul ten ; sum * 10. dx = high, ax = low
add ax,bx ; add current value
mov tmp,1 ; say have sum being computed
loop atoi1
inc si ; inc for dec below
atoi2: dec si ; point at terminator
cmp tmp,0 ; were any digits discovered?
je atoi4 ; e = no, fail
atoi3: jmp rskp ; success exit, sum is in ax
atoi4: mov dx,offset erms25 ; Input must be numeric
ret
ATOI ENDP

; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.

RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP

; Jumping here is the same as a ret

R PROC NEAR
ret
R ENDP

code ends
end


  3 Responses to “Category : Assembly Language Source Code
Archive   : KRMTSRCE.ZIP
Filename : MSSTER.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/