;/* IL_SORT.ASM
;
COMMENT ~
PDC Prolog 3.31 & Visual Prolog 4/5(tm) ASSEMBLY LANGUAGE EXTENSIONS
====================================================================
Ultra-fast SORTING PREDICATES for Integer-Lists:
------------------------------------------------
GLOBAL PREDICATES
unsigned il_sort(IL) -(i) language c
unsigned il_sortndup(IL) -(i) language c
% Visual/PDC PROLOG NOTES
% %%%%%%%%%%%%%%%%%%%%%%%
%
% These predicates are incredibly fast, and of 'linear complexity'
% (proportional to N, where N is the number of list-elements).
%
% The algorithm used in the ASSEMBLY source-code of these predicates
% is a variant of Radix-Sort, probably the fastest Sort in the world.
%
% The second predicate also eliminates duplicates from the list while
% sorting it, and is slightly faster than the first.
%========================================================================
~
; Visual/PDC Prolog Memory-Allocation Functions:
extrn _MEM_MarkGStack:far
extrn _MEM_AllocGStack:far
extrn _MEM_ReleaseGStack:far
extrn _MEM_AdjustGStackAlloc:far
IDEAL
MODEL large
DATASEG
t512a dw 256 dup (0)
CODESEG
P386N
; ========================== LOCAL PROCEDURES: ==========================
PROC phase_1 near
push ds ;
cld ;forwards
; ***********************************************************************
; ***** PHASE 'ZERO': Clear the 512-byte-"HISTOGRAM table" (t512a): *****
; ***********************************************************************
mov si,di ;make SI=offset_of_list
mov ax,es ;
mov di,offset DS:t512a ;
mov bx,ds ;
mov ds,ax ;make DS:SI=list
mov es,bx ;make ES:DI=local_table
mov cx,128 ;make cx=128 (times 4 this is 512)
xor eax,eax ;use eax for clearing 512 bytes
mov bx,di ;save table1_offset also in bx
rep stosd ;clear 512 bytes in table1
mov di,bx ;recover table-1 offset from bx
; ***********************************************************************
; *** PHASE ONE: Record a HISTOGRAM of hi-bytes occurrences in t512a: ***
; ***********************************************************************
xor cx,cx ;number_of_elements_Counter
jmp short @@Nx1 ;
; ===============================
@@EL1: inc si ;
lodsb ;load hi-byte
xor AL,128 ;
mov bl,al ;
xor bh,bh ;prepare BX as an array-index-assistant
shl bx,1 ;times 2 (since words, not bytes)
MASM
mov dx,word ptr ES:[DI+BX] ;get current 'occurrences_number'
inc dx ;increase it
mov word ptr ES:[DI+BX],dx ;store the new value
IDEAL
inc cx ;add 1 to Counter_of_elements
lodsw ;next pointer-offset in AX
mov bx,ax ;also in BX
lodsw ;next pointer-segment in AX
mov ds,ax ;also in DS
mov si,bx ;now offset also in SI
; ===============================
@@Nx1: lodsb ;load first byte of list-element
dec al ;is list-element NORMAL? (=1)?
jz @@EL1 ;if so, continue loop,
pop ds ;
ret
ENDP phase_1
; -----------------------------------------------------------------------
PROC phase_2 near
; ***********************************************************************
; **** PHASE TWO: Turn occurrence-numbers into "Hotel Reservations": ****
; ***********************************************************************
mov si,di ;copy offset of table-1 also to SI
add di,512 ;make di=table2_offset (512 bytes later)
mov dx,di ;put this also in DX
add dx,512 ;512 bytes later is 'tourist_buffer'
mov ax,es ;
mov ds,ax ;make table_segment = DS
xor cl,cl ;clear CL to use it as an 'ASCII-counter'
jmp short @@PH2 ;go to middle of next loop
; ===============================
@@PH2a: stosw ;write (zero-)occurrences_number to table-2
inc cl ;increment ascii-pointer;
jz @@PH2x ;when it becomes again zero (at ASCII 256), exit
; -------------------------------
@@PH2: lodsw ;load occurrences_number from table-1(histogram)
or ax,ax ;a zero?
jz @@PH2a ;if so, write it as-it-is, and repeat
xchg ax,dx ;else: swap {DX-occur/s_number,AX-DX}
stosw ;write DX (temporarily turned into AX),
xchg ax,dx ;then restore {DX,AX},
add dx,ax ;then add current_occurences_number to DX
inc cl ;then increment the ascii-pointer CL,
jnz @@PH2 ;and till its 0 again repeat (256 times)
; ===============================
@@PH2x: mov cx,si ;
ret ;(now cx is table-2 offset, di is tourist_offset)
ENDP phase_2
; -----------------------------------------------------------------------
PROC phase_3 near
; ***********************************************************************
; *** PHASE THREE: Use "Hotel Reservations" to allocate tourists! :-) ***
; ***********************************************************************
jmp short @@Nx1 ;
; ===============================
@@EL1: inc si
mov bl,byte ptr DS:SI ;load hi-byte of list into BL
xor bl,128 ;
xor bh,bh ;prepare BX as an array-index-assistant
shl bx,1 ;times 2 (since words, not bytes)
mov di,cx ;put table2_offset in DI
dec si ;
MASM
mov di,word ptr ES:[DI+BX] ;load 'reservation_pointer' in DI
movsb ;copy byte from list to str_buf
inc si ;advance once more
mov ax,di ;put the new DI in AX
mov di,cx ;put again in DI the table_offset
mov word ptr ES:[DI+BX],ax ;update the 'reservation_pointer'
IDEAL
lodsw ;next pointer-offset in AX
mov dx,ax ;also in DX
lodsw ;next pointer-segment in AX
mov ds,ax ;also in DS
mov si,dx ;now offset also in SI
; ===============================
@@Nx1: lodsb ;load first byte of list-element
dec al ;is list-element NORMAL? (=1)?
jz @@EL1 ;if so, continue loop,
; =======================
ret
ENDP phase_3
; -----------------------------------------------------------------------
PROC phase_4a near
; ***********************************************************************
; **** Part of Phase_4_5 as well as Phase_4_5a (common code re-used) ****
; ***********************************************************************
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
; NOTE NOW: DS:SI = ES:SI ="local_binary_input", CX = number of elements,
; ES:DI = DS:DI =binary_output, AL="common character to write rightwards:
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
push ax ;save ASCII-num. to write rightwards, temporarily
push di ;save the output_buffer_offset again, temporarily
push es ;save the output_buffer_segment
mov ax,ds ;
mov es,ax ;make ES=DS
mov di,dx ;use table2_offset as a "new destination"
mov bx,di ;save the table2-offset, also in bx
mov dx,cx ;save the "tourist group size" CX, in DX
mov cx,128 ;use 128 (times 4 bytes) to clear table-2
xor eax,eax ;prepare empty register, to clear table-2
rep stosd ;clear 512 bytes (in table-2)
mov cx,dx ;recover CX (size of this group) from DX
mov di,bx ;recover table2_offset (DI) from bx
; ===============================
@@PH4d: lodsb ;load a byte from the "tourist_buffer"
mov bl,al ;put it in BL
xor bh,bh ;prepare BX as an array-index-assistant
shl bx,1 ;times 2 since words, not bytes
MASM
mov dx,word ptr ES:[DI+BX] ;get occurrences_number
inc dx ;increment it once
mov word ptr ES:[DI+BX],dx ;store the new value
IDEAL
loop @@PH4d ;repeat for all elements of this "group"
; ------------------------------> NOTE: di has remained unchanged!
mov si,di ;now ES:SI=table2_start
pop es ;recover binary_output_segment
pop di ;recover binary_output_offset
pop ax ;recover ASCII-byte to "write leftwards"
ret
ENDP phase_4a
; -----------------------------------------------------------------------
PROC phase_4_5 near
; ***********************************************************************
; *** PHASE FOUR: Return the "tourists" home... SORTED this time! :-) ***
; ***********************************************************************
; assumes: ES:DI=list(as output now), DS:SI=table1(occurrences)
; DS:SI=table2(temporary), DS:[SI+1024]='tourist_buffer'
; =======================
mov dx,si ;copy offset of table-1 into DX
add dx,512 ;now DX is offset of table-2(temporary)
mov bx,dx ;
add bx,512 ;now BX is offset of 'tourist_buffer'
push dx ;save offset of table-2 in the stack
xor cl,cl ;clear CL (to use it as "ASCII-counter")
; -----------------------------------------------------------------------
; NOW: si=occurrence_table_offset, dx=table2_offset, ES:DI=output_buffer,
; bx=tourist_buffer_offset, cl=ascii_counter (0..255, initially 0)
; =======================================================================
inc di ;increment list by 1 (skip first functor)
jmp short @@PH4m ;goto middle of next loop (the MAIN LOOP)
; -------------------------------
@@PH4: mov dx,si ;save current_table1_offset inside DX
mov si,bx ;put the current "tourist_offset" into SI
movsb ;copy 1 'tourist-byte' to "final output buffer",
mov al,cl ;use as "companion-byte" the current ASCII-number
xor al,128 ;
stosb ;write this, too...
; =======================================
mov eax,dword ptr ES:DI ;next list_offset_and_segment
mov di,ax ;
shr eax,16 ;
mov es,ax ;
inc di ;skip list functor
; =======================================
mov bx,si ;record the next output-pos. back into bx
mov si,dx ;restore the table1_offset from DX, in SI
@@PH4b: inc cl ;increment current ASCII-counter
jz short @@PH4x ;if again zero (i.e. 256) exit this loop!
; ======================================================================
; >>>>>>>>>>>>>>>> Middle of MAIN LOOP of "PHASE FOUR": lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;
@@PH4m: lodsw ;(else) load the occurrences_number from table-1
or ax,ax ;is it a zero?
jz @@PH4b ;if so, no point in writing anything; just go on!
dec ax ;else, one less (to "test for zero" more easily):
jz @@PH4 ;if 0 (i.e. a "lonely tourist") move the tourist!
; ====================== else, need to move en entire group of "tourists"
pop dx ;so.... recover start of table-2 (from the stack)
push dx ;and then save it again in the stack,
inc ax ;balance 'dec ax' so that ax="number_of_tourists"
push ax ;put this "tourist group"'s size :-) in the stack
push si ;save the current_offset of the occurrences_table
push bx ;save the "tourist_buffer"'s offset in the stack,
push cx ;finally save the current "ASCII-counter" value,
xchg ax,cx ;swap ax (tourist_group_size) with CL (ascii-num)
mov si,bx ;use the tourist_buffer offset as source-register
; ===============================
call phase_4a ;
; ===============================
; ***********************************************************************
; ************ PHASE FIVE (INNER LOOP within PHASE FOUR): ***************
; ***********************************************************************
; Now ds:si is a "local occurrence_table", ES:DI = original output_buffer
; and AL = "local common byte" (to write rightwards, after each element):
; =======================================================================
xor cl,cl ;prepare CL as a 'local ascii-counter'
mov ch,al ;move rightwardly_writeable char. to CH
XOR CH,128 ;
jmp short @@PH5 ;jump to middle of next loop
; ===============================
@@PH5a: inc cl ;increment the 'local ascii-number', CL
jz @@PH5b ;if reached 0 (i.e. 256) exit this loop!
; -------------------------------
@@PH5: lodsw ;(else) load "occurrences_number"
or ax,ax ;is it a zero (i.e. no occurrences)?
jz @@PH5a ;if so, don't write anything (but go on)
xchg ax,cx ;now {AL,AH}=byte_pair, CX="occurrences"
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@@Ldump: stosw ;write as many byte_pairs AS OCCURRENCES
mov ebx,dword ptr ES:DI ;
mov di,bx ;
shr ebx,16 ;
mov es,bx ;
inc di ;
loop @@Ldump ;
;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;
mov cx,ax ;restore CL=count,CH=char_right, from AX
inc cl ;increment the "local ascii_counter", CL
jnz @@PH5 ;if not reached 0 (i.e. 256), repeat loop
; ///////////////////////////////////////////////////////////////////////
@@PH5b: pop cx ;now retrieve the current "ASCII-Counter" value,
pop bx ;and also recover the old "tourist_buffer_offset"
pop si ;and recover current offset of occurrences_table
pop ax ;also recover this "tourist group"'s size, in AX,
add bx,ax ;now add this to current offset of tourist_buffer
inc cl ;and finally increment the current ASCII-number,
jnz @@PH4m ;if not 0 (i.e.256) repeat PHASE FOUR's MAIN LOOP
; =======================================================================
@@PH4x: pop cx ;balance the stack (for saving start of table-2)
ret
ENDP phase_4_5
; -----------------------------------------------------------------------
PROC phase_4b near
; ***********************************************************************
; *********************** Part of Phase_nd_4_5 *************************
; ***********************************************************************
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
; NOTE NOW: DS:SI = ES:SI ="local_binary_input", CX = number of elements,
; ES:DI = DS:DI =binary_output, AL="common character to write rightwards:
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
push ax ;save ASCII-num. to write rightwards, temporarily
push di ;save the output_buffer_offset again, temporarily
push es ;save the output_buffer_segment
mov ax,ds ;
mov es,ax ;make ES=DS
mov di,dx ;use table2_offset as a "new destination"
mov bx,di ;save the table2-offset, also in bx
mov dx,cx ;save the "tourist group size" CX, in DX
mov cx,64 ;use 64 (times 4 bytes) to clear table-2
xor eax,eax ;prepare empty register, to clear table-2
rep stosd ;clear 256 bytes (in table-2)
mov cx,dx ;recover CX (size of this group) from DX
mov di,bx ;recover table2_offset (DI) from bx
; ===============================
@@PH4d: lodsb ;load a byte from the "tourist_buffer"
mov bl,al ;put it in BL
xor bh,bh ;prepare BX as an array-index-assistant
MASM
mov byte ptr ES:[DI+BX],al ;
IDEAL
loop @@PH4d ;repeat for all elements of this "group"
; ------------------------------ NOTE: di has remained unchanged!
mov si,di ;now ES:SI=table2_start
pop es ;recover binary_output_segment
pop di ;recover binary_output_offset
pop ax ;recover ASCII-byte to "write leftwards"
ret
ENDP phase_4b
; -----------------------------------------------------------------------
PROC phase_nd_4_5 near
; ***********************************************************************
; *** PHASE FOUR: Return the "tourists" home... SORTED this time! :-) ***
; ***********************************************************************
; assumes: ES:DI=list(as output now), DS:SI=table1(occurrences)
; DS:SI=table2(temporary), DS:[SI+1024]='tourist_buffer'
; =======================
xor edx,edx ;
mov dx,si ;copy offset of table-1 into DX
add dx,512 ;now DX is offset of table-2(temporary)
mov bx,dx ;
add bx,512 ;now BX is offset of 'tourist_buffer'
push dx ;save offset of table-2 in the stack
xor cl,cl ;clear CL (to use it as "ASCII-counter")
; -----------------------------------------------------------------------
; NOW: si=occurrence_table_offset, dx=table2_offset, ES:DI=output_buffer,
; bx=tourist_buffer_offset, cl=ascii_counter (0..255, initially 0)
; =======================================================================
inc di ;increment list by 1 (skip first functor)
jmp short @@PH4m ;goto middle of next loop (the MAIN LOOP)
; -------------------------------
@@PH4: mov dx,si ;save current_table1_offset inside DX
mov si,bx ;put the current "tourist_offset" into SI
movsb ;copy 1 'tourist-byte' to "final output buffer",
mov al,cl ;use as "companion-byte" the current ASCII-number
stosb ;write this, too...
; =======================================
mov eax,dword ptr ES:DI ;next list_offset_and_segment
mov di,ax ;
shr eax,16 ;
mov es,ax ;
inc di ;skip list functor
; =======================================
mov bx,si ;record the next output-pos. back into bx
mov si,dx ;restore the table1_offset from DX, in SI
ror edx,16 ;
inc dx ;increment list-element counter
ror edx,16 ;
@@PH4b: inc cl ;increment current ASCII-counter
jz short @@PH4x ;if again zero (i.e. 256) exit this loop!
; ======================================================================
; >>>>>>>>>>>>>>> Middle of MAIN LOOP of "PHASE FOUR": lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;
@@PH4m: lodsw ;(else) load the occurrences_number from table-1
or ax,ax ;is it a zero?
jz @@PH4b ;if so, no point in writing anything; just go on!
dec ax ;else, one less (to "test for zero" more easily):
jz @@PH4 ;if 0 (i.e. a "lonely tourist") move the tourist!
; ====================== else, need to move en entire group of "tourists"
pop dx ;so.... recover start of table-2 (from the stack)
push dx ;and then save it again in the stack,
inc ax ;balance 'dec ax' so that ax="number_of_tourists"
push ax ;put this "tourist group"'s size :-) in the stack
push si ;save the current_offset of the occurrences_table
push bx ;save the "tourist_buffer"'s offset in the stack,
push cx ;finally save the current "ASCII-counter" value,
xchg ax,cx ;swap ax (tourist_group_size) with CL (ascii-num)
mov si,bx ;use the tourist_buffer offset as source-register
; ===============================
call phase_4b ;
; ===============================
; ***********************************************************************
; ************ PHASE FIVE (INNER LOOP within PHASE FOUR): ***************
; ***********************************************************************
; Now ds:si is a "local occurrence_table", ES:DI = original output_buffer
; and AL = "local common byte" (to write rightwards, after each element):
; =======================================================================
xor cl,cl ;prepare CL as a 'local ascii-counter'
mov ah,al ;move rightwardly_writeable char. to AH
XOR AH,128 ;
jmp short @@PH5 ;jump to middle of next loop
; ===============================
@@PH5a: inc cl ;increment the 'local ascii-number', CL
jz @@PH5b ;if reached 0 (i.e. 256) exit this loop!
; -------------------------------
@@PH5: lodsb ;(else) load byte from table
or al,al ;is it a zero (i.e. no occurrences)?
jz @@PH5a ;if so, don't write anything (but go on)
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
stosw ;write the byte_pair
mov ebx,dword ptr ES:DI ;
mov di,bx ;
shr ebx,16 ;
mov es,bx ;
inc di ;skip list_functor
ror edx,16 ;
inc dx ;increment list-element counter
ror edx,16 ;
;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;lt;
inc cl ;increment the "local ascii_counter", CL
jnz @@PH5 ;if not reached 0 (i.e. 256), repeat loop
; ///////////////////////////////////////////////////////////////////////
@@PH5b: pop cx ;now retrieve the current "ASCII-Counter" value,
pop bx ;and also recover the old "tourist_buffer_offset"
pop si ;and recover current offset of occurrences_table
pop ax ;also recover this "tourist group"'s size, in AX,
add bx,ax ;now add this to current offset of tourist_buffer
inc cl ;and finally increment the current ASCII-number,
jnz @@PH4m ;if not 0 (i.e.256) repeat PHASE FOUR's MAIN LOOP
; =======================================================================
@@PH4x: pop cx ;balance the stack (for saving start of table-2)
dec di ;go back to last list-functor
mov al,02h ;
stosb ;mark end of list at that point
ret
ENDP phase_nd_4_5
; ======================== PUBLIC PREDICATES: ==========================
public _il_sort ;-(i)
; Updates the input number-list 'destructively', overwriting old values.
; Uses temporary GStack-Memory Allocation. The number of temporary extra
; bytes required to sort a list of N numbers, is equal to N/2+1024. Note
; that for large N (e.g. 32000), this is almost N/2 (16000), i.e. 17024.
PROC _il_sort far
ARG ilist:dword
ENTER 2,0
push ds
push si
push es
push di
; ===============================
cld ;
call _MEM_MarkGStack ;
push dx ;
push ax ;
; ===============================
les di,[ilist] ;input-list..............................ARG-1
push es ;save segment of input in the stack
push di ;save offset of input in the stack
; \\\\\\\\\\\\\\\\\\\\\\\
call phase_1 ;get length in CX, histogram in t512a(table)
mov [bp-2],cx ;
; ///////////////////////
push ds ;
push di ;
push cx ;save the length in the stack
add cx,1024 ;add space for 2 temporary tables in it
push cx ;push it as a parameter (bytes to allocate)
call _MEM_AllocGStack ;allocate space in the GStack
pop cx ;balance
mov di,ax ;put offset of 'fresh' binary in DI
mov bx,di ;copy it also to BX
mov es,dx ;put segment of 'fresh' binary in ES
pop dx ;recover number_of_elements, but in DX
pop si ;recover start of t512a (dataseg-table)
pop ds ;recover standard data_segment
mov cx,128 ;
rep movsd ;copy t512a to new table-1 in GStack
mov di,bx ;recover start of 'fresh' binary
mov cx,dx ;put number_of_elements in CX
push di ;save the temporary buffer offset in the stack
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
call phase_2 ;
; ///////////////////////////////
pop di ;
pop si ;recover offset of input, but in SI
pop ds ;recover segment of input, but in DS
push di ;
call phase_3 ;
; ///////////////////////////////
pop si ;recover the temporary buffer offset, but in SI
mov ax,es ;
mov ds,ax ;now DS:SI=temporary_buffer
les di,[ilist] ;and ES:DI=list(now as output)....ARG-1
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
call phase_4_5 ;
; ///////////////////////////////
pop ax ;recover offset of GStack_array
pop dx ;recover segment of GStack_array
push dx ;push segment as parameter
push ax ;push offset as parameter
call _MEM_ReleaseGStack ;Release temporary GStack-memory used
pop cx ;balance the stack
pop cx ;balance the stack
; -------------------------------
mov ax,[bp-2] ;return number of elements
; ===============================
pop di
pop es
pop si
pop ds
LEAVE
ret
ENDP _il_sort
; -----------------------------------------------------------------------
public _il_sortndup ;-(i)
; Same as 'il_sort/1', but removes from the list all duplicate elements.
; Also slightly faster than 'il_sort/1', as a result.
PROC _il_sortndup far
ARG ilist:dword
ENTER 0,0
push ds
push si
push es
push di
; ===============================
cld ;
call _MEM_MarkGStack ;
push dx ;
push ax ;
; ===============================
les di,[ilist] ;input-list..............................ARG-1
push es ;save segment of input in the stack
push di ;save offset of input in the stack
; \\\\\\\\\\\\\\\\\\\\\\\
call phase_1 ;get length in CX, histogram in t512a(table)
; ///////////////////////
push ds ;
push di ;
push cx ;save the length in the stack
add cx,1024 ;add space for 2 temporary tables in it
push cx ;push it as a parameter (bytes to allocate)
call _MEM_AllocGStack ;allocate space in the GStack
pop cx ;balance
mov di,ax ;put offset of 'fresh' binary in DI
mov bx,di ;copy it also to BX
mov es,dx ;put segment of 'fresh' binary in ES
pop dx ;recover number_of_elements, but in DX
pop si ;recover start of t512a (dataseg-table)
pop ds ;recover standard data_segment
mov cx,128 ;
rep movsd ;copy t512a to new table-1 in GStack
mov di,bx ;recover start of 'fresh' binary
mov cx,dx ;put number_of_elements in CX
push di ;save the temporary buffer offset in the stack
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
call phase_2 ;
; ///////////////////////////////
pop di ;
pop si ;recover offset of input, but in SI
pop ds ;recover segment of input, but in DS
push di ;
call phase_3 ;
; ///////////////////////////////
pop si ;recover the temporary buffer offset, but in SI
mov ax,es ;
mov ds,ax ;now DS:SI=temporary_buffer
les di,[ilist] ;and ES:DI=list(now as output)....ARG-1
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
call phase_nd_4_5 ;
; ///////////////////////////////
pop ax ;recover offset of GStack_array
pop dx ;recover segment of GStack_array
push dx ;push segment as parameter
push ax ;push offset as parameter
call _MEM_ReleaseGStack ;Release temporary GStack-memory used
pop cx ;balance the stack
pop cx ;balance the stack
; ===============================
ror edx,16 ;
mov ax,dx ;return number of list-elements
; =======================
pop di
pop es
pop si
pop ds
LEAVE
ret
ENDP _il_sortndup
END ;*/
ifndef include_defs
CONSTANTS
test_il_tobin = 1
include ".\\AUXPREDS.DOM"
GLOBAL PREDICATES
unsigned il_sort(IL) -(i) language c
unsigned il_sortndup(IL) -(i) language c
include ".\\AUXPREDS.INC"
PREDICATES
do_il_sort(INTEGER)
GOAL
do_il_sort(1), do_il_sort(2), do_il_sort(3), do_il_sort(4).
enddef
PREDICATES
fill_random(unsigned,CHAR,binary)
write_array(CHAR,unsigned,unsigned,binary)
showbinx(unsigned,unsigned,binary)
showelement(INTEGER,INTEGER)
mywritef(CHAR,CHAR,CHAR)
CLAUSES
do_il_sort(1):- attribute(A), rep, attribute(79),
write("testing: unsigned il_sort(ilist) -(i)\n"), attribute(14),
write("\n\nHow many numbers in the array?\n-> "), attribute(15),
readint(N), fill_random(N,'n',Bin1), il_tobin(ILx,Bin1),
attribute(14), write("input-list:\n",ILx), nl, Nx=il_sort(ILx),
write("SORTED list:\n",ILx,"\n\nNumber of elements=",Nx), nl,
attribute(A), pkey, !.
do_il_sort(2):- attribute(A), rep, attribute(79),
write("testing: unsigned il_sort(ilist) -(i)\n"), attribute(14),
write("\nHow many numbers in the array?\n-> "),
readint(N), fill_random(N,'n',Bin1), il_tobin(ILx,Bin1),
NN=N+N, openwrite(output,"il_sort.RAW"), writedevice(output),
write_array('\n',0,NN,Bin1), closefile(output),
system("LIST il_sort.RAW"), il_sort(ILx), il_tobin(ILx,0,Bin1),
openwrite(output,"il_sort.SRT"), writedevice(output),
write_array('\n',0,NN,Bin1), closefile(output),
system("LIST il_sort.SRT"), attribute(A), pkey, !.
do_il_sort(3):- attribute(A), unread_str("[3,2,5,-12,4,5,9,8,4,-12,1,3]"),
rep, attribute(79),
write("testing: unsigned il_sortndup(ilist) -(i)\n"),
attribute(14), prompt(0,"\nGive a list of numbers:\n",Istr),
term_str(il,L,Istr), NewN=il_sortndup(L), nl, attribute(14),
write("This list, after sorting and removing duplicates is:\n "),
attribute(15), write(L), write("\n\nNew Number of elements=",NewN),
attribute(A), nl, pkey, !.
do_il_sort(4):- attribute(A), rep, attribute(79),
write("testing: unsigned il_sortndup(ilist) -(i)\n"), attribute(14),
write("\nHow many numbers in the array?\n-> "), attribute(15),
readint(N), fill_random(N,'n',Bin1), il_tobin(ILx,Bin1),
NN=N+N, openwrite(output,"il_sort.RAW"), writedevice(output),
write_array('\n',0,NN,Bin1), closefile(output),
system("LIST il_sort.RAW"), New=il_sortndup(ILx), il_tobin(ILx,0,Bin1),
openwrite(output,"il_sort.SRT"), writedevice(output),
New2=New+New, write_array('\n',0,New2,Bin1), closefile(output),
system("LIST il_sort.SRT"), nl, attribute(A), pkey, !.
fill_random(NumW,'s',Bin):- bitleft(NumW,1,NumW2), Bin=makebinary(NumW2),
BC=makebinary(2), setwordentry(BC,0,0), rep,
P=getwordentry(BC,0), random(26,Byte1a), random(26,Byte2a),
Byte1=Byte1a+65, Byte2=Byte2a+97,
setbyteentry(Bin,P,Byte1), P2=P+1, setbyteentry(Bin,P2,Byte2),
P3=P2+1, setwordentry(BC,0,P3), P3>=NumW2, !.
fill_random(NumW,'n',Bin):- bitleft(NumW,1,NumW2), Bin=makebinary(NumW2),
BC=makebinary(2), setwordentry(BC,0,0), rep,
P=getwordentry(BC,0), random(Real), RND=cast(unsigned,Real*65535),
setwordentry(Bin,P,RND), PP=P+1, setwordentry(BC,0,PP), PP>=NumW, !.
write_array('\0',Startbyte,Numbytes,Bin):-
bitright(Startbyte,1,Start), bitright(Numbytes,1,NumW),
Bc=makebinary(2), write("lt; "), setwordentry(Bc,0,Start),
getbacktrack(LP), rep, P1=getwordentry(Bc,0),
Word1=getwordentry(Bin,P1), P2=P1+1,
write(Word1,' '), setwordentry(Bc,0,P2),
P2>=NumW, cutbacktrack(LP), write('>'), !.
write_array('\n',Startbyte,Numbytes,Bin):- Bc=makebinary(2),
bitright(Startbyte,1,Start), bitright(Numbytes,1,NumW),
setwordentry(Bc,0,Start),
rep, P1=getwordentry(Bc,0), W1=getwordentry(Bin,P1), P2=P1+1,
W1a=cast(integer,W1),
writef("%6\n",W1a), setwordentry(Bc,0,P2), P2>=NumW, !.
write_array(SepC,Startbyte,Numbytes,Bin):-
Bc=makebinary(2), write('lt;'), setwordentry(Bc,0,Startbyte),
getbacktrack(LP), rep, P1=getwordentry(Bc,0),
Byte1=getbyteentry(Bin,P1), P2=P1+1, Byte2=getbyteentry(Bin,P2),
mywritef(Byte1,Byte2,SepC), Q=P2+1, setwordentry(Bc,0,Q),
Q>=NumBytes, cutbacktrack(LP), write('>'), !.
mywritef(Byte1,Byte2,'\1'):- Byte1>lt;0, Byte2>lt;0,
writef("%c%c",Byte1,Byte2), !.
mywritef(Byte1,Byte2,'\1'):- Byte1>lt;0, Byte2=0,
writef("%c%c",Byte1,'.'), !.
mywritef(Byte1,Byte2,'\1'):- Byte2>lt;0, Byte1=0,
writef("%c%c",'.',Byte2), !.
mywritef(_,_,'\1'):- writef(".."), !.
mywritef(Byte1,Byte2,SepC):- Byte1>lt;0, Byte2>lt;0,
writef("%c%c%c",Byte1,Byte2,SepC), !;
Byte1=0, Byte2=0, write("__%",SepC), !;
Byte1>lt;0, Byte2=0, writef("%c_%",Byte1,SepC), !;
Byte2>lt;0, Byte1=0, writef("%c_%",Byte2,SepC), !.
showbinx(Start,End,Bi):- BC=makebinary(2),
setwordentry(BC,0,Start), rep, P=getwordentry(BC,0),
Byte1=getbyteentry(Bi,P), P2=P+1, Byte2=getbyteentry(Bi,P2),
E=Byte1+(256*Byte2), Pee=(P-Start)/2, showelement(Pee,E),
P3=P2+1, setwordentry(BC,0,P3), P3>=End, !.
showelement(_,0):- !.
showelement(P,N):- writef("%c=%,",P,N), !./
Back to ASM-Library Index
Stathis Services Ltd (Office Automation): http://www.stathis.com