home *** CD-ROM | disk | FTP | other *** search
- COMMENT ^
-
- CWSORT.ASM
-
- 32-bit assembly language sort utility using CauseWay 386 DOS extender
-
- Version: 1.0
-
- Usage: CWSORT <input file> <output file> <options>
-
- <options> may be placed anywhere in the command line and are
- preceded by a '/'. They are not case sensitive.
-
- Supported options are:
- /+##### begin at offset from start of sort string, ##### is the
- offset value, relative 1, maximum of 65535
- /D remove duplicate fields
- /L##### fixed length field sort, ##### is the field length,
- maximum of 65535
- /Q run in quiet mode
- /R reverse sort order
- /S<file name> sort file according to sort order specified in
- <file name>.
-
- Comments: This code is not optimized except in the bottleneck areas where it
- makes a difference. Even there, every last cycle hasn't been
- wrung out, although optimization is pretty good. Be aware that
- many optimizations are written towards Pentium usage and some
- code constructs may be less optimal with a 386 and, to a lesser
- extent, a 486. In particular, string instructions tend to be
- much less important on a Pentium.
-
- A minimum of higher level directives were used to avoid
- compatibility problems with different assembler versions.
-
- The CWSORT.ASM source code is released to the public domain.
- Copyright restrictions remain in force for the CauseWay DOS
- extender contained in CWSORT.EXE. However, redistribution of
- CauseWay-extended executable files created by registered owners
- of CauseWay (as Michael Devore is) without royalties or
- licensing fees or restrictions is explicitly allowed by the
- CauseWay software license agreement.
-
- Written by: Michael Devore
-
- Authorized contact information for CWSORT and CauseWay questions:
- CompuServe: 71540,62
- Internet: 71540.62@compuserve.com
- Fax: 1-708-717-6373 (N.B. 708 area code is scheduled to change in 1996)
- Mail: Michael Devore
- Devore Software & Consulting
- PO Box 4283
- Naperville, IL 60567-4283
- USA
-
- Begin Date: 08/95
- Last changed: 08/95
-
- END COMMENT ^
-
- ;******************************************************************************
- ;******************************************************************************
-
- .386 ; placed before model directive and segment declarations
- ; makes all segments 32-bit
- .MODEL SMALL
- .STACK 400h
-
- ; handy equates
- BELL EQU 7
- CR EQU 13
- LF EQU 10
- OFF EQU 0
- ON EQU 1
- STDOUT EQU 1
-
- BADEXITCODE = 129
-
- .DATA
-
- BufferSelector DW 0 ; selector of input file memory buffer
- InputFileHandle DW 0
- LineCount DD 0 ; count of text lines
- OutputFileHandle DW 0
- OutputSelector DW 0 ; selector of output file memory buffer
- PointerArraySize DD 0 ; current size of dword pointer array
- PointerSelector DW 0 ; selector of pointers to variable length fields
- SortOrderFileHandle DW 0
-
- ALIGN 4
- FixedLengthSize DD 0 ; size of fixed length fields
- ALIGN 4
- SortOffsetValue DD 0 ; size of sorting offset
-
- ExitCode DB 0
- FileCount DB 0
- IsDuplicateOption DB 0 ; nonzero if remove duplicates option
- IsFixedLengthOption DB 0 ; nonzero if /L##### option
- IsSortOffsetOption DB 0 ; nonzero if /+##### option
- IsQuietOption DB 0 ; nonzero if /Q quiet option specified
- IsReverseOption DB 0 ; nonzero if /R reverse option
- IsSortOrderOption DB 0 ; nonzero if /S<filename> option
- ParsingFileNameFlag DB 0 ; nonzero if parsing file name
-
- DW 0 ; file name length
- InputFileName DB 81 DUP (0) ; input file name
- DW 0 ; file name length
- OutputFileName DB 81 DUP (0) ; output file name
- DW 0 ; file name length
- SortOrderFileName DB 81 DUP (0) ; sort order file name
-
- ; build the default sort order table in ASCII order
- ALIGN 4
- SortOrderTable LABEL BYTE
- COUNTER = 0
- REPT 256
- DB COUNTER
- COUNTER=COUNTER+1
- ENDM
-
- ; address for different sort logic parameters
- ALIGN 4
- SetOffsetCounterAddress DD OFFSET NoOffsetCounterLogic
- SortOffsetLogicAddress DD OFFSET NoSortOffsetLogic
- FixedCounterAddress DD OFFSET NoFixedCounterLogic
- FixedMoveAddress DD OFFSET NoFixedMoveLogic
- FixedJumpAddress DD OFFSET NoFixedJumpLogic
- SortLookupAddress DD OFFSET NoSortLookupLogic
-
- .DATA?
-
- ScratchBuffer DB 256 DUP (?)
-
- InputFileSize DD ?
-
- ; variables used in shell sort
- iValue DD ?
- vValue DD ?
- SortOffsetCounter DD ?
- FixedLengthCounter DD ?
-
- .CONST
-
- CRLFText DB CR,LF
-
- DW BadOptionTextStop-BadOptionText
- BadOptionText DB 'Invalid option specified: /'
- BadOptionTextStop = $
-
- DW BadSortFileOpenTextStop-BadSortFileOpenText
- BadSortFileOpenText DB 'Cannot open sort order file: '
- BadSortFileOpenTextStop = $
-
- DW BadSortFileReadTextStop-BadSortFileReadText
- BadSortFileReadText DB 'Error reading sort order file: '
- BadSortFileReadTextStop = $
-
- DW BadInputOpenTextStop-BadInputOpenText
- BadInputOpenText DB 'Cannot open input file: '
- BadInputOpenTextStop = $
-
- BadInputReadText DB 'Failure to read input file: '
-
- DW BadOutputOpenTextStop-BadOutputOpenText
- BadOutputOpenText DB 'Cannot create output file: '
- BadOutputOpenTextStop = $
-
- DW LocatingLinesTextStop-LocatingLinesText
- LocatingLinesText DB 'Locating text lines....'
- LocatingLinesTextStop = $
-
- DW MemoryTextStop-MemoryText
- MemoryText DB 'Not enough available memory.'
- MemoryTextStop = $
-
- DW NoInputTextStop-NoInputText
- NoInputText DB 'No input or output file specified.'
- NoInputTextStop = $
-
- DW NoOutputTextStop-NoOutputText
- NoOutputText DB 'No output file specified.'
- NoOutputTextStop = $
-
- DW ReadingFileTextStop-ReadingFileText
- ReadingFileText DB 'Reading file: '
- ReadingFileTextStop = $
-
- DW SortingFileTextStop-SortingFileText
- SortingFileText DB 'Sorting file....'
- SortingFileTextStop = $
-
- DW WritingFileTextStop-WritingFileText
- WritingFileText DB 'Writing file: '
- WritingFileTextStop = $
-
- DW CreditTextStop-CreditText
- CreditText = $
- DB "CWSORT 1.0, Written by Michael Devore, released to public domain.",CR,LF
- DB CR,LF
- DB "Usage: CWSORT <input file> <output file> <options>",CR,LF
- DB CR,LF
- DB " <options> may be placed anywhere in the command line and are",CR,LF
- DB " preceded by a '/'. They are not case sensitive.",CR,LF
- DB CR,LF
- DB " Supported options are:",CR,LF
- DB CR,LF
- DB " /+##### begin at offset from start of sort string, ##### is the",CR,LF
- DB " offset value, relative 1, maximum of 65535",CR,LF
- DB " /D remove duplicate fields",CR,LF
- DB " /L##### fixed length field sort, ##### is the field length,",CR,LF
- DB " maximum of 65535",CR,LF
- DB " /Q run in quiet mode",CR,LF
- DB " /R reverse sort order",CR,LF
- DB " /S<file name> sort file according to sort order specified in",CR,LF
- DB " <file name>.",CR,LF
- CreditTextStop = $
-
- .CODE
-
- ;******
- ; MAIN
- ;******
- ; main entry point of application
-
- main PROC
- call Init
- call GetCommandLine
- jc mexit
- call PrepareFiles
- jc mexit
- call AllocateInputBuffer
- mov edx,OFFSET DGROUP:ReadingFileText
- call DisplayString
- mov edx,OFFSET DGROUP:InputFileName
- call DisplayStringCRLF
- call ReadFileIntoMemory
- jc mexit
- mov edx,OFFSET DGROUP:LocatingLinesText
- call DisplayStringCRLF
- call SetTextPointers
- mov edx,OFFSET DGROUP:SortingFileText
- call DisplayStringCRLF
- call SortInfo
- call CheckDuplicateLines
- call BuildOutputBuffer
- mov edx,OFFSET DGROUP:WritingFileText
- call DisplayString
- mov edx,OFFSET DGROUP:OutputFileName
- call DisplayStringCRLF
- call WriteFileToDisk
- jc mexit
-
- mexit:
- call Terminate ; no return
- main ENDP
-
- ;******
- ; INIT
- ;******
- ; initialization code
-
- Init PROC NEAR
-
- ; point ds and gs to DGROUP as default
- mov eax,DGROUP
- mov ds,eax ; yes, this is stupid, but MOV DS,AX with MASM forces a
- ; superfluous 66h prefix byte and it's harmless as far
- ; as TASM is concerned
- mov gs,eax
- ret
- Init ENDP
-
- ;****************
- ; GETCOMMANDLINE
- ;****************
- ; get command line parameters
- ; no intelligent option parsing, but not enough options to make it so
- ; upon entry es -> protected mode PSP (application entry condition)
- ; return carry flag set if bad option or null command line
- ; carry flag reset otherwise
-
- GetCommandLine PROC NEAR
- mov esi,81h ; es:esi -> command line preceded by length
- movzx ecx,BYTE PTR es:[esi-1] ; get count of bytes in command line
- cmp ecx,1
- jbe nocl
-
- clloop:
- or ecx,ecx ; no more parameter chars
- je gcldone
- dec ecx
- mov al,es:[esi] ; get parameter char
- inc esi
- cmp al,' ' ; see if whitespace
- jbe nextparam ; yes, move to next parameter
- cmp al,'/' ; see if option
- je isoption ; yes
-
- ; see if file name being processed
- cmp ParsingFileNameFlag,ON
- je savechar
-
- ; start of input or output file name
- mov edi,OFFSET DGROUP:InputFileName
- inc FileCount
- mov ParsingFileNameFlag,ON
- cmp FileCount,2 ; determine if on input or output file name
- jb savestart
- ja clloop ; both parsed, ignore this extraneous text
-
- ; acquiring output file name
- mov edi,OFFSET DGROUP:OutputFileName
-
- savestart:
- mov ebx,edi ; save pointer to start of file name for length word
-
- ; store file name
- savechar:
- mov ds:[edi],al ; save file name char
- inc edi
- inc WORD PTR [ebx-2]
- jmp clloop ; loop for another char
-
- ; moving to next parameter
- nextparam:
- mov ParsingFileNameFlag,OFF ; turn off flag of processing file name
- jmp clloop
-
- gcldone:
- clc ; flag successful command line processing
- ret
-
- ; no command line, display help screen
- nocl:
- call DisplayHelp
-
- gclfail:
- stc ; flag failure
- ret
-
- ; process option
- isoption:
- or ecx,ecx ; no more chars
- je gcldone
- dec ecx
- mov al,es:[esi] ; get option char
- inc esi
-
- cmp al,'Q'
- jne iso2
-
- isoq:
- mov IsQuietOption,ON
- jmp clloop
-
- iso2:
- cmp al,'q'
- je isoq
- cmp al,'R'
- jne iso3
-
- isor:
- mov IsReverseOption,ON
- jmp clloop
-
- iso3:
- cmp al,'r'
- je isor
- cmp al,'D'
- jne iso4
-
- isod:
- mov IsDuplicateOption,ON
- jmp clloop
-
- iso4:
- cmp al,'d'
- je isod
- cmp al,'L'
- jne iso5
-
- ; set fixed length fields option and get field length
- isol:
- mov IsFixedLengthOption,ON
- call GetWordValue
- mov WORD PTR FixedLengthSize,ax
- jmp clloop
-
- iso5:
- cmp al,'l'
- je isol
- cmp al,'+'
- jne iso6
-
- ; set sorting offset option and get offset value
- mov IsSortOffsetOption,ON
- call GetWordValue
- mov WORD PTR SortOffsetValue,ax
- jmp clloop
-
- iso6:
- cmp al,'S'
- jne iso7
-
- ; set sort order option and get sort order file name
- isos:
- mov IsSortOrderOption,ON
- mov edi,OFFSET DGROUP:SortOrderFileName
-
- soloop:
- or ecx,ecx ; no more chars
- je gcldone
- dec ecx
- mov al,es:[esi] ; get file name char
- inc esi
- cmp al,' '
- jbe clloop
- mov ds:[edi],al
- inc edi
- inc WORD PTR SortOrderFileName-2 ; bump file name length
- jmp soloop
-
- iso7:
- cmp al,'s'
- je isos
-
- ; invalid option
- mov ScratchBuffer+2,al
- mov WORD PTR ScratchBuffer,1
- mov edx,OFFSET DGROUP:BadOptionText
- call DisplayString
- mov edx,OFFSET DGROUP:ScratchBuffer+2
- call DisplayStringCRLF
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
-
- jmp gclfail
-
- GetCommandLine ENDP
-
- ;**************
- ; GETWORDVALUE
- ;**************
- ; get an option word value, 1-65535
- ; upon entry ecx == remaining count of chars in command line, updated,
- ; es:esi -> command line chars
- ; return value in eax, ignore overflow
- ; Yes, there are all sorts of tricks to shave code and cycles for these
- ; type of routines dreamed up from countless contests, but I never remember
- ; them when the time comes. Prime rule of optimization: unless
- ; doing it for practice or entertainment, cycle-shaving where it isn't
- ; necessary or noticed is a waste of time.
-
- GetWordValue PROC NEAR
- xor eax,eax ; init return value
- mov edi,10 ; use as constant
-
- gwvloop:
- or ecx,ecx ; no more chars
- je gwvdone
- dec ecx
- mov bl,es:[esi] ; get option value
- inc esi
- cmp bl,'0' ; must be numeric
- jb gwvdone
- cmp bl,'9'
- ja gwvdone
- mul edi ; shift previous value by 1 digit place (*10)
- and eax,0ffffffh ; eliminate possibility of dword overflow problems
- and bl,0fh ; strip ASCII value
- movzx ebx,bl ; zero high bytes
- add eax,ebx
- jmp gwvloop
-
- gwvdone:
- cmp eax,65535 ; check for word overflow
- jb gwvdone2 ; no problem
- mov eax,65535
-
- gwvdone2:
- or eax,eax ; see if nonzero value specified
- jne gwvret ; yes
- inc eax ; make minimum value of 1
-
- gwvret:
- ret
- GetWordValue ENDP
-
- ;*************
- ; DISPLAYHELP
- ;*************
- ; display help screen
-
- DisplayHelp PROC NEAR
- mov edx,OFFSET DGROUP:CreditText
- call DisplayString
- ret
- DisplayHelp ENDP
-
- ;**************
- ; PREPAREFILES
- ;**************
- ;
- ; prepare input and output files, sort order file if necessary
- ; check file existence and open
- ; return carry flag set if failure,
- ; carry flag reset if success
-
- PrepareFiles PROC NEAR
- cmp BYTE PTR InputFileName,0 ; see if any input file specified
- jne pf2 ; yes
-
- ; no input or output file
- mov edx,OFFSET DGROUP:NoInputText
- call DisplayStringCRLF
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
-
- jmp pffail
-
- pf2:
- cmp BYTE PTR OutputFileName,0 ; see if output file specified
- jne pf3 ; yes
-
- ; no output file
- mov edx,OFFSET DGROUP:NoOutputText
- call DisplayStringCRLF
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
-
- jmp pffail
-
- pf3:
- mov edx,OFFSET DGROUP:InputFileName
- mov al,40h ; read-only, deny none access
- call OpenFile ; open input file, ax == handle
- jc pfbadinp
- mov InputFileHandle,ax
-
- ; seek to end of input file to get file size
- mov bx,ax
- xor cx,cx
- mov dx,cx
- mov ax,4202h ; move file pointer relative end of file
- int 21h
- mov WORD PTR InputFileSize,ax ; save the input file size
- mov WORD PTR InputFileSize+2,dx
-
- ; rewind file
- xor cx,cx
- mov dx,cx
- mov ax,4200h ; move file pointer relative beginning of file
- int 21h
-
- mov edx,OFFSET DGROUP:OutputFileName
- mov al,40h ; read-only, deny none access
- call CreateFile ; create output file, ax == handle
- jc pfbadout
- mov OutputFileHandle,ax
-
- ; open and process sort order file, if any
- cmp IsSortOrderOption,ON
- jne pfret
- call ProcessSortOrderFile
- jc pffail ; error processing sort order file
-
- pfret:
- clc ; flag success
- ret
-
- ; error opening input file
- pfbadinp:
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
- mov edx,OFFSET DGROUP:BadInputOpenText
-
- pfbadshared:
- call DisplayString
- mov edx,OFFSET DGROUP:InputFileName
- call DisplayStringCRLF
-
- pffail:
- stc ; flag failure
- ret
-
- ; error creating output file
- pfbadout:
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
- mov edx,OFFSET DGROUP:BadOutputOpenText
- jmp pfbadshared
-
- PrepareFiles ENDP
-
- ;**********************
- ; PROCESSSORTORDERFILE
- ;**********************
- ; open and process the sort order file
- ; return carry flag set if fail, reset on success
-
- ProcessSortOrderFile PROC NEAR
- mov edx,OFFSET DGROUP:SortOrderFileName
- mov al,40h ; read-only, deny none access
- call OpenFile ; open input file, ax == handle
- jc psobadopen
- mov SortOrderFileHandle,ax ; currently superfluous, but good idea to keep
- mov bx,ax ; file handle to bx for reads
-
- ; read the sort order file and process
- psoreadloop:
- mov cx,256
- mov edx,OFFSET DGROUP:ScratchBuffer
- call ReadFile
- jc psobadread
- or ax,ax ; see if any bytes read
- je psosuccess ; not this time
-
- psomodloop:
- movzx edi,BYTE PTR ds:[edx] ; ebx -> position to modify within table
- mov cl,ds:[edx+1] ; get modification value
- mov ds:[SortOrderTable+edi],cl ; update sort order value
- add edx,2 ; move to next position
- sub ax,2 ; drop count of entries read (word/entry)
- ja psomodloop ; not at end entry or odd byte
- jmp psoreadloop ; loop for another round
-
- psosuccess:
- call CloseFile
- clc ; flag success
- ret
-
- psofail:
- stc ; flag failure
- ret
-
- ; error creating output file
- psobadopen:
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
- mov edx,OFFSET DGROUP:BadSortFileOpenText
-
- psobadshared:
- call DisplayString
- mov edx,OFFSET DGROUP:SortOrderFileName
- call DisplayStringCRLF
- jmp psofail
-
- ; error reading sort input file
- psobadread:
- mov ExitCode,BADEXITCODE
- BADEXITCODE = BADEXITCODE+1
- mov edx,OFFSET DGROUP:BadSortFileReadText
- jmp psobadshared
-
- ProcessSortOrderFile ENDP
-
- ;**********
- ; OPENFILE
- ;**********
- ; open file
- ; upon entry edx -> filename, al holds open flags
- ; return carry set if error, otherwise ax == file handle
-
- OpenFile PROC NEAR
- mov ah,3dh ; open file
- int 21h
- ret
- OpenFile ENDP
-
- ;************
- ; CREATEFILE
- ;************
-
- ; create normal file, truncate if exists
- ; upon entry edx -> file name
- ; return carry set if error, otherwise ax == file handle
-
- CreateFile PROC
- xor cx,cx ; normal file attribute
- mov ah,3ch ; create or truncate file
- int 21h
- ret
- CreateFile ENDP
-
- ;*********************
- ; ALLOCATEINPUTBUFFER
- ;*********************
- ; allocate memory block buffer for input file
-
- AllocateInputBuffer PROC NEAR
- mov eax,InputFileSize
- add eax,2 ; in case need to add final CR/LF to file
- add eax,9 ; allow slop at end of file for text scanning
- call GetMemory ; attempt to allocate sufficient memory to hold file
- mov BufferSelector,ax ; save selector
- ret
- AllocateInputBuffer ENDP
-
- ;***************
- ; DISPLAYSTRING
- ;***************
- ; display text string
- ; upon entry edx -> text to display, word length prepended
-
- DisplayString PROC NEAR
- cmp IsQuietOption,ON
- je dsret ; no display with quiet option
- mov cx,WORD PTR ds:[edx-2]
- mov bx,STDOUT
- mov ah,40h
- int 21h
-
- dsret:
- ret
- DisplayString ENDP
-
- ;*******************
- ; DISPLAYSTRINGCRLF
- ;*******************
- ; display text string with CR/LF terminator
- ; upon entry edx -> text to display, word length prepended
-
- DisplayStringCRLF PROC NEAR
- cmp IsQuietOption,ON
- je dscrret ; no display with quiet option
- call DisplayString
- mov edx,OFFSET DGROUP:CRLFText
- mov cx,2
- mov bx,STDOUT
- mov ah,40h
- int 21h
-
- dscrret:
- ret
- DisplayStringCRLF ENDP
-
- ;********************
- ; READFILEINTOMEMORY
- ;********************
- ; read entire input file into memory, if possible
- ; return carry flag set if failure,
- ; carry flag reset if success
-
- ReadFileIntoMemory PROC NEAR
- push ds ; save critical register
- xor edx,edx ; zero init offset in input buffer
- mov bx,InputFileHandle
- mov esi,InputFileSize ; get bytes to read
- mov ds,BufferSelector ; ds:edx -> input file read buffer
-
- rffileloop:
- mov ecx,esi ; get bytes to read
- cmp ecx,0fff0h ; see if past maximum
- jbe rfread ; no
- mov cx,0fff0h ; set bytes to read to maximum (ecx high word known zero)
-
- rfread:
- call ReadFile
- jc rfret ; error during read
- movzx eax,ax ; get bytes read this pass
- add edx,eax ; update buffer read position
- sub esi,eax ; update bytes left to read
- jne rffileloop ; more to read
-
- ; check for final CR/LF, add if necessary and not fixed length sorting
- cmp gs:IsFixedLengthOption,ON ; see if fixed length sorting
- jne rfvar ; no
-
- ; pad the input sort buffer with spaces for any partial line at
- ; end of file for less than fixed length
- xor edx,edx
- mov eax,gs:InputFileSize
- mov ecx,gs:FixedLengthSize
- div ecx ; value known to fit in eax
- or edx,edx ; see if any remainder
- je rf2 ; no
- sub ecx,edx ; compute amount of partial line padding
-
- ; resize memory allocation for input buffer increase
- push ecx ; keep pad size
- mov eax,gs:InputFileSize
- add ecx,eax ; compute original file size+pad size
- add ecx,9 ; allow slop space at end of file for text scanning
- mov ax,gs:BufferSelector
- call ResizeMemory
- pop ecx ; restore pad size
-
- ; pad the partial line with spaces
- ; one-time store isn't worth special Pentium optimizations, just use stos
- mov edi,gs:InputFileSize
- add gs:InputFileSize,ecx ; bump defacto file size for partial padding
- mov eax,20202020h
- push ds
- pop es ; es -> input buffer
- push ecx
- shr ecx,2
- rep stosd
- pop ecx
- and ecx,3
- rep stosb
-
- rf2:
- mov edx,gs:InputFileSize ; edx -> end of file
- jmp scanpad
-
- rfvar:
- cmp WORD PTR ds:[edx-2],CR+(256*LF)
- je scanpad
- mov WORD PTR ds:[edx],CR+(256*LF)
- add edx,2
- add gs:InputFileSize,2 ; bump length of file by two for CR/LF pair
-
- ; pad the input sort buffer with spaces for end of line scanning
- ; much easier and faster than constantly doing a special end of file check
- ; note that this pad will not be sorted into the output file, it's just
- ; a bumper for reads past end of file
- scanpad:
- mov eax,20202020h
- mov ds:[edx],eax
- mov ds:[edx+4],eax
- mov ds:[edx+8],al
-
- rfret:
- pop ds ; restore critical register
- ret
- ReadFileIntoMemory ENDP
-
- ;*****************
- ; SETTEXTPOINTERS
- ;*****************
- ; allocate array of dword pointers to text lines
- ; keep pointer to each new line
- ; grow the pointer array allocation as necessary
-
- SetTextPointers PROC NEAR
- cmp IsFixedLengthOption,OFF ; see if sorting fixed length files
- je varline ; no
- xor edx,edx ; compute line pointer entry count
- mov eax,InputFileSize
- mov ecx,FixedLengthSize
- div ecx ; value known to fit in eax, partial already padded to full
-
- stpalloc:
- mov LineCount,eax
- inc eax ; make relative 1
- shl eax,2 ; allocate dword entry per line
- mov PointerArraySize,eax
- call GetMemory
- mov PointerSelector,ax
-
- ; setup line pointer entry values, each a multiple of fixed length size
- mov es,ax ; es -> array storage
- mov edi,4 ; edi -> line pointer array, don't use 0'th element
- xor eax,eax ; eax -> current line
- mov ecx,LineCount
-
- stpstoreloop:
- mov es:[edi],eax ; update line pointer entry
- add edi,4 ; move to next entry
- add eax,FixedLengthSize ; point to next line
- dec ecx
- jne stpstoreloop ; more lines
- jmp stpdone
-
- varline:
- mov eax,65536
- mov PointerArraySize,eax
- call GetMemory ; make initial space for pointer array
- mov PointerSelector,ax
- mov es,ax ; es -> array storage
- mov ds,BufferSelector ; ds -> input buffer for performance
- mov esi,4 ; init pointer array element
- ; don't use [0]'th array element, not used in sort
- xor edi,edi ; buffer pointer
- mov edx,edi ; buffer pointer adjustment
-
- ; es -> array
- ; ds -> input buffer
- ; gs -> DGROUP
- addline:
- add edi,edx ; compute adjusted start of line
- cmp edi,gs:InputFileSize ; check if at or past end of file
- jae stpdone ; no more lines
- inc gs:LineCount ; bump count of lines
-
- ; check if pointer array needs expanding
- cmp esi,gs:PointerArraySize
- jae growarray ; next array element is past pointer array boundary
-
- storearray:
- mov es:[esi],edi
- add esi,4 ; move to next array element
- mov edx,2 ; preset adjustment for alignment check in case of match
- mov ecx,gs:InputFileSize ; get absolute upper boundary
- dec ecx ; adjust for second byte
- mov eax,ecx
- sub eax,9 ; get main loop upper boundary
- jnc alignchk
- xor eax,eax ; upper boundary below zero, set to zero
-
- ; realign EDI to dword boundary if necessary
- alignchk:
- cmp edi,ecx ; see if at absolute upper boundary
- jae stpdone ; yes
- cmp edi,eax ; see if at main loop upper boundary
- jae slowchk ; yes, check remaining bytes via slow compare
- test edi,3 ; see if at dword alignment
- je scanloop ; already aligned
-
- slowchk:
- cmp WORD PTR ds:[edi],CR+(256*LF) ; see if at CR/LF pair
- je addline ; yes
- inc edi
- jmp alignchk
-
- ; scan for CR/LF pairs in the buffer.
- ; match checks can be made in advance of previous locations IF they are
- ; within one byte of the previous location, otherwise previous locations
- ; may match first.
- ; this testing order looks somewhat strange, but improves Pentium
- ; performance by pairing instructions for the UV pipelines with a minimum
- ; of stalls.
- scanloop:
- mov eax,ds:[edi]
- mov ebx,ds:[edi+4]
-
- cmp ax,CR+(256*LF)
- je match1
- shr eax,16
- mov ecx,ds:[edi+1]
- mov edx,ds:[edi+5]
-
- cmp ax,CR+(256*LF)
- je match3
- cmp cx,CR+(256*LF)
- je match2
- shr ecx,16
-
- cmp bx,CR+(256*LF)
- je match5
- shr ebx,16
- cmp cx,CR+(256*LF)
- je match4
- cmp dx,CR+(256*LF)
- je match6
- shr edx,16
-
- cmp bx,CR+(256*LF)
- je match7
- cmp dx,CR+(256*LF)
- je match8
-
- add edi,8
- jmp scanloop
-
- ; matches on CR/LF pair
- ; location determines adjustment to next line
- match1:
- mov edx,2
- jmp addline
-
- match2:
- mov edx,3
- jmp addline
-
- match3:
- mov edx,4
- jmp addline
-
- match4:
- mov edx,5
- jmp addline
-
- match5:
- mov edx,6
- jmp addline
-
- match6:
- mov edx,7
- jmp addline
-
- match7:
- mov edx,8
- jmp addline
-
- match8:
- mov edx,9
- jmp addline
-
- stpdone:
- push gs ; restore ds -> DGROUP
- pop ds
- ret
-
- ; grow the pointer array by 64K
- growarray:
- mov ax,es ; input buffer selector to grow
- mov ecx,gs:PointerArraySize
- add ecx,65536
- mov gs:PointerArraySize,ecx
- call ResizeMemory
- jmp storearray
-
- SetTextPointers ENDP
-
- ;**********
- ; SORTINFO
- ;**********
- ; sort information, using either an optimized simple sort if no sort parameters
- ; are specified or a slower, parameter-checking sort. The performance
- ; decrease compared to the simple sort is quite significant, so don't
- ; use the fixed length, offset, or sort order settings if possible.
-
- SortInfo PROC NEAR
- mov al,IsFixedLengthOption
- or al,IsSortOffsetOption
- or al,IsSortOrderOption ; see if any special sort parameters in use
- jne sspspec ; use special sort
-
- call SimpleShellSort
- ret
-
- sspspec:
- call ParameterShellSort
- ret
- SortInfo ENDP
-
- ;*****************
- ; SIMPLESHELLSORT
- ;*****************
- ; sort the information in the input file, defaults to simple and fast
- ; the sort is a shell sort and follows this C code:
- COMMENT ^
- shellsort(int a[],int N)
- {
- int i,j,h,v;
-
- for(h=1;h<=N/9;h=3*h+1)
- ;
- for(;h>0;h/=3){
- for(i=h+1;i<=N;i++){
- v=a[i];
- j=i;
- while(j>h && a[j-h]>v){
- a[j]=a[j-h];
- j-=h;
- }
- a[j]=v;
- }
- }
- }
- END COMMENT ^
-
- SimpleShellSort PROC NEAR
- mov eax,LineCount
- cmp eax,1
- jbe siret ; 1 line is sorted by definition
-
- mov fs,PointerSelector
- mov ds,BufferSelector
-
- ; sort the symbol names
- ; fs -> pointer array
- ; ds -> input buffer
- ; gs -> DGROUP
- xor ebx,ebx
- mov edx,ebx
- mov bl,9
- div ebx
- mov ecx,eax ; ecx == quotient, N/9
-
- ; for (h=1;h<=N/9;h=3*h+1);
- mov eax,ebx ; eax==9
- mov al,1 ; eax==1, h
- mov bl,3 ; ebx==3
- xor edx,edx ; zero for multiply loop
-
- sethloop:
- cmp eax,ecx ; h<=N/9
- ja sort2
- mul ebx ; 3*h, assume 32-bit result (pretty safe bet)
- inc eax ; 3*h+1
- jmp sethloop
-
- ; ebx will play role of j, edx will play role of h
- sort2:
- mov edx,eax ; edx == h
-
- ; for (;h>0;...
- hloop:
- or edx,edx ; h>0
- je sortend
-
- ; for(i=h+1...
- mov eax,edx
- inc eax
- mov gs:iValue,eax
-
- ; for(...;i<=N;...){
- iloop:
- mov eax,gs:iValue
- cmp eax,gs:LineCount
- ja nexth
-
- mov ecx,fs:[4*eax]
- mov gs:vValue,ecx ; v=a[i]
- mov ebx,eax ; j=i
-
- ; while(j>h && a[j-h]>v){
- whileloop:
- cmp ebx,edx ; j>h
- jbe whilefail
-
- mov eax,ebx
- sub eax,edx ; eax==j-h
- xor ecx,ecx ; zero high bytes of register for following repe
-
- mov esi,fs:[4*eax] ; ds:esi -> a[j-h]
- mov edi,gs:vValue ; ds:edi==v
-
- comploop:
- mov ax,ds:[esi]
- mov cx,ds:[edi]
- cmp ax,CR+(256*LF)
- je whilefail ; first <= second, a[j-h]<v
- cmp cx,CR+(256*LF) ; check if first >= second
- je dochange ; first > second, modify a[j]
- cmp al,cl
- jb whilefail ; first < second, a[j-h]<v
- jne dochange ; first > second, modify a[j]
- inc esi
- inc edi
- jmp comploop
-
- dochange:
- mov eax,ebx
- sub eax,edx ; eax==j-h
- mov eax,fs:[4*eax] ; eax==a[j-h]
- mov fs:[4*ebx],eax ; a[j]=a[j-h]
- sub ebx,edx ; j-=h
- jmp whileloop
-
- whilefail:
- mov eax,gs:vValue
- mov fs:[4*ebx],eax ; a[j]=v
-
- ; for(...;i++){
- inc gs:iValue
- jmp iloop
-
- ; for (...;h/=3){
- nexth:
- mov eax,edx
- xor edx,edx
- mov ecx,edx
- mov cl,3
- div ecx
- mov edx,eax
- jmp hloop
-
- sortend:
- mov ax,DGROUP
- mov ds,ax
-
- siret:
- ret
- SimpleShellSort ENDP
-
- ;********************
- ; PARAMETERSHELLSORT
- ;********************
- ; sort the information in the input file according to specified parameters
- ; this is also a shell sort, but slower than the simple sort version.
- ; the heart of the sort routine has replaceable parts depending on the option
- ; parameter which has been specified.
-
- ParameterShellSort PROC NEAR
- mov eax,LineCount
- cmp eax,1
- jbe paret ; 1 line is sorted by definition
-
- cmp IsSortOffsetOption,OFF ; check if sort offset
- je pss2 ; no
-
- ; change default logic in sort
- mov SetOffsetCounterAddress,OFFSET OffsetCounterLogic
- mov SortOffsetLogicAddress,OFFSET SortOffsetLogic ; add sort offset logic
-
- pss2:
- cmp IsFixedLengthOption,OFF ; see if fixed length sort option
- je pss3 ; no
-
- ; change default logic in sort
- mov FixedCounterAddress,OFFSET FixedCounterLogic
- mov FixedMoveAddress,OFFSET FixedMoveLogic
- mov FIxedJumpAddress,OFFSET FixedJumpLogic
-
- pss3:
- cmp IsSortOrderOption,OFF ; see if sort order option
- je pss4 ; no
-
- ; change default logic in sort
- mov SortLookupAddress,OFFSET SortLookupLogic
-
- pss4:
- mov fs,PointerSelector
- mov ds,BufferSelector
-
- ; sort the symbol names
- ; fs -> pointer array
- ; ds -> input buffer
- ; gs -> DGROUP
- xor ebx,ebx
- mov edx,ebx
- mov bl,9
- div ebx
- mov ecx,eax ; ecx == quotient, N/9
-
- ; for (h=1;h<=N/9;h=3*h+1);
- mov eax,ebx ; eax==9
- mov al,1 ; eax==1, h
- mov bl,3 ; ebx==3
- xor edx,edx ; zero for multiply loop
-
- pasetpahloop:
- cmp eax,ecx ; h<=N/9
- ja pasort2
- mul ebx ; 3*h, assume 32-bit result (pretty safe bet)
- inc eax ; 3*h+1
- jmp pasetpahloop
-
- ; ebx will play role of j, edx will play role of h
- pasort2:
- mov edx,eax ; edx == h
-
- ; for (;h>0;...
- pahloop:
- or edx,edx ; h>0
- je pasortend
-
- ; for(i=h+1...
- mov eax,edx
- inc eax
- mov gs:iValue,eax
-
- ; for(...;i<=N;...){
- pailoop:
- mov eax,gs:iValue
- cmp eax,gs:LineCount
- ja panexth
-
- mov ecx,fs:[4*eax]
- mov gs:vValue,ecx ; v=a[i]
- mov ebx,eax ; j=i
-
- ; while(j>h && a[j-h]>v){
- pawhileloop:
- cmp ebx,edx ; j>h
- jbe pawhilefail
-
- mov eax,ebx
- sub eax,edx ; eax==j-h
- xor ecx,ecx ; zero high bytes of register for following repe
-
- mov esi,fs:[4*eax] ; ds:esi -> a[j-h]
- mov edi,gs:vValue ; es:edi==v
-
- jmp DWORD PTR gs:[SetOffsetCounterAddress]
-
- pastsetoff:
-
- jmp DWORD PTR gs:[FixedCounterAddress]
-
- pacomploop:
-
- jmp DWORD PTR gs:[FixedMoveAddress]
-
- pastmove:
- inc esi
- inc edi
-
- jmp DWORD PTR gs:[SortOffsetLogicAddress]
-
- pastoffset:
- jmp DWORD PTR gs:[SortLookupAddress]
-
- padocomp:
- cmp al,cl
- jb pawhilefail ; first < second, a[j-h]<v
- jne padochange ; first > second, modify a[j]
-
- jmp DWORD PTR gs:[FixedJumpAddress]
-
- padochange:
- mov eax,ebx
- sub eax,edx ; eax==j-h
- mov eax,fs:[4*eax] ; eax==a[j-h]
- mov fs:[4*ebx],eax ; a[j]=a[j-h]
- sub ebx,edx ; j-=h
- jmp pawhileloop
-
- pawhilefail:
- mov eax,gs:vValue
- mov fs:[4*ebx],eax ; a[j]=v
-
- ; for(...;i++){
- inc gs:iValue
- jmp pailoop
-
- ; for (...;h/=3){
- panexth:
- mov eax,edx
- xor edx,edx
- mov ecx,edx
- mov cl,3
- div ecx
- mov edx,eax
- jmp pahloop
-
- pasortend:
- mov ax,DGROUP
- mov ds,ax
-
- paret:
- ret
-
- ; variable logic routines for different sort parameters follows
-
- ; no counter to set
- ; has to be constructed as label near to shut up ML 6 griping
- NoOffsetCounterLogic LABEL NEAR
- jmp pastsetoff ; simple processing return
-
- ; set offset counter for sort offset processing
- OffsetCounterLogic:
- mov eax,gs:SortOffsetValue
- mov gs:SortOffsetCounter,eax
- jmp pastsetoff
-
- ; no sort offset logic
- NoSortOffsetLogic LABEL NEAR
- jmp pastoffset
-
- ; sort offset logic
- SortOffsetLogic:
- dec gs:SortOffsetCounter ; drop counter of sort offset
- jg pacomploop ; still positive nonzero
- jmp pastoffset ; sort offset has been decremented down, continue with sort
-
- ; no fixed counter logic
- NoFixedCounterLogic LABEL NEAR
- jmp pacomploop
-
- ; fixed length sort counter logic
- FixedCounterLogic:
- mov eax,gs:FixedLengthSize
- mov gs:FixedLengthCounter,eax
- jmp pacomploop
-
- ; no fixed move logic
- NoFixedMoveLogic LABEL NEAR
- mov ax,ds:[esi]
- mov cx,ds:[edi]
- cmp ax,CR+(256*LF)
- je pawhilefail ; first <= second, a[j-h]<v
- cmp cx,CR+(256*LF) ; check if first >= second
- je padochange ; first > second, modify a[j]
- jmp pastmove
-
- ; fixed length sort move logic
- FixedMoveLogic:
- mov al,ds:[esi]
- mov cl,ds:[edi]
- jmp pastmove
-
- ; no fixed jump logic
- NoFixedJumpLogic LABEL NEAR
- jmp pacomploop
-
- ; fixed length sort jump logic
- FixedJumpLogic:
- dec gs:FixedLengthCounter ; drop count of bytes to check
- jne pacomploop ; more bytes to check
- jmp pawhilefail ; equal length of field
-
- ; no sort order lookup table logic
- NoSortLookupLogic LABEL NEAR
- jmp padocomp
-
- ; sort order lookup table logic
- SortLookupLogic:
- movzx eax,al ; get offsets in sort order table
- movzx ecx,cl
- mov al,gs:[SortOrderTable+eax] ; get new lookup compare values
- mov cl,gs:[SortOrderTable+ecx]
- jmp padocomp
-
- ParameterShellSort ENDP
-
- ;*********************
- ; CHECKDUPLICATELINES
- ;*********************
- ; check for and remove duplicate lines if the no duplicates option specified
-
- CheckDuplicateLines PROC NEAR
- push ds ; save critical register
- cmp IsDuplicateOption,OFF
- je cdlret ; duplicate removal not turned on
-
- mov ebx,8
- mov fs,PointerSelector ; fs:ebx -> pointer array, second entry
- mov ecx,LineCount
- dec ecx
- je cdlret ; only one line
-
- mov ds,BufferSelector ; ds -> input buffer
-
- cdllineloop:
- mov esi,fs:[ebx] ; ds:esi -> current line to check against previous
- mov edi,fs:[ebx-4] ; es:edi -> previous line
-
- cmp gs:IsFixedLengthOption,OFF ; see if fixed length option specified
- je cdlvarloop ; no
-
- ; fixed length
- mov edx,gs:FixedLengthSize
-
- cdlfixloop:
- mov al,ds:[esi] ; get current line char
- cmp al,ds:[edi] ; check against previous line's
- jne cdlnext ; no match on lines
- inc esi ; move to next position
- inc edi
- dec edx ; drop count of chars to check
- jne cdlfixloop ; more to check
-
- ; current line matched previous
- ; update input file size with removed character count
- cdlmatch:
- sub esi,fs:[ebx]
- sub gs:InputFileSize,esi
- mov DWORD PTR fs:[ebx-4],-1 ; mark previous line for removal
- jmp cdlnext
-
- ; variable length fields
- cdlvarloop:
- mov ax,ds:[esi] ; get current line char+1
- mov dx,ds:[edi]
- cmp al,dl ; check first line char against previous line's
- jne cdlnext ; no match on lines
- inc esi ; move to next position
- inc edi
- cmp ax,CR+(256*LF) ; see if at end of first line
- je cdlfirstend ; yes
- cmp dx,CR+(256*LF) ; see if at end of second line
- jne cdlvarloop ; no
- jmp cdlnext ; lines don't match, different lengths
-
- ; at end of first line
- cdlfirstend:
- cmp ax,dx ; see if match on EOL
- jne cdlnext ; no
- inc esi ; update offset so can properly update InputFileSize
- jmp cdlmatch ; yes
-
- cdlnext:
- add ebx,4 ; move to next line entry
- dec ecx ; drop count of lines to check
- jne cdllineloop
-
- cdlret:
- pop ds ; restore critical register
- ret
- CheckDuplicateLines ENDP
-
- ;*******************
- ; BUILDOUTPUTBUFFER
- ;*******************
- ; build output buffer from sorted pointers to input buffer
-
- BuildOutputBuffer PROC NEAR
- push ds ; save critical register
- mov eax,InputFileSize
- call GetMemory ; attempt to allocate sufficient memory to hold file
- mov OutputSelector,ax ; save selector
- xor edi,edi
- mov ebx,4
- mov fs,PointerSelector ; fs:ebx -> pointer array
- mov es,ax ; es:edi -> output buffer
- mov ecx,LineCount
- mov ebp,4 ; increment for next entry
- cmp IsReverseOption,ON ; see if reversing normal order
- jne bo2 ; no
- mov ebp,ecx
- dec ebp ; make relative zero
- shl ebp,2 ; dword entry/line
- add ebx,ebp ; ebx -> last entry
- mov ebp,-4 ; increment for next entry
-
- bo2:
- mov ds,BufferSelector ; ds -> input buffer
-
- lineloop:
- mov esi,fs:[ebx] ; ds:esi -> current line to transfer
- add ebx,ebp ; move to next pointer in array
- cmp esi,-1 ; see if marked for removal
- je nextline ; yes
-
- cmp gs:IsFixedLengthOption,OFF ; see if fixed length sort
- je transloop ; no
-
- ; fixed length value transfer, just blast across the character count
- push ecx ; save critical register
- mov ecx,gs:FixedLengthSize
- push ecx
- shr ecx,2
- rep movsd
- pop ecx
- and ecx,3
- rep movsb
- pop ecx ; restore critical register
- jmp nextline
-
- transloop:
- mov ax,ds:[esi]
- add esi,2 ; move to next word in input buffer
- cmp al,CR ; check if possible end of line
- je chkend1
- cmp ah,CR
- je chkend2
-
- dotrans:
- mov es:[edi],ax ; no end of line, transfer characters
- add edi,2 ; move to next word in output buffer
- jmp transloop
-
- chkend1:
- cmp ah,LF ; see if CR/LF pair
- jne dotrans ; no
- mov es:[edi],ax
- add edi,2
- jmp nextline
-
- chkend2:
- cmp BYTE PTR ds:[esi],LF ; see if CR/LF pair
- jne dotrans ; no
- mov es:[edi],ax
- mov BYTE PTR es:[edi+2],LF
- add edi,3
-
- nextline:
- dec ecx
- jne lineloop
-
- ; release the input buffer and pointer buffer to free up memory and
- ; possible disk space
- pop ds ; restore critical register
- mov ax,BufferSelector
- call ReleaseMemory
- mov BufferSelector,0
- mov ax,PointerSelector
- call ReleaseMemory
- mov PointerSelector,0
- ret
- BuildOutputBuffer ENDP
-
- ;**********
- ; READFILE
- ;**********
- ; read file
- ; upon entry bx == file handle, cx == bytes to read,
- ; ds:edx -> read buffer
- ; return carry set if error, otherwise ax == bytes read
-
- ReadFile PROC NEAR
- mov ah,3fh ; read from file
- int 21h
- ret
- ReadFile ENDP
-
- ;********************
- ; WRITEFILETODISK
- ;********************
- ; write sorted input file to disk
- ; return carry flag set if failure,
- ; carry flag reset if success
-
- WriteFileToDisk PROC NEAR
- push ds ; save critical register
-
- mov bx,OutputFileHandle
- mov esi,InputFileSize
- mov ds,OutputSelector ; ds -> output file write buffer
- xor edx,edx
-
- wffileloop:
- mov ecx,esi
- cmp ecx,0fff0h ; see if past maximum
- jbe wfwrite ; no
- mov cx,0fff0h ; set bytes to write to maximum (ecx high word known zero)
-
- wfwrite:
- call WriteFile
- jc wfret ; error during write
- movzx eax,ax ; get bytes written this pass
- add edx,eax ; update buffer write position
- sub esi,eax ; update bytes left to write
- jne wffileloop ; more to write
-
- wfret:
- pop ds ; restore critical register
- ret
- WriteFileToDisk ENDP
-
- ;***********
- ; WRITEFILE
- ;***********
- ; write file
- ; upon entry bx == file handle, cx == bytes to write,
- ; ds:edx -> write buffer
- ; return carry set if error, otherwise ax == bytes written
-
- WriteFile PROC NEAR
- mov ah,40h ; write to file
- int 21h
- ret
- WriteFile ENDP
-
- ;***********
- ; CLOSEFILE
- ;***********
- ; close file
- ; upon entry bx == file handle
- ; return carry set if error, otherwise reset
-
- CloseFile PROC NEAR
- mov ah,3eh ; close file
- int 21h
- ret
- CloseFile ENDP
-
- ;***********
- ; TERMINATE
- ;***********
- ; perform termination functions
-
- Terminate PROC NEAR
- call Cleanup
- call ExitApplication ; no return
- Terminate ENDP
-
- ;*********
- ; CLEANUP
- ;*********
- ; perform cleanup operations prior to exiting
-
- CleanUp PROC NEAR
-
- ; free allocated memory, although not strictly necessary since normal
- ; DOS termination will accomplish the task as well.
- mov ax,BufferSelector
- cmp ax,0 ; see if selector is allocated
- je cu2 ; nope
- call ReleaseMemory
-
- cu2:
- mov ax,PointerSelector
- cmp ax,0 ; see if selector is allocated
- je cu3 ; nope
- call ReleaseMemory
-
- cu3:
- mov ax,OutputSelector
- cmp ax,0 ; see if selector is allocated
- je cu4 ; nope
- call ReleaseMemory
-
- cu4:
- ret
- CleanUp ENDP
-
- ;*****************
- ; EXITAPPLICATION
- ;*****************
- ; exit the application
-
- ExitApplication PROC NEAR
- mov al,ExitCode ; get code to return to calling program
- mov ah,4ch ; exit with return code
- int 21h
- ExitApplication ENDP
-
- ;*************
- ; OUTOFMEMORY
- ;*************
- ; out of memory, give feedback and terminate
-
- OutOfMemory PROC NEAR
- mov eax,DGROUP
- mov ds,eax ; ensure ds -> cwsort data
- mov edx,OFFSET DGROUP:MemoryText
- call DisplayStringCRLF
- mov ExitCode,8
- call Terminate ; no return
- OutOfMemory ENDP
-
- ;
- ;***** CauseWay specific functions which use the CauseWay API *****
- ;
-
- ;***************
- ; RELEASEMEMORY
- ;***************
- ; release previously allocated memory block
- ; upon entry ax == selector of block to release
- ; return carry flag set if error
-
- ReleaseMemory PROC NEAR
- push ebx ; save used registers
- mov bx,ax ; bx == selector of block to release
- mov ax,0ff0fh ; CauseWay RelMem function
- int 31h
- pop ebx ; restored used registers
- ret
- ReleaseMemory ENDP
-
- ;***********
- ; GETMEMORY
- ;***********
- ; allocate memory block, automatically use virtual memory if
- ; available and required (allocation exceeds free physical memory)
- ; upon entry eax == size of block to allocate in bytes
- ; return ax == selector of allocated block
-
- GetMemory PROC NEAR
- push ebx ; save used registers
- push ecx
- mov ecx,eax ; ecx == size of block to allocate
- mov ax,0ff0ch ; CauseWay GetMem32 function
- int 31h
- jc gmerror
- mov ax,bx ; ax == selector of allocated block
- pop ecx ; restored used registers
- pop ebx
- ret
-
- ; error allocating, out of memory
- gmerror:
- call OutOfMemory ; no return
-
- GetMemory ENDP
-
- ;***************
- ;* RESIZEMEMORY
- ;***************
-
- ; resize allocated memory block
- ; upon entry ax == selector, ecx == new size of block in bytes
-
- ResizeMemory PROC NEAR
- push ecx ; save used registers
- push ebx
- mov bx,ax ; selector value to bx
- mov ax,0ff0eh ; CauseWay ResMem32 function
- int 31h
- jc rmerror
- pop ebx ; restore used registers
- pop ecx
- ret
-
- ; error resizing memory
- rmerror:
- call OutOfMemory ; no return
-
- ResizeMemory ENDP
-
- END main
-