home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / PROGRAM / ASM / ALIB30B / SORT23.ASM < prev    next >
Assembly Source File  |  1994-11-12  |  5KB  |  207 lines

  1. ;***************************** SORT23.ASM ***********************************
  2.  
  3. LIBSEG           segment byte public "LIB"
  4.         assume cs:LIBSEG , ds:nothing
  5. ;----------------------------------------------------------------------------
  6. .xlist
  7.     include  mac.inc
  8.     extrn    dos_mem_allocate:far
  9.     extrn    dos_mem_release:far
  10. .list
  11. comment 
  12. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  SORT   )
  13. ; merge_sort_arrayw - sort array of words. 
  14. ;  inputs:  ds:0 - ptr to word array
  15. ;              cx - number of elements in array (range 2-16383)
  16. ;
  17. ;  Output:  if no carry array is sorted in decending order
  18. ;           carry = insufficient memory
  19. ;           
  20. ;  Note:  merge_sort_arrayw uses 290 bytes for code and allocates
  21. ;         memory to hold array being sorted.
  22. ;  Psuedo code:
  23. ;
  24. ;int array2sort[n]; /* array with indexes from 0 to n-1 as in C */
  25. ;                   /* replace int with whatever datatype you want to sort */
  26. ;int l;          /* length of sorted sets */
  27. ;int first;      /* first element to be sorted */
  28. ;  l=1;
  29. ;  while (l<n)
  30. ;  {
  31. ;    first=0;
  32. ;    while (first+l<n)
  33. ;    {
  34. ;      merge(array2sort[first..first+l-1], array2sort[first+l..first+2*l-1]);
  35. ;      first= first + 2 * l;
  36. ;    }
  37. ;    l= 2*l; /* We now have sorted sets of length 2*l */
  38. ;  }
  39. ;****************************
  40. 
  41. work_seg        dw    0    ;temp index sort area
  42. sort_buffer_seg        dw    0
  43. delta            dw    0
  44. no_sort_flag        db    0    ;set =1 if no sort in merge pass
  45. sorted_flag        db    0    ;set =1 if index already sorted
  46.  
  47.     public    merge_sort_arrayw              
  48. merge_sort_arrayw    proc    far
  49.     apush    ax,bx,cx,dx,si,di,bp,ds,es
  50.     cld
  51.     cmp    cx,1
  52.     jbe    sort_exit        ;jmp if not enough data to sort
  53.     shl    cx,1
  54.     mov    bp,cx            ;bp=sort buffer length (bytes)
  55.     mov    cs:sort_buffer_seg,ds
  56. ;
  57. ; allocate work area
  58. ;
  59.     mov    dx,0
  60.     mov    ax,bp
  61.     call    dos_mem_allocate
  62.     jc    sort_exit3
  63.     mov    cs:work_seg,es
  64.     mov    cs:delta,2
  65.  
  66.         mov    di,cs:delta        ;setup list2 start
  67. lp1:    mov    bx,0            ;setup store ptr for 'merge' routine
  68.     mov    si,0                     ;set si at top of buffer
  69.     mov    cs:sorted_flag,1    ;preload already sorted flag
  70.     
  71. lp2:    call    merge
  72.     mov    cl,cs:no_sort_flag    ;get 1 if no sort occured
  73.     and    cs:sorted_flag,cl    ;keep 1 in sorted_flag if block sorted
  74.     add    si,cs:delta
  75.     add    di,cs:delta
  76.     cmp    si,bp            ;bp=sort buffer length
  77.     jb    lp2            ;jmp if more data to sort
  78. ;
  79. ; move the temp index back to origional
  80. ;    
  81. ms_4:    cmp    cs:sorted_flag,1
  82.     je    ms_done            ;jmp if no sort needed
  83.  
  84.     mov    di,cs:delta
  85.     shl    di,1
  86.     mov    cs:delta,di
  87.     cmp    di,bp            ;check if delta > buffer length
  88.     jae    ms_done
  89. ;
  90.     mov    ax,ds            ;swap
  91.     mov    cx,es            ;  buffer
  92.     mov    ds,cx            ;    pointers
  93.     mov    es,ax            ;       ds & es
  94.     jmp    lp1
  95.  
  96. ms_done:
  97.     mov    ax,ds
  98.     cmp    ax,cs:sort_buffer_seg    ;check if good data in work seg
  99.     jne    sort_exit2        ;jmp if sort data in sort_buffer
  100.         
  101.     mov    cx,bp            ;bp=sort_buffer_length
  102.     shr    cx,1            ;length
  103.     mov    di,0            ;destination
  104.     mov    si,0            ;source
  105.     mov    es,cs:sort_buffer_seg
  106.     mov    ds,cs:work_seg
  107.     rep    movsw            ;move work index -> origional index
  108. sort_exit2:    
  109.     mov    es,cs:work_seg
  110.     call    dos_mem_release    
  111. sort_exit:
  112.     clc
  113. sort_exit3:
  114.     apop    es,ds,bp,di,si,dx,cx,bx,ax
  115.     retf
  116. merge_sort_arrayw    endp
  117.  
  118. ;--------------------------------------------------------------------
  119. ; MERGE - combine two sorted lists
  120. ;   inputs:  ds:si = list1 index top
  121. ;            ds:di = list2 index top, (may be short list)
  122. ;          cs:delta = length of each list
  123. ;            es:bx = active storage pointer of work area
  124. ;               bp = sort buffer length (byte count)
  125. ;
  126. ;  output: si,di updated to end of field
  127. ;
  128. starting_list2_len    dw    0
  129.  
  130. merge:    mov    cs:no_sort_flag,0    ;preload data unsorted state
  131.     mov    cx,cs:delta        ;get list1 length
  132.     mov    dx,cx            ;set list2 length
  133. ;
  134. ; check length of list2
  135. ;    
  136.     mov    ax,dx            ;get list2 length
  137.     add    ax,di            ;compute last location
  138.     sub    ax,bp            ;ax = list2 length adjustment
  139.     jb    mer_cont2        ;jmp if length ok
  140.     sub    ax,cx
  141.     jbe    mer_cont1        ;jmp if only list2 needs adjusting
  142.     mov    dx,0            ;list2 is zero length
  143. ;
  144. ; adjust list1 length
  145. ;
  146.     sub    cx,ax
  147.     jmp    mer_cont2
  148. ;
  149. ; adjust list2 length
  150. ;
  151. mer_cont1:    
  152.     add    ax,cx
  153.     sub    dx,ax            ;adjust list2 length
  154. mer_cont2:
  155.     mov    cs:starting_list2_len,dx
  156. ;
  157. ;             bp=sort buffer length    ds:si=list1 ptr  cx=list1 length  
  158. ; ax=scratch  es:bx=store ptr          ds:di=list2 ptr  dx=list2 length
  159. ;
  160. m_lp:    cmp    cx,0
  161.     je    sort2_only        ;jmp if list1 length=0
  162.     cmp    dx,0
  163.     je    move1            ;jmp if list2 length=0
  164. ;
  165. ; both lists have valid records, do compare
  166. ;
  167.     mov    ax,word ptr ds:[si]
  168.     cmp    ax,word ptr ds:[di]
  169.     ja    move2            ;jmp if list2 data smaller
  170.     jmp    move1            ;jmp if list1 data smaller    
  171. ;
  172. ; list1 is empty, check list2
  173. ;
  174. sort2_only:
  175.     cmp    dx,0            ;check if list2 has data
  176.     je    merge_done1        ;jmp if end of both lists
  177. ;
  178. ; check if no sort was needed for list1, (everything already sorted)
  179. ;
  180.     cmp    dx,cs:starting_list2_len ;has list2 data been merged
  181.     jne    sort2_cont        ;jmp if merge occured
  182.     mov    cs:no_sort_flag,1    ;set no sort this pass flag
  183. sort2_cont:    
  184. ;
  185. ; list2 has data move it
  186. ;
  187. move2:    mov    ax,word ptr ds:[di]    ;get list2 data
  188.     add    di,2
  189.     sub    dx,2            ;list2 length - 2
  190.     jmp    do_move
  191. ;
  192. ; list1 has data move it
  193. ;
  194. move1:    lodsw
  195.     sub    cx,2            ;list1 length - 2
  196. do_move:mov    word ptr es:[bx],ax
  197.     add    bx,2
  198.     jmp    m_lp
  199. ;
  200. merge_done1:
  201.     ret
  202.  
  203. ;
  204. LIBSEG    ENDS
  205.     end
  206.