home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
msk230s2.zip
/
MSSTER.ASM
next >
Wrap
Assembly Source File
|
1988-02-12
|
35KB
|
751 lines
NAME msster
; File MSSTER.ASM
; Last edit: 1 Jan 1988
; 1 Jan 1988 version 2.30
; 24 Dec 1987 Speed up Status display. [jrd]
; 9 Oct 1987 Add cnvstr routine for curly braced strings. [jrd]
; 2 Oct 1987 Make TARG structure global, clean out old Set Key material. [jrd]
; 15 July 1987 Fix xon/xoff bug when Pushing to DOS. Tnx to Mark Zinzow. [jrd]
; 7 July 1986 Remove prkey routine. [jrd]
; 2 July 1987 Slight modification to cnvlin permitting \0 in text.
; Remove Control-Z at end of capture file. [jrd]
; 22 June 1987 Add XOFF host when Pushing to DOS, from Paul Amaranth. [jrdd
; 13 June 1987 Use decimal printing for showing Macros. Move many number
; conversion routines here from mssset.asm so latter will assemble under
; MASM 1.25. [jrd]
; 19 April 1987 Add global byte pcnet for support of local area nets. [jrd]
; Add global byte ttyact to indicate, by non-zero, that Connect mode
; is active; mostly for system dependent i/o modules. [jrd]
; 5 April 1987 Keep Domsg message on screen for 1 second minimum.
; Add L (Long Break) and H (Hangup) to keyboard operations [jrd]
; 24 March 1987 Add logging details for separate packet and session. [jrd]
; 9 Jan 1987 Add hooks for keyboard translator in system dependent modules.
; Byte kbdflg, defined here, receives a char from the sys dep routines
; instead of from keyboard during breaks from Connect mode. Word Shkadr
; is defined here as zero. If it is set to the address of a replacement
; Show Key procedure then the regular code here is bypassed. [jrd]
; 11 Dec 1986 Turn of serial port when Pushing to DOS. Add char transfer
; from keyboard translator. [jrd]
; 19 Oct 1986 Output cr/lf before status display. [rjd]
; 1 Oct 1986 Version 2.29a
; [2.29] code frozen on 6 May 1986 [jrd]
Public clscpt, defkey, inicpt, clscpi
public dopar, shokey, cptchr, targ
public kbdflg, shkadr, telnet, pcnet, 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
extrn cptio:byte
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 capture file open$' ;[jd]
erms23 db cr,lf,'?Error writing capture file, suspending capture'
db cr,lf,'$'
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> $'
CAPBUF DB cptsiz DUP (?)
CAPBP DW ?
CAPLFT dw ?
scntab dw 0
deftab dw 0
sttmsg db cr,lf,'Type space to continue ...$'
shkmsg db cr,lf,'Press key: $'
kbdflg db 0 ; non-zero means char here from Term
pcnet db 0 ; Network is functioning properly
ttyact db 0 ; Connect mode active, if non-zero
shkadr dw 0 ; offset of replacement Show Key command
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
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:
; mov ah,cmcfm ; confirm with carriage return
; call comnd
; jmp r ; uh oh...
; mov dx,offset shkmsg
; mov ah,prstr
; int dos ; print a prompt for it
; mov ax,offset targ ; give it terminal arg block.
; call showkey ; show them the key definition
jmp rskp ; and return
shokey 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.wrpflg,0 ; wrap mode?
jz tel011 ; no, keep going
or al,lnwrap
tel011: cmp flags.vtflg,0 ; emulation a terminal?
jz tel1
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
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
cmp flags.comflg,'N' ; Network port?
jne tem0 ; ne = no
cmp pcnet,1 ; did net intialize?
ja tem0 ; a=yes (0=no net,1=net/no session,2=session)
mov kbdflg,'C' ; no, say Close the connection
jmp tem2 ; do it
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 flags.wrpflg,0 ; assume not wrap mode
test targ.flgs,lnwrap ; in wrap mode?
jz tem2 ; no, continue
mov flags.wrpflg,1
tem2:
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 intch0 ; ne = yes, else ask for one from kbd
intchr: mov ah,dconio ; Direct console I/O.
mov dl,0FFH ; Input.
int dos ; Get a char.
jz intchr ; no char, keep looking
intch0:
mov ah,al
cmp ah,' ' ; space - ignore it
je tem
mov bh,ah ; Save the actual char.
and ah,not ('a'-'A') ; Convert to upper case.
or ah,40H ; convert ctl-char to actual char.
cmp ah,'C' ; Is it close?
jne intch1
call serrst ; reset serial port
mov ttyact,0 ; say we are no longer active
jmp rskp ; and return
intch1: cmp ah,'S' ; Is it status?
jne intch2 ; ne = no
call stat0 ; If so, call stat0.
call puthlp ; put help on screen
mov dx,offset sttmsg
mov ah,prstr
int dos
intch1a:mov ah,coninq ; console input, no echo
int dos
cmp al,' ' ; space?
jne intch1a
and targ.flgs,not scrsam ; remember screen changed.
jmp tem
intch2: cmp ah,'B' ; Send a break?
jne intch3 ; No
call sendbr ; Yes, so send a break
jmp tem ; And return
intch3: cmp ah,'M' ; mode line?
jne intch4
cmp bh,cr ; check ^M (cr) against plain ascii M
je intch3a ; exit on cr
cmp flags.modflg,1 ; mode line enabled?
jne intch3a ; ne = no, leave it alone
xor targ.flgs,modoff ; enabled, toggle its state
intch3a:jmp tem ; and reconnect
intch4: cmp ah,'F' ; Dump screen to filespec?
jne intch4a ; ne = no
call dumpscr ; call global proc in MSX or MSY
jmp tem ; and return
intch4a:cmp bh,'?' ; Is it help?
jne intch5 ; If not, go to the next check.
mov ax,offset inthlp ; get the address of the 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 intchr ; Get another char.
intch5: cmp bh,trans.escchr ; Is it the escape char?
jne intch7 ; ne = no
intch6: mov ah,al
call outchr
nop
nop
nop
jmp tem ; Return, we are done here.
intch7: cmp ah,'Q' ; 'Q' maybe want to stop logging?
jne intch8
test targ.flgs,capt ; not capturing, can't do this
jz intc11
and targ.flgs,not capt ; stop capturing
jmp tem ; and resume
intch8: cmp ah,'R' ; maybe resume?
jne intch9 ; no, keep going
test flags.capflg,logses ; can we capture?
jz intc11 ; no, forget it
test targ.flgs,capt ; already capturing?
jnz intc11 ; yes, can't toggle back on then
or targ.flgs,capt ; else turn flag on
jmp tem ; and resume
intch9: cmp bh,'0' ; perhaps want a null (note original chr in bh)
jne intc10
mov ah,0
call outchr
nop
nop
nop
jmp tem
intc10: cmp ah,'P' ; maybe want to push?
jne intc11 ; no, go on
push bx ; send XOFF, if possible, to hold host
mov bx,portval ; from Paul Amaranth
mov ah,byte ptr [bx].flowc ; get XOFF char, or null
pop bx
or ah,ah ; check for null (no flow control)
jz intch10a ; z = null, don't send one
call outchr ; send XOFF to host while we are away
nop
nop
nop
intch10a:call serrst ; turn off serial interrupts
call fpush ; try pushing
nop
nop
nop
mov dx,offset sttmsg
mov ah,prstr
int dos
call serini ; init serial port again
call ihostr ; XON the host (if using flow control)
jmp intch1a ; wait for space
intc11: cmp ah,'L' ; 'L', send a long Break?
jne intc12 ; ne = no
call sendbl ; send a long one
jmp tem
intc12: cmp ah,'H' ; 'H', hangup the phone
jne intc13 ; ne = no
call serhng
call serrst ; turn off port
jmp tem
intc13: call beep ; say illegal character
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
inicpt proc near
mov capbp,offset capbuf
mov caplft,cptsiz ; init buffer ptr & chrs left
ret ; and return
inicpt endp
cptchr proc near ; capture routine, char in al
push di
mov di,capbp
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
call inicpt ; re-init ptrs.
cptch1: ret ; and return
cptchr endp
cptdmp proc near ; empty the capture buffer
push ax
push bx
push cx
push dx
mov dx,offset capbuf ; the capture routine buffer
mov bx,cptio.handle ; get file handle
mov cx,cptsiz ; original buffer size
sub cx,caplft ; minus number remaining
jl cptdm2 ; means error
mov ah,write2 ; write with filehandle
int dos ; write out the block
jnc cptdm1 ; carry set means error
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
clscpt proc near
test flags.capflg,0FFH ; doing capture
jnz clscp1 ; yes, go ahead
mov dx,offset erms22
mov ah,prstr
int dos
jmp rskp
clscp1: mov ah,cmcfm
call comnd
jmp r
clscpi: mov ax,caplft
cmp ax,cptsiz ; is buffer empty?
je clscp2 ; yes, forget this stuff
call cptdmp ; dump buffer (preserves registers)
clscp2: mov ah,close2 ; DOS 2.0 close
push bx
mov bx,cptio.handle ; file handle
int dos ; close up file
pop bx
mov flags.capflg,logoff ; no longer capturing...
jmp rskp ; and return
clscpt endp
; enter with ax/scan code to define, si/ pointer to definition, cx/ length
; of definition. Defines it in definition table.
defkey proc near
ret
defkey 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?
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
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 AX.
; 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,';' ; start of comment?
jne atoi0a ; ne = no
dec si ; backup to semicolon
mov byte ptr [si],0 ; plant terminator
xor cx,cx ; clear bytes remaining field
jmp atoi4 ; and exit
atoi0a: cmp al,'0' ; got punctuation?
jb atoi0 ; e = yes, keep scanning
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 ; No so fail
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