🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.asm.x86
Article #121

Re: Frustrating

#121
From: David Lindauer
Date: Thu, 29 Oct 1998 00:00
313 lines
9676 bytes
--------------D848763A36575765A4DDCF79
Content-type: text/plain; charset="us-ascii"

hi,
    find attached an example for TASM that will BOTH uppercase strings,
AND do additions/subtractions.  You can find more working demos on my
web site, but, they are probably mostly more advanced than you are ready for
at this point.  Have you checked out the 'snippets' collection (see FAQ).  I
have never looked at it but it is supposed to have lots of example code...



--
---------------------------------------------------------------
David Lindauer    mailto:camille@bluegrass.net     ICQ: 8699592

http://www.ladsoft.com                                     (computer page)
http://www.geocities.com/Area51/Station/5196/index.html    (home page)
http://www.geocities.com/Area51/Station/5196/ttc.html      (tao te ching)


--------------D848763A36575765A4DDCF79
Content-type: text/plain; charset="us-ascii"; name="Q.asm"
Content-transfer-encoding: 7bit
Content-Disposition: inline; filename="Q.asm"

;
; example program
;
; (public domain)
;
; David Lindauer, LADSoft, October 1998
;
; it prompts you for input
; if the first character is a letter, it will convert the string to uppercase
; and display it
;
; otherwise it will prompt for a second number,
; then it will multiply the two numbers and add them and show the
; results
;
; when you want to exit the program, just hit return without typing anything
; on the line
;
; note you CAN do the input and output with DOS calls 0ah and 09h, I just
; never use them because I always find it easier to just roll my own I/O
; than try to remember the strange protocols DOS uses.
;
	.model small
	.stack
	.data
banner	db	"My test program"	; always have a banner
crlf	db	13,10,0			; this is BOTH part of the banner
					; AND a seperate thing to move to
					; the next line on the screen
prompt2 db	"2"    			; this is the second prompt
					; since it doesn't have a terminator
					; this string is prefixed to the next
					; one during displays
prompt	db	"-> ",0			; the main prompt
	.data?
inputbuffer db	256 DUP (?)		; an input buffer.  We make it big
					; so the odds are they won't overrun
					; it, although they can if they want
					; in which case the program will
					; crash.  A good program would
					; check and not allow this to happen.
outputbuffer db	256 DUP (?)		; output buffer.  Must be as big as
					; the input buffer.
	.code
;
; routine to conver an ASCII string to uppercase
; A-Z = 041h -05Ah whereas a-z = 061h -07ah
; in: SI points to (null terminated) string
;     di points to a new buffer
; out: string is copied, with the case change
;
uppercase PROC
	push	di			; save regs
	push	si
ucl:
	lodsb				; get a character
	or	al,al			; bail out when we hit the
					; null terminator
	jz	ucx			;
	cmp	al,'a'			; see if it is a lowercase character
	jc	ucnone
	cmp	al,'z'
	ja	ucnone
	and	al,not 20h		; yes, make it uppercase
ucnone:
	stosb				; save the new character
	jmp	ucl			; and loop
ucx:
	stosb				; exit point, store the null
					; terminator
	pop	si			; and restore regs
	pop	di
	ret
uppercase ENDP
;
; reads a number from a buffer, returns it in AX
;
; in: si points at the buffer
; out: ax = value
;
getnum	PROC
	
	push	bx			; save regs
	push	cx
	push	dx
	push	si
	sub	cx,cx			; CX = answer = 0
	mov	bx,10			; base 10
gnl:
 	lodsb				; get char
	sub	ah,ah			; AH=0 for the later add
	sub	al,'0'			; is it a digit
	jc	gnx			; no, bail out with the answer
	cmp	al,10			; is it a digit?
	jae	gnx			; no bail out with the answer
	xchg	ax,cx			; else AX = old result, cx = new result
	mul	bx			; multiply old result *10
	add	cx,ax			; and add new result
	jmp	gnl			; ghen go get another char
gnx:
	mov	ax,cx			; move result to AX
	pop	si			; then pop regs and return
	pop	dx
	pop	cx
	pop	bx
	ret
getnum  ENDP
;
; puts the number in AX into the buffer at DI, with a null terminator
;
; in: ax = number
;     di = buffer
;
putnum	PROC
	push	dx			; save regs.  Note we are NOT
	push	cx			; saving DI to make it easy
	push	bx			; toconcatenate two answers together
	mov	bx,10			; BX = base
	sub	cx,cx			; CX = number of digits = 0
pnl1:
	sub	dx,dx			; for a DIV we must clear the MSW
	div	bx			; divide by 10
	add	dl,'0'			; remainder in DL, make it ASCII
	push	dx			; and save it on the stack
	inc	cx			; update the digit count
	or	ax,ax			; is the quotient 0?
	jnz	pnl1			; no, get another digit
					; now we have all digits on the stack
					; in such a way that they will be
					; popped in left-to-right order
pnl2:
	pop	ax			; get a digit
	stosb				; save it in output buffer
	loop	pnl2			; loop till done
	sub	al,al			; store a null terminator
	stosb
	pop	bx			; pop registers
	pop	cx
	pop	dx
	ret
putnum	ENDP
;
; readstring
;
; in DI = buffer.  
; out: buffer holds null-terminated string
;
readstring PROC
	push	di			; save regs
	push	bx
	mov	bx,di			; bx = start of buffer so that
					; when we do a backspace we
					; won't go past the beginning
rsl:
	sub	ah,ah			; BIOS function to wait for a key
	int	16h			; and do it
	cmp	al,13			; is it CR?
	jz	rsx			; yes, exit
	cmp	al,8			; else is it one of the backspace
					; variants?
	jz	bkspc			; yes- do it
	cmp	al,07fh			; the other?
	jz	bkspc			; yes- do it
	stosb				; else save the char
					; this is where we would check for
					; overrun of the inputbuffer
	mov	dl,al			; and use dos function 2 to echo it
	mov	ah,2
	int	21h
	jmp	rsl			; loop for next char
; backspace routine
bkspc:
	cmp	di,bx			; at the beginning of text?
	jz	rsl			; if so no backspace
	dec	di			; else discard the last input char
	mov	ah,2			; and print the sequence
	mov	dl,8			;backspace
	int	21h
	mov	ah,2
	mov	dl,' '			;space
	int	21h
	mov	ah,2
	mov	dl,8			;backspace
	int	21h			; in order to discard the character
	jmp	rsl			; from the screen and move the cursor
					; back
rsx:
	sub	al,al			; end of input, so store a null
	stosb				; terminator
	pop	bx			; restore regs
	pop	di
	ret
readstring ENDP
;
; in: SI = null-terminated buffer
; out: buffer placed on screen
;
writestring PROC
	push	si			; save regs
wsl:
	lodsb				; get a char
	or	al,al			; null terminator?
	jz	wsx			; yes, exit
	mov	dl,al			; else put the char out
	mov	ah,2			; with DOS function 2
	int	21h
	jmp	wsl			; loop to next char
wsx:
	pop	si			; restore regs
	ret
writestring ENDP
;
; main program
;

start PROC
	mov	ax,DGROUP		; necessary EXE initialization
	mov	ds,ax
	mov	es,ax

	mov	si,offset banner	;tell them we are here
	call	writestring
; program main loop starts here
sl:
	mov	si,offset prompt	; issue a prompt
	call	writestring
	mov	di,offset inputbuffer	; now read input
	call	readstring
	mov	si,offset crlf		; then advance to the next line
	call	writestring
	xchg	si,di			; now si = pointer to input string 
	test	byte ptr [si],-1	; see if first char is null terminator
	jnz	nox			; if not continue
	mov	ax,4c00h		; if so bail to DOS
	int	21h
nox:
	cmp	byte ptr [si],'9'	; now see if the first char is possibly
					; a number
	ja	touc			; greater than a number, go uppercase it
	call	getnum			; else get the number (si = buf ptr)
	push	ax			; save the number on the stack
	mov	si,offset prompt2	; prompt for another number
	call	writestring
	mov	di,offset inputbuffer	; read it in
	call	readstring
	mov	si,offset crlf		; advance to next line
	call	writestring
	xchg	si,di			; si = input buffer
	call	getnum			; read the second number
	mov	bx,ax			; put it in bx
	pop	ax			; restore the first number
	push	ax			; but we are about to wipe it, save it again
	mul	bx			; now multiply the two numbers
	mov	di,offset outputbuffer	; and stick the result in the output buffer
	call	putnum			;
	dec	di			; we are going to append the easy way,
					; by overriting the null terminator
					; for the first number
	mov	al,","			; so store a comma
	stosb
	pop	ax			; restore the first number
	add	ax,bx                   ; add them
	call	putnum			; and append the result
	mov	si,offset outputbuffer	; now write it to the screen
	call	writestring
	mov	si,offset crlf		; advance to the next line
	call	writestring
	jmp	sl			; and go get more input
;
; come here to uppercase a string
;
touc:
	mov	di,offset outputbuffer	; load up output buffer,
					; si already = input buffer
	call	uppercase		; convert to uppercase
	xchg	si,di			; si = output buffer
	call	writestring		; write the result
	mov	si,offset crlf		; advance to the next line
	call	writestring
	jmp	sl			; and go get more input.

start ENDP
	end start


	
--------------D848763A36575765A4DDCF79--
Technical Details
Message-ID: <71aqss$lrk$1@autumn.news.rcn.net>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <7177gc$ms7$1@autumn.news.rcn.net>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: feaef,9649ddaf83649d3e
X-Google-Attributes: gidfeaef,public
X-Google-Thread: 114917,9649ddaf83649d3e
X-Google-Attributes: gid114917,public
From: David Lindauer <camille@bluegrass.net>
Subject: Re: Frustrating
Date: 1998/10/29
Message-ID: <71aqss$lrk$1@autumn.news.rcn.net>
X-Deja-AN: 406468235
Cache-Post-Path: news.bluegrass.net!unknown@dial28.pm3.bluegrass.net
Approved: <johnfine@erols.com>
References: <7177gc$ms7$1@autumn.news.rcn.net>
Content-Type: multipart/mixed; boundary="------------D848763A36575765A4DDCF79"
X-Mozilla-Status: 0801
X-Complaints-To: abuse@rcn.com
X-Trace: ze8P0BsDpkcUUDVmmyhs1RVR2HDj19bDl/vGypaLRXw=
Organization: Bluegrass Net
X-Cache: nntpcache 2.3.2 (see http://www.nntpcache.org/)
Mime-Version: 1.0
NNTP-Posting-Date: 29 Oct 1998 22:40:28 GMT
Newsgroups: comp.lang.asm.x86,borland.public.tasm