home *** CD-ROM | disk | FTP | other *** search
- NAME STOBIN
- TITLE Motorola S-record to Binary Translator
- PAGE 58,110 ;58 printed lines per page, 110 columns/page
- ;in assembler listings
-
- ;This program translates files from the Motorola S-record format (output by
- ;motorola's freeware cross assemblers for Motorola microprocessor/microcomputer
- ;chips) into binary files (the real code and data for the chip). The Motorola
- ;S-record format consists of lines of ASCII characters. Each line starts with
- ;an S, followed by a digit which seems to indicate something about the contents
- ;of the line (1 for regular code and data, 9 for last line, which doesn't
- ;contain code or data?). Next, two digits give the hexadicimal number of
- ;program code/data bytes represented on the line + 3. Then, 4 digits give the
- ;hexadecimal address of the first program code/data byte represented on the
- ;line. Then, a string of digits gives the hexadecimal values of program
- ;code/data bytes in ascending address sequence (2 digits per byte). Finally,
- ;two digits give some sort of housekeeping data and these are followed by a line
- ;feed and a carriage return to get to the next line.
-
- ;Procedures: SCRCLR, KEYSTRNG, KEYNUM, ASCTOHEX, GETKEY, DISPCHAR, DISPMSG
-
-
- DATA1 SEGMENT 'DATA'
- ;BUFFERS
- BUFF1 DB 64,65 DUP(0) ;filename input buffer. first byte gives 1+max.
- ;# of input characters. size set to 3 more than
- ;max # of input characters, as required by
- ;KEYSTRNG. Max. 63 characters is the length
- ;acceptable by DOS for filespec's (not counting
- ;the ending null, which KEYSTRNG will supply)
- ;VARIABLES
- INFILE DB 64 DUP(?) ;input file name
- INHNDLE DW ? ;input file handle
- OUTFILE DB 68 DUP(?) ;output file name
- OUTHNDLE DW ? ;output file handle
- DEVSIZE DW ? ;size of destination memory device
- IMAGESEG DW ? ;segment of memory image area
- INSIZE DW ? ;size of input file
- INSEG DW ? ;segment of input file area
- OUTEXT DB 5,".BIN",00H ;extension for output filename in LSTRING
- ;format with ending null
- NUMFILL DB ? ;fill value for unused memory locations
- LINELEN DB ? ;number of bytes represented on an input file
- ;line
- ;MESSAGES
- FILEPMT DB 0DH,0AH,0AH,"Please enter an input file name, or press"
- DB " <Ctrl-C> to quit.",0DH,0AH,"$"
- NXTPMT DB 0DH,0AH,0AH,"Please enter the next input file name, or"
- DB " just press Enter to quit.",0DH,0AH,"$"
- SIZEPMT DB 0DH,0AH,0AH,"What is the capacity (in bytes) of the "
- DB "((E)E)PROM you will transfer this program"
- DB "to? (or press Q to quit)",0DH,0AH,"$"
- FILLPMT DB 0DH,0AH,0AH,"Shall I fill unused locations with ones or"
- DB " zeroes? (1/0)",0DH,0AH,"$"
- ADJMSG DB 0DH,0AH,0AH,"Memory reallocation error. If you do not"
- DB 0DH,0AH,0AH,"reboot your computer now, it may crash."
- DB 0DH,0AH,"$"
- INFLMSG DB 0DH,0AH,0AH,"Attempt to open input file failed.",0DH,0AH,"$"
- OUTFLMSG DB 0DH,0AH,0AH,"Attempt to create output file failed.",0DH,0AH
- DB "$"
- WGVERMSG DB 0DH,0AH,0AH,"This program requires DOS version 3.00 or"
- DB " greater, and that's not what you're"
- DB 0DH,0AH,"using right now.",0AH,0DH,"$"
- BADSZMSG DB 0DH,0AH,0AH,"The size you entered was 0 or too large.",0DH
- DB 0AH,"$"
- NOMEMMSG DB 0DH,0AH,0AH,"Insufficient available memory.",0DH,0AH,"$"
- NOSZMSG DB 0DH,0AH,0AH,"Unable to determine input file size.",0DH
- DB 0AH,"$"
- INTOOBIG DB 0DH,0AH,0AH,"Input file is too large.",0DH,0AH,"$"
- CANTREAD DB 0DH,0AH,0AH,"Can't read input file.",0DH,0AH,"$"
- SIZERR DB 0DH,0AH,0AH,"Warning: wrong number of bytes read from"
- DB " input file.",0DH,0AH,"$"
- TRERRMSG DB 0DH,0AH,0AH,"Input file doesn't follow expected format;"
- DB " file ignored.",0AH,0DH,"$"
- SAVERR DB 0DH,0AH,0AH,"Attempt to open output file failed.",0DH,0AH
- DB "$"
- WRITERR DB 0DH,0AH,0AH,"Error writing to output file.",0DH,0AH,"$"
- ;LOOKUP TABLES
- LINPSCRN DB 25,25,25,25,0,0,0,25,0,0,0,0,0,0,0,0,0
- DATA1 ENDS
-
-
- STSEG SEGMENT STACK 'STACK'
- DB 80H DUP(0)
- STSEG ENDS
-
-
- CODE1 SEGMENT 'CODE'
- ASSUME CS:CODE1, DS:DATA1, SS:STSEG
-
- ;INITIALIZE DS AND SS
- START: MOV AX,DATA1 ;Obtain DATA1 segment address
- MOV DS,AX ;and put it in DS
- MOV AX,STSEG ;Obtain STSEG segment address
- MOV SS,AX ;and put it in SS.
-
- ;MAIN PROGRAM
-
- ;SHRINK MEMORY ALLOCATION
- MOV AX,ZZZZZZZZ ;Get segment address of dummy final segment
- MOV BX,ES ;and segment address of Program Segment Prefix.
- SUB AX,BX ;Compute size of program in paragraphs
- MOV BX,AX ;and put it in BX
- ;ES points to Program Segment Prefix (PSP)
- ;because we haven't messed with it yet.
- MOV AX,4A00H ;Store Set Block function number and 0 (to
- ;allow error checking idependent of the
- ;carry flag.
- INT 21H ;Change memory allocation.
- CMP AX,7 ;If memory control blocks were destroyed,
- JE ADJFAIL ;go respond to the failure
- CMP AX,8 ;If not enough memory (not an expected error!),
- JE ADJFAIL ;go respond to the failure
- CMP AX,9 ;If correct segment specified,
- JNE DOSVER ;go continue.
- ADJFAIL: LEA DX,ADJMSG ;Get address of error message
- CALL DISPMSG ;and display it.
- MOV AL,1 ;Store error code in AL,
- JMP QUITERR ;then go terminate program.
-
- ;CHECK DOS VERSION
- DOSVER: MOV AH,30H ;Get DOS version
- INT 21H ;number.
- CMP AL,03H ;If DOS version number is
- JAE FRSTFILE ;3 or greater, go run the program.
- LEA DX,WGVERMSG ;Otherwise, get the address of the "wrong
- CALL DISPMSG ;version" message and display it,
- MOV AL,1 ;store an error code in AL,
- JMP QUITERR ;then go quit the program.
-
- ;GET INPUT FILENAME AND TRY OPENING FILE
- FRSTFILE: CALL SCRCLR ;Clear screen.
- LEA DX,FILEPMT ;Get the address of the file prompt
- CALL DISPMSG ;and display it.
- LEA DX,BUFF1 ;Get buffer address and
- CALL KEYSTRNG ;get a filename.
- MOV BX,DX ;Get number of
- MOV CL,[BX+1] ;characters entered
- XOR CH,CH ;in CX,
- LEA SI,BUFF1+2 ;get address of 1st character entered in DS:SI,
- PUSH DS ;get address of
- POP ES ;filename
- LEA DI,INFILE ;variable in ES:DI,
- CLD ;set direction flag for ascending addresses,
- REP MOVSB ;and copy filename into its variable
- MOVSB ;along with its ending null.
- LEA DX,INFILE ;Get address of input filename,
- MOV AL,00H ;specify read-only, DOS-2 compatible access
- MOV AH,3DH ;and attempt
- INT 21H ;to open the file.
- JNC INFILEOK ;If no problem, go try the output file.
- LEA DX,INFLMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code
- JMP QUITERR ;and go terminate the program.
- INFILEOK: MOV INHNDLE,AX ;Save input file handle
- MOV BX,INHNDLE ;and close
- MOV AH,3EH ;the input
- INT 21H ;file.
-
- ;ATTEMPT TO CREATE OUTPUT FILE
- LEA BX,BUFF1 ;Get number of
- MOV CL,[BX+1] ;characters entered
- XOR CH,CH ;in CH,
- LEA SI,BUFF1+2 ;get address of 1st character entered in DS:SI,
- LEA DI,OUTFILE ;get address of filename variable in ES:DI,
- CLD ;set direction flag for ascending addresses,
- REP MOVSB ;and copy filename into its variable
- MOVSB ;along with its ending null.
- LEA DI,OUTFILE ;Get address of output file string in ES:DI,
- MOV CL,BUFF1+1 ;number of characters in string
- XOR CH,CH ;in CX,
- MOV AL,"." ;and character to search for
- CLD ;in ascending addresses,
- REPNE SCASB ;and look for the character.
- JNZ EXTADR ;If . not found, go append file extension.
- DEC DI ;If . found, move back onto it.
- EXTADR: LEA SI,OUTEXT+1 ;Get the address of output filename extension
- MOV CL,OUTEXT ;and get its length
- XOR CH,CH ;in CX,
- REP MOVSB ;then attach it to the output filename.
- MOV AH,5BH ;Store file creation function number,
- MOV CX,20H ;an "archive" attribute byte,
- LEA DX,OUTFILE ;and the output filename address
- INT 21H ;and attempt to create the output file.
- JNC SAVHNDLE ;If no problem, go continue.
- LEA DX,OUTFLMSG ;Otherwise, get error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code,
- JMP QUITERR ;and go terminate program.
- SAVHNDLE: MOV OUTHNDLE,AX ;Store output file handle.
- MOV BX,OUTHNDLE ;and close
- MOV AH,3EH ;the output
- INT 21H ;file.
-
- ;GET DESTINATION DEVICE SIZE
- GETSIZE: LEA DX,SIZEPMT ;Get the device size prompt
- CALL DISPMSG ;and display it.
- MOV DL,BUFF1 ;Get maximum # of BUFF1 characters
- PUSH DX ;and preserve it.
- MOV BUFF1,05H ;Store max. # of digits in device size
- LEA DX,BUFF1 ;and get buffer location,
- CALL KEYNUM ;then go get device size.
- POP DX ;Restore maximum # of
- MOV BUFF1,DL ;BUFF1 characters.
- CMP BUFF1+1,0 ;If digits were entered, go
- JNE ASC2BIN ;convert them to a number.
- LEA DX,BADSZMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- JMP GETSIZE ;then go try to get size again.
- ASC2BIN: MOV CL,BUFF1+1 ;Get the number of digits entered
- XOR CH,CH ;in CX
- MOV SI,CX ;and the least significant digit's offset in
- ADD SI,1 ;SI.
- MOV DEVSIZE,00H ;Set cumulative value to 0.
- MOV BX,01H ;Set place value for LSD to 1.
- CLC ;Assure loop entry.
- NXTDIG: JC OVERFLOW ;If place value exceeds 16 bits, go choke
- MOV AL,BUFF1[SI] ;Get ASCII digit in AL,
- XOR AH,AH ;then AX.
- SUB AL,30H ;If it's not a digit,
- JC OVERFLOW ;go display error message and quit.
- CMP AL,0AH ;If it's too big,
- JAE OVERFLOW ;go display error message and quit.
- MUL BX ;Multiply digit by its place value.
- JC OVERFLOW ;if result more than 16 bits, go choke.
- ADD AX,DEVSIZE ;Add running sum to present digit.
- JC OVERFLOW ;if result more than 16 bits, go choke.
- MOV DEVSIZE,AX ;Otherwise, store new running sum.
- MOV AX,BX ;Get last place value
- MOV BX,10 ;and place multiplier
- MUL BX ;and compute next place value.
- MOV BX,AX ;Put place value in BX,
- DEC SI ;move to next digit,
- LOOP NXTDIG ;and go process next digit.
- JMP GETFILL ;Go get fill digit
- OVERFLOW: LEA DX,BADSZMSG ;Get bad size error message address
- CALL DISPMSG ;and display message
- JMP GETSIZE ;then go try to get size again.
-
- ;GET FILL DIGIT
- GETFILL: LEA DX,FILLPMT ;Get address of fill digit prompt
- CALL DISPMSG ;display prompt,
- CALL GETKEY ;and get response.
- CMP AL,30H ;If the response was not zero,
- JNE ONECHK ;go see if it was one.
- MOV NUMFILL,00H ;Otherwise, store fill byte
- JMP GETIMMEM ;and go continue.
- ONECHK: CMP AL,31H ;If the response was not one,
- JNE GETFILL ;go try to get fill digit again.
- MOV NUMFILL,0FFH ;Otherwise, store fill byte.
-
- ;SET UP MEMORY BLOCK FOR DEVICE IMAGE
- GETIMMEM: MOV BX,DEVSIZE ;Get size of destination device
- MOV CL,4 ;and convert
- SHR BX,CL ;it to
- INC BX ;paragraphs.
- MOV AH,48H ;Request
- INT 21H ;memory allocation.
- JNC GOTIMMEM ;If request successful, go continue.
- LEA DX,NOMEMMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and go display it.
- LEA DX,ADJMSG ;Get address of memory error message
- CALL DISPMSG ;and go display it.
- MOV AL,1 ;Store error code in AL,
- JMP QUITERR ;then go terminate program
- GOTIMMEM: MOV IMAGESEG,AX ;Store destination device image segment address.
-
- ;FILL THE DESTINATION DEVICE IMAGE WITH THE FILL VALUE
- MOV AL,NUMFILL ;Get fill value
- MOV CX,DEVSIZE ;and size of destination device.
- PUSH DS ;Preserve DS, then
- MOV DS,IMAGESEG ;point it to the device image.
- MOV BX,0 ;Set starting offset to 0.
- FILLUP: MOV BYTE PTR [BX],AL ;Store fill value
- INC BX ;move to next byte
- LOOP FILLUP ;and go fill next byte until all done.
- POP DS ;Restore data segment address.
-
- ;GET INPUT FILE SIZE AND REQUEST MEMORY FOR IT
- SIZEPREP: LEA DX,INFILE ;Get address of input filename,
- MOV AL,00H ;specify read-only, DOS-2 compatible access
- MOV AH,3DH ;and attempt
- INT 21H ;to open the file.
- JNC INFILESZ ;If no problem, go continue.
- LEA DX,INFLMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code *******REPLACE?
- JMP QUITERR ;and go terminate the program. *******REPLACE?
- INFILESZ: MOV INHNDLE,AX ;Save the input file's handle.
- MOV BX,INHNDLE ;Get input file's handle,
- MOV CX,00H ;Set offset for file pointer
- MOV DX,00H ;move to zero,
- MOV AX,4202H ;Store "move file pointer" function request
- ;number and "end of file" code,
- INT 21H ;and move the pointer.
- JNC GOTSIZE ;If successful, go continue
- MOV BX,INHNDLE ;Otherwise, close
- MOV AH,3EH ;the input
- INT 21H ;file.
- LEA DX,NOSZMSG ;Then, get error message address,
- CALL DISPMSG ;display message,
- MOV AL,01H ;store error code, *******REPLACE?
- JMP QUITERR ;and go terminate program. *****REPLACE?
- GOTSIZE: CMP DX,0 ;If file size occupies less than 17 bits,
- JE SIZEOK ;go continue.
- MOV BX,INHNDLE ;Otherwise, close
- MOV AH,3EH ;the input
- INT 21H ;file.
- LEA DX,INTOOBIG ;Then, get error message address,
- CALL DISPMSG ;display message,
- MOV AL,01H ;store error code, *****REPLACE?
- JMP QUITERR ;and go terminate program. *****REPLACE?
- SIZEOK: MOV INSIZE,AX ;Store size of input file
- MOV BX,INSIZE ;Get size of input file
- MOV CL,4 ;and convert
- SHR BX,CL ;it to
- INC BX ;paragraphs.
- MOV AH,48H ;Request
- INT 21H ;memory allocation.
- JNC GOTINMEM ;If request successful, go continue.
- LEA DX,NOMEMMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and go display it.
- LEA DX,ADJMSG ;Get address of memory error message
- CALL DISPMSG ;and go display it.
- MOV AL,1 ;Store error code in AL,
- JMP QUITERR ;then go terminate program
- GOTINMEM: MOV INSEG,AX ;Store input file area segment address.
-
- ;READ INPUT FILE
- MOV BX,INHNDLE ;Get input file's handle,
- MOV CX,00H ;Set offset for file pointer
- MOV DX,00H ;move to zero,
- MOV AX,4200H ;Store "move file pointer" function request
- ;number and "beginning of file" code,
- INT 21H ;and move the pointer.
- MOV BX,INHNDLE ;Get the input file's handle
- MOV CX,INSIZE ;and size.
- PUSH DS ;Preserve data segment address and
- MOV DS,INSEG ;get input file area
- MOV DX,0 ;address in DS:DX.
- MOV AH,3FH ;Store "read handle" function number,
- INT 21H ;then read input file.
- POP DS ;Restore data segment address.
- JNC READOK ;If read successful, go continue.
- LEA DX,CANTREAD ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code, *****REPLACE?
- JMP QUITERR ;and go terminate the program. *****REPLACE?
- READOK: CMP AX,INSIZE ;If the number of bytes read equals the
- JE TRANPREP ;input file's size, go continue.
- LEA DX,SIZERR ;Otherwise, get address of error message
- CALL DISPMSG ;and display it, then continue.
- TRANPREP: MOV BX,INHNDLE ;Close
- MOV AH,3EH ;the input
- INT 21H ;file.
-
- ;TRANSLATE S-RECORD FILE INTO MEMORY IMAGE
- PUSH DS ;Preserve data segment address.
- MOV DS,INSEG ;Get address of input file
- MOV SI,00H ;in DS:SI
- SLINE: MOV AL,[SI] ;Get first character of line.
- CMP AL,"S" ;if it's an S,
- JE LINETYPE ;go continue.
- JMP TRANERR ;otherwise, go choke on the error.
- LINETYPE: INC SI ;Move to second character of line
- MOV AL,[SI] ;and get it.
- CMP AL,"1" ;if it's a 1,
- JE GETLEN ;go continue
- CMP AL,"9" ;if it's a 9,
- JE OUTSTORE ;you're finished, go do cleanup.
- JMP TRANERR ;Otherwise, go choke on error.
- GETLEN: ADD SI,02H ;Point DS:SI to LSD of line length
- CALL ASCTOHEX ;and get line length.
- JC TRANERR ;If there was a problem, go choke.
- SUB AL,3 ;Otherwise, subtract "overhead" bytes.
- JC TRANERR ;If underflow, go choke.
- MOV CL,AL ;Otherwise, store number of bytes to convert
- XOR CH,CH ;in CX.
- ADD SI,02H ;Point DS:SI to LSD of most significant half
- ;(MSH) of starting address
- CALL ASCTOHEX ;and get MSH of starting address
- JC TRANERR ;If there was a problem, go choke.
- MOV BH,AL ;Otherwise store MSH of starting address.
- ADD SI,02H ;Point DS:SI to LSD of least significant half
- ;(LSH) of starting address
- CALL ASCTOHEX ;and get LSH of starting address
- JC TRANERR ;If there was a problem, go choke.
- MOV BL,AL ;Otherwise, store LSH of starting address.
- POP DS ;Restore data segment address,
- MOV ES,IMAGESEG ;get segment of image area in ES,
- PUSH DS ;preserve data segment address, and
- MOV DS,INSEG ;get segment of input file in DS.
- MOV DI,BX ;Get starting address of line in DI.
- TRANSLAT: ADD SI,02H ;Point SI to LSD of next item
- CALL ASCTOHEX ;and get item in hexadecimal
- JC TRANERR ;If there was a problem, go choke.
- MOV ES:[DI],AL ;Otherwise, store the item in the memory image,
- INC DI ;move to the next byte of image area,
- LOOP TRANSLAT ;and continue until done.
- ADD SI,05H ;Move to next line
- JMP SLINE ;and go process it.
- TRANERR: POP DS ;Restore data segment address.
- LEA DX,TRERRMSG ;Get address of translation error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code
- JMP QUITERR ;and go terminate program.
-
- ;STORE OUTPUT FILE
- OUTSTORE: POP DS ;Restore data segment address to DS
- LEA DX,OUTFILE ;Get address of output filename,
- MOV AL,01H ;specify write-only, DOS-2 compatible access
- MOV AH,3DH ;and attempt
- INT 21H ;to open the file.
- JNC OUTOPEN ;If no problem, go continue.
- LEA DX,SAVERR ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code
- JMP QUITERR ;and go terminate the program.
- OUTOPEN: MOV OUTHNDLE,AX ;Save output file handle
- MOV BX,OUTHNDLE ;Get output file handle
- MOV CX,DEVSIZE ;number of bytes in image area.
- PUSH DS ;Preserve data segment address
- MOV DS,IMAGESEG ;and point DS:DX
- MOV DX,00H ;to the image area.
- MOV AH,40H ;And store image
- INT 21H ;area in output file.
- POP DS ;Restore data segment address.
- JC BADWRITE ;If there was a problem, go choke.
- CMP AX,DEVSIZE ;If there was no problem,
- JE OUTCLOSE ;go continue.
- BADWRITE: LEA DX,WRITERR ;Get address of error message
- CALL DISPMSG ;go display it
- MOV AL,1 ;store error code in AL
- JMP QUITERR ;and go terminate the program.
- OUTCLOSE: MOV BX,OUTHNDLE ;Get output file handle
- MOV AH,3EH ;and close
- INT 21H ;output file.
-
- ;RELEASE INPUT FILE MEMORY
- MOV ES,INSEG ;Get segment address of input file area,
- MOV AH,49H ;and release
- INT 21H ;that block of memory.
- CMP AX,7 ;If memory control blocks not damaged,
- JNE NXTFILE ;then go continue.
- LEA DX,ADJMSG ;Otherwise, load error message
- CALL DISPMSG ;display it,
- MOV AL,1 ;store error code in AL
- JMP QUITERR ;and go terminate the program.
-
- ;CHECK FOR MORE INPUT FILES
- NXTFILE: CALL SCRCLR ;Clear screen.
- LEA DX,NXTPMT ;Get the address of the file prompt
- CALL DISPMSG ;and display it.
- LEA DX,BUFF1 ;Get buffer address and
- CALL KEYSTRNG ;get a filename.
- MOV BX,DX ;Get number of
- MOV CL,[BX+1] ;characters entered
- XOR CH,CH ;in CX.
- CMP CX,00H ;If no characters entered,
- JE QUIT ;go quit the program.
- LEA SI,BUFF1+2 ;Get address of 1st character entered in DS:SI,
- PUSH DS ;get address of
- POP ES ;filename
- LEA DI,INFILE ;variable in ES:DI,
- CLD ;set direction flag for ascending addresses,
- REP MOVSB ;and copy filename into its variable
- MOVSB ;along with its ending null.
- LEA DX,INFILE ;Get address of input filename,
- MOV AL,00H ;specify read-only, DOS-2 compatible access
- MOV AH,3DH ;and attempt
- INT 21H ;to open the file.
- JNC NXTFILOK ;If no problem, go try the output file.
- LEA DX,INFLMSG ;Otherwise, get address of error message
- CALL DISPMSG ;and display it,
- MOV AL,1 ;store error code
- JMP QUITERR ;and go terminate the program.
- NXTFILOK: MOV INHNDLE,AX ;Save input file handle
- MOV BX,INHNDLE ;and close
- MOV AH,3EH ;the input
- INT 21H ;file.
- JMP SIZEPREP ;Go process this input file.
-
- QUIT: MOV AL,0 ;Store "no error" code in AL.
-
- QUITERR: MOV AH,4CH
- INT 21H
-
-
- ;PROCEDURE SCRCLR --- this procedure clears the screen and moves the cursor to
- ;the upper left corner.
- ;ENTRY: the data segment must contain lookup table LINPSCRN, a sequential list
- ;of the number of lines per screen for each video mode which might be in use
- ;(0 for graphics or other modes for which ASCII line feeds won't work).
- ;STACK USAGE: 8 bytes plus one interrupt
- ;REGISTERS AFFECTED: if no error, none; if error AX (original AX can be
- ;recovered by decrementing SP twice and POPing)
- ;RETURN: if error, carry flag set and error code in AX
-
- SCRCLR PROC
- PUSH AX ;Preserve contents
- PUSH BX ;of registers
- PUSH CX ;used by
- PUSH DX ;this routine.
- MOV AH,0FH ;Get the video mode and other assorted info
- INT 10H ;by calling the video BIOS.
- CMP AL,10H ;If video mode is not in our table
- JG BADVIDMD ;go respond to the problem.
- MOV BX,AX ;Otherwise, put video mode
- XOR BH,BH ;in BX and
- MOV CL,LINPSCRN[BX] ;get the number of screen lines
- XOR CH,CH ;in CX.
- CMP CX,0 ;If 0 lines (a graphics mode)
- JE GRAPHICS ;go respond to the problem.
- MOV AH,2 ;Store send-to-screen function number
- MOV DL,0AH ;and ASCII line feed
- LINEFEED: INT 21H ;and feed a line.
- LOOP LINEFEED ;Send more linefeeds 'til screen cleared.
- MOV AH,0FH ;Get the video mode and other assorted info
- INT 10H ;by calling the video BIOS.
- ;Video page number now in BH and required below.
- MOV DH,0 ;Store row number,
- MOV DL,0 ;column number,
- MOV AH,2H ;and "set cursor position" function number,
- INT 10H ;then call video BIOS to set cursor postion.
- CLC ;Clear carry flag to indicate no error.
- JMP CLEARED ;Go return to main program.
- BADVIDMD: MOV AX,2 ;Store unrecognized video mode error number,
- STC ;set carry flag to indicate error,
- JMP CLEARED ;and go return to main program.
- GRAPHICS: MOV AX,1 ;Store graphics mode error number,
- STC ;set carry flag to indicate error,
- ;and go return to main program
- CLEARED: POP DX ;Restore contents
- POP CX ;of registers used
- POP BX ;by this routine
- JC RETERR ;but if error code in ax, don't restore it.
- POP AX ;If no error, restore contents of AX
- RET ;and return to main program.
- RETERR: INC SP ;Adjust stack pointer
- INC SP ;for failure to pop AX
- RET ;and return to main program.
- SCRCLR ENDP
-
-
- ;PROCEDURE KEYSTRNG --- this procedure uses MS-DOS for buffered key-
- ;board input. The input may be edited via the usual MS-DOS "template"
- ;editing commands (a subset of the EDLIN editing commands).
- ;The procedure fills any unused allowed field length with nulls (00H).
- ;ENTRY: DX must contain the offset of a buffer in the data segment.
- ; The first byte of the buffer must contain a number 1 greater
- ; than the maximum allowable number of characters (and no
- ; bigger than 2 less than the buffer's size and no bigger
- ; than 255 decimal). Thus, the maximum storage space is buffer size
- ; - 3 characters. For setting up the buffer, declare the first byte
- ; as 1+max. # of characters, then declare 2+max. # of characters
- ; DS must contain the correct segment address for the buffer.
- ;STACK USAGE: 8 bytes, 1 DOS function call
- ;REGISTERS AFFECTED: none
- ;VARIABLES AFFECTED: second through nth bytes of the buffer, where n
- ; is the maximum allowable number of characters + 3
- ;RETURN: second byte of buffer contains the number of
- ; characters entered
- ; third byte & on of buffer contain characters entered
- ; followed by nulls (00H) to fill unused allowed space
-
- KEYSTRNG PROC
- PUSH AX ;save contents of AX
- PUSH CX ;CX,
- PUSH SI ;SI,
- PUSH DI ;and DI.
- MOV AH,0AH ;store "buffered input" function #
- INT 21H ;and make the function call
- MOV SI,DX ;get address of max. # of char's + 1
- CMP BYTE PTR [SI],1 ;If no characters were allowed,
- JBE FULL ;then you're done.
- MOV CL,[SI] ;Get the max. allowable # of characters + 1
- INC SI ;minus
- SUB CL,[SI] ;the number of characters entered.
- XOR CH,CH ;Get the number of nulls to
- ;insert in CX.
- MOV DI,DX ;Get the address of
- ADD DI,2 ;the first character in DI.
- MOV AL,[SI] ;Get the number of characters entered
- XOR AH,AH ;in AX.
- ADD DI,AX ;Get the address of the first unused
- ;byte in DI.
- FILL: MOV BYTE PTR [DI],00H ;Put a null in an unused byte.
- INC DI ;Move to the next byte.
- LOOP FILL ;If not done, fill it.
- FULL: POP DI ;Restore original contents of DI,
- POP SI ;SI,
- POP CX ;CX,
- POP AX ;and AX.
- RET
- KEYSTRNG ENDP
-
-
- ;PROCEDURE KEYNUM --- this procedure uses two MS-DOS function calls
- ;to obtain ASCII codes for the digits of a decimal number
- ;typed on the keyboard and stores the successive codes in ascending
- ;bytes of the data segment starting at DS:DX+2. If Q or q is pressed,
- ;the procedure jumps to QUIT, which must be the main program's termination
- ;section.
- ;ENTRY: DX must conatain the offset of a buffer in the data segment
- ; DS:DX must contain the maximum allowable number of digits (no
- ; bigger than buffer size - 3 and no bigger than 254 decimal).
- ;STACK USAGE: 8 bytes, 1 interrupt
- ;NOTE: DX is preserved in BX and restored. Don't mess with BX!
- ;REGISTERS AFFECTED: none
- ;VARIABLES AFFECTED: DS:DX+1 to DS:DX+1+n where n is the number of
- ; characters entered.
- ;RETURN: DS:DX+1 contains the number of characters entered.
- ; DS:DX+2 to DS:DX+1+n contain the ASCII codes of the characters
- ; entered.
-
- KEYNUM PROC
- PUSH AX ;preserve the contents of AX
- PUSH BX ;preserve the contents of BX
- PUSH CX ;preserve the contents of CX
- PUSH DI ;preserve the contents of DI
- XOR DI,DI ;zero DI (no characters entered)
- MOV BX,DX ;get buffer offset in BX
- MOV BYTE PTR [BX]+1,0 ;set number of characters entered to 0
- MOV CL,[BX] ;get number of digits allowed
- XOR CH,CH ;in CX
- DIGIT: MOV DL,0FFH ;prepare to request
- MOV AH,6 ;direct keyboard input
- KEYBD: INT 21H ;and make the function call
- CMP AL,0 ;if no character pressed,
- JE KEYBD ;try again
- CMP AL,'Q' ;if Q pressed,
- JE QUE ;quit.
- CMP AL,'q' ;If q was pressed,
- JE QUE ;quit.
- CMP AL,0DH ;if character is a RETURN
- JE DONE ;the procedure terminates
- CMP AL,08H ;if character is a BACKSPACE
- JE BACKSP ;accomodate it
- CMP CX,DI ;if maximum # of digits already entered,
- JE DIGIT ;ignore this one
- CMP AL,'0' ;if it's inappropriate
- JB DIGIT ;ignore it
- CMP AL,'9' ;if it's not a digit
- JA DIGIT ;ignore it
- ;if it's a digit
- STORE: MOV [BX][DI]+2,AL ;store it
- INC DI ;count it
- MOV DL,AL ;move it to DL
- MOV AH,2 ;store send-to-display function #
- INT 21H ;and make the function call
- JMP DIGIT ;and go get the next character
- QUE: JMP QUIT ;If "quit", go quit.
- BACKSP: CMP DI,0 ;don't backspace
- JE DIGIT ;too far
- DEC DI ;count a backspace
- MOV DL,08H ;store ASCII backspace in DL
- MOV AH,2 ;store send-to-display function #
- INT 21H ;and make the function call
- MOV DL,20H ;erase the
- INT 21H ;existing character
- MOV DL,08H ;then move back onto
- INT 21H ;the space
- BAKDIG: JMP DIGIT ;and go get next character
- DONE: MOV AX,DI ;get # of characters entered in AX
- MOV [BX]+1,AL ;and in 2nd byte of buffer
- MOV DX,BX ;put buffer offset back in DX
- POP DI ;restore original contents of DI,
- POP CX ;CX,
- POP BX ;BX,
- POP AX ;and AX
- RET ;and go back to main program
- KEYNUM ENDP
-
-
- ;PROCEDURE ASCTOHEX --- This procedure converts two ASCII digits to a
- ;hexadecimal number returned in AL. If there's a problem, it will return to the
- ;calling program with the carry flag set. The ASCII digits should be stored
- ;with the least significant digit in the higher memory location, pointed to by
- ;SI.
- ;ENTRY: DS:SI points to the second (least significant) digit
- ;STACK USAGE: none?
- ;REGISTERS AFFECTED: AL
- ;RETURN: hex number in AL, carry set if error, carry clear if OK
-
- ASCTOHEX PROC
- PUSH BX ;Preserve contents of BX
- MOV AL,[SI] ;Get LSD of line length,
- SUB AL,30H ;and try to make it a decimal digit.
- JC ERRET ;if it's not a digit, go choke.
- CMP AL,09H ;If it's a decimal digit
- JBE STORE1 ;go store it.
- SUB AL,07H ;Otherwise, try to make it a hex digit.
- JC ERRET ;if it's not a digit, go choke.
- CMP AL,0FH ;If it's not a hex digit,
- JA ERRET ;go choke.
- STORE1: MOV BH,AL ;Store LSD of line length.
- DEC SI ;Move to MSD of line length.
- MOV AL,[SI] ;Get MSD of line length,
- INC SI ;put SI back where it was,
- SUB AL,30H ;and try to make it a decimal digit.
- JC ERRET ;if it's not a digit, go choke.
- CMP AL,09H ;If it's a decimal digit
- JBE STORE2 ;go store it.
- SUB AL,07H ;Otherwise, try to make it a hex digit.
- JC ERRET ;if it's not a digit, go choke.
- CMP AL,0FH ;If it's not a hex digit,
- JA ERRET ;go choke.
- STORE2: MOV BL,10H ;Multiply MSD
- MUL BL ;by its place value,
- ADD AL,BH ;then add the LSD
- JC ERRET ;If overflow, go choke.
- CLC ;Note lack of error
- POP BX ;restore contents of BX
- RET ;and return to caller.
- ERRET: STC ;Note error
- POP BX ;restore contents of BX
- RET ;and return to caller.
- ASCTOHEX ENDP
-
-
- ;PROCEDURE GETKEY --- this procedure uses an MS-DOS function call (via
- ;INT 21H) to cause the computer to wait for a character to be pressed
- ;on the keyboard. When a character is pressed, it is echoed to the
- ;display and its ASCII code is stored in AL. If the character is a
- ;<SHIFT-BREAK> (or Ctrl-C), the program terminates and MS-DOS takes over.
- ;ENTRY: no requirements.
- ;REGISTERS AFFECTED: AX.
- ;RETURN: AL contains ASCII code for the character pressed.
-
- GETKEY PROC
- MOV AH,1 ;store "get-from-keyboard" function #
- INT 21H ;and make the function call
- RET ;then return to main program
- GETKEY ENDP
-
-
- ;PROCEDURE DISPCHAR --- this procedure uses an MS-DOS function call (via
- ;INT 21H) to display a character or to send a control character to the
- ;display.
- ;ENTRY: DL must contain the ASCII code of the character to be displayed
- ;STACK USAGE: 2 bytes, 1 interrupt
- ;REGISTERS AFFECTED: none
- ;RETURN: no data
-
- DISPCHAR PROC
- PUSH AX ;preserve contents of AX
- MOV AH,2 ;store "send-to-display" function #
- INT 21H ;and make the function call
- POP AX ;restore original contents of AX
- RET ;then return to main program
- DISPCHAR ENDP
-
-
- ;PROCEDURE DISPMSG --- this procedure uses an MS-DOS function call (via
- ;INT 21H) to display a character string. The string must end with a
- ;dollar sign, which will not be sent to the display.
- ;ENTRY: DS must contain the string's segment address and DX must con-
- ; tain the offset of the string's first character.
- ;STACK USAGE: 2 bytes, 1 interrupt
- ;REGISTERS AFFECTED: none
- ;RETURN: no data
-
- DISPMSG PROC
- PUSH AX ;preserve contents of AX
- MOV AH,9 ;store "display message" function #
- INT 21H ;and make the function call
- POP AX ;restore original contents of AX
- RET ;then return to main program
- DISPMSG ENDP
-
- CODE1 ENDS
-
-
- ZZZZZZZZ SEGMENT 'ZZZZ'
- ;This segment is used when releasing memory not needed by the main
- ;program. It should be the last segment in its source file so that
- ;it will be placed last in the program file if the assembler and
- ;linker use sequential segment ordering. The name ZZZZZZZZZ assures
- ;that this segment will be last in the program file if the assembler
- ;or linker uses alphabetic segment ordering.
- ZZZZZZZZ ENDS
-
-
- END START
-
-