Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

706 lines
25 KiB

  1. ;----------------------M O D U L E H E A D E R----------------------------;
  2. ; ;
  3. ; Module Name: SORT.ASM ;
  4. ; ;
  5. ; History: SORT.C ;
  6. ; Created by Charles Whitmer 12/30/1986 ;
  7. ; Modified by Mitchel B. London 08/05/1987 ;
  8. ; ;
  9. ; SORT.ASM - translation of SORT.C ;
  10. ; CreateModule David Weise ;
  11. ; Other Modules Amit Chatterjee 08/09/1988 ;
  12. ; ;
  13. ; Copyright (c) 1985 - 1988 Microsoft Corporation ;
  14. ; ;
  15. ; General Description: ;
  16. ; ;
  17. ; The SORT module creates and maintains a tree of nodes, each node ;
  18. ; having a KEY value and a TAG field. The KEY field is used to or- ;
  19. ; -ganize the tree into a heap. ;
  20. ; The heap tree is implemented using an array, where if ;
  21. ; parent node occurs in position i, its left child will be at index ;
  22. ; (2 * i) and the right chaild at index (2 * i + 1). ;
  23. ; The Module ensures that at any instant, the root node ;
  24. ; of any subtree has the least key value in the subtree. ;
  25. ; First few positions in the array are used for storing ;
  26. ; a header for the tree. ;
  27. ; ;
  28. ; SubModules: ;
  29. ; ;
  30. ; 1. CreatePQ: ;
  31. ; Allocates space for the heaptree and its header ;
  32. ; and initializes the header. ;
  33. ; 2. InsertPQ: ;
  34. ; Inserts a node into the heap ensuring that the heap ;
  35. ; property is not violated. ;
  36. ; 3. MinPQ: ;
  37. ; Returns the tag value associated with the lowest ;
  38. ; key in the heap. (node is not deleted) ;
  39. ; 4. ExtractPQ: ;
  40. ; Return the tag value associated with the lowest key ;
  41. ; in the heap and deletes the node. The heap is then ;
  42. ; reconstructed with the remaining nodes. ;
  43. ; 5. DeletePQ: ;
  44. ; Deletes the entire heap by freeing the allocated ;
  45. ; area. ;
  46. ; 6. SizePQ: ;
  47. ; Increases the size of the heap by adding space ;
  48. ; for a requested number of entries ;
  49. ; Heap Data Structure: ;
  50. ; ;
  51. ; The heap data structure has two parts, a header and a set of nodes and ;
  52. ; these are blocked one after the other. ;
  53. ; The header maintains: ;
  54. ; (i) A pointer to the next available node slot ;
  55. ; relative to start of the node area ;
  56. ; (ii) A pointer to the first valid node slot ;
  57. ; node slots between the header and this pointer ;
  58. ; are actually deleted nodes ;
  59. ; (iii) A pointer past the last allocated node slot ;
  60. ; (iv) A last key value, which either holds the largest;
  61. ; key value as long as the nodes are sequentially ;
  62. ; ordered, or a very large value to indicate there;
  63. ; is no sequential ordering ;
  64. ; ;
  65. ; ---------------- ;
  66. ; | INDEX | ---- Pointer to next available node slot ;
  67. ; ---------------- ;
  68. ; | MAXENTRY | ---- Pointer past last allocated node slot ;
  69. ; ---------------- ;
  70. ; START | LASTKEY | ---- Aslong as possible holds max key ;
  71. ; NODE | START | ---- pointer to first active node slot ;
  72. ; ---------------- ;
  73. ; | KEY | ---- Node 1. ;
  74. ; | TAG | ;
  75. ; //---------------// ;
  76. ; | KEY | ---- Last allocated node slot ;
  77. ; | TAG | ;
  78. ; ---------------- ;
  79. ; ;
  80. ; All pointers to nodes are relative to node 1 (pointer to node 1 is ZERO) ;
  81. ;----------------------------------------------------------------------------;
  82. ;----------------------------------------------------------------------------;
  83. ; Include File Section and definitions: ;
  84. ; ;
  85. .xlist
  86. include cmacros.inc
  87. include gdimacro.inc
  88. include gdimem.inc
  89. .286p
  90. .list
  91. START equ SIZE PQ - SIZE ENTRY ; The header includes Node 0
  92. VERYLARGE equ 4000h ; assumed to be larger than any key
  93. PQERROR equ -1 ; return value on error
  94. TRUE equ 1
  95. FALSE equ 0
  96. Entry struc
  97. e_key dw ? ; key value of node
  98. e_tag dw ? ; corresponding tag value
  99. Entry ends
  100. PQ struc ; HEAP Header Structure + Start Node
  101. pq_index dw ?
  102. pq_maxentry dw ? ; excludes START NODE
  103. pq_lastkey dw ?
  104. pq_start dw ?
  105. PQ ends
  106. externFP GlobalLock
  107. externFP GlobalUnlock
  108. externFP GlobalReAlloc
  109. externFP GlobalFree
  110. externFP GlobalAlloc ; Defined in HELPER.ASM
  111. createSeg _SORT,SORT,byte,public,CODE
  112. sBegin SORT
  113. ;-----------------------------------------------------------------------------;
  114. ; ;
  115. ;CreatePQ: ;
  116. ; Inputs: ;
  117. ; Max Number of entries the tree will hold ;
  118. ; Outputs: ;
  119. ; HANDLE to Heap -- if creation successful ;
  120. ; PQERROR if failure ;
  121. ; Registers Preserved: ;
  122. ; DI,SI ;
  123. ; ;
  124. ; -by- David Weise [davidw] ;
  125. ; ;
  126. ;-----------------------------------------------------------------------------;
  127. assumes cs,SORT
  128. assumes ds,nothing
  129. cProc farGDIGlobalAlloc,<FAR,PUBLIC>
  130. parmd amount
  131. cBegin
  132. cCall GlobalAlloc,<GMEM_MOVEABLE+GMEM_SHARE,amount>
  133. cEnd
  134. cProc CreatePQ,<FAR,PUBLIC,NODATA>,<di,si>
  135. parmW cEntries
  136. cBegin
  137. mov ax,cEntries ; max no of nodes the tree will hold
  138. shl ax,1
  139. shl ax,1 ; ax <---- ax * SIZE ENTRY
  140. .errnz (SIZE ENTRY - 4)
  141. mov si,ax ; save number of bytes in node array
  142. add ax, SIZE PQ ; size of header including NODE 0
  143. xor dx,dx
  144. cCall farGDIGlobalAlloc,<dx,ax>
  145. mov bx,ax ; Handle returned
  146. dec ax ; set to -1 if handle returned == 0
  147. .errnz (-1 - PQERROR)
  148. or bx,bx ; test for succesfull memory allocation
  149. jz cPQ_Done ; error return.
  150. push bx
  151. cCall GlobalLock,<bx> ; lock handle get back segment
  152. pop bx
  153. mov es,dx
  154. mov di,ax ; es:di points to start of structure
  155. ; now initialize the header part of the structure with values
  156. ; si has size of the node array
  157. stosw ; index set to zero
  158. .errnz (0 - pq_index)
  159. mov ax,si ; pointer past end of node array
  160. stosw ; max no of entries
  161. .errnz (2 - pq_maxentry)
  162. xor ax,ax ; last key = 0, as heap empty
  163. stosw
  164. .errnz (4 - pq_lastkey)
  165. stosw ; START = 0, implies no deleted slot
  166. .errnz (6 - pq_start)
  167. push bx
  168. cCall GlobalUnlock,<bx> ; unlock the handle to heap
  169. pop ax ; return the handle
  170. cPQ_Done:
  171. cEnd
  172. ;-----------------------------------------------------------------------------;
  173. ; ;
  174. ; InsertPQ: ;
  175. ; Inputs: ;
  176. ; hPQ -- handle to heap structure segment ;
  177. ; tag -- tag value for new node ;
  178. ; key -- key value for new node ;
  179. ; Outputs: ;
  180. ; return TRUE if insertion was successful ;
  181. ; return PQERROR if heap was already packed ;
  182. ; Preserves: ;
  183. ; DS,SI ;
  184. ; ;
  185. ; -by- Amit Chatterjee [amitc] Tue Aug 9 10:45:25 ;
  186. ;-----------------------------------------------------------------------------
  187. assumes cs,SORT
  188. assumes ds,nothing
  189. cProc InsertPQ,<FAR,PUBLIC,NODATA>,<di,si>
  190. parmW hPQ
  191. parmW tag
  192. parmW key
  193. cBegin
  194. mov di,hPQ
  195. cCall GlobalLock,<di> ; lock heap and get back segment addres
  196. or ax,dx ; Invalid handle causes zero return
  197. jz Ins_Cant_Proceed
  198. mov es,dx
  199. xor si,si ; offset in segment always zero
  200. mov ax,es:[si] ; pointer to next available slot
  201. sub ax,es:[si].pq_start ; convert it relative to 1st active node
  202. cmp ax,es:[si].pq_maxentry ; compare with pointer past last slot
  203. jb Insertion_Possible
  204. cCall GlobalUnlock,<di>
  205. Ins_Cant_Proceed:
  206. mov ax,PQERROR ; error return
  207. jmp cInsert_Done
  208. Insertion_Possible:
  209. push es ; HEAP structure segment
  210. smov es,ds ; save local segment in es
  211. pop ds ; change DS to heap segment
  212. mov ax,[si].pq_index ; next available slot in node area
  213. cmp ax,[si].pq_maxentry
  214. jb Enough_Space_Atend ; insertion possible w/o compaction
  215. ; Deleted nodes exist near the head of the tree, compaction necessary
  216. call CompactList ; removes all deleted elements
  217. ; LASTKEY still holds the max key value in the tree
  218. Enough_Space_Atend:
  219. mov bx,[si].pq_index ; pointer to next available slot
  220. mov dx,bx ; save value in register
  221. add bx,SIZE PQ ; area for header
  222. mov ax,tag
  223. mov [si][bx].e_tag,ax ; insert new tag and key
  224. mov ax,key
  225. mov [si][bx].e_key,ax ; key in ax will be used below
  226. mov bx,dx ; bx points to last occupied slot
  227. add dx,SIZE ENTRY ; available slot points to next node
  228. mov [si].pq_index,dx ; save in the structure
  229. ; Now test whether the heap property is valid still.
  230. ; ax has key, dx has pointer to next slot after addition
  231. ; bx points to last valid node
  232. cmp ax,[si].pq_lastkey ; compare with new key
  233. jb Heap_Violated
  234. mov [si].pq_lastkey,ax ; new key is the largest key in tree
  235. jmp short Heap_Restructured ; Insertion over
  236. comment ~
  237. node i has lchild at 2*i and rchild at 2*i+1. But we maintain their
  238. address relative to start of node array. [ie node 1 has addr 0,
  239. node 2 has 4, node 3 12 and so on.]
  240. so if x happens to be the address of a node, the address of its
  241. parent is (x/2 -2) AND 0fffch.
  242. if x is the address of a parent, the address of its lchild is 2*x + 4
  243. and that of its rchild is 2*x + 8
  244. end comment ~
  245. Heap_Violated:
  246. call CompactList ; make sure heap is compacted first!
  247. mov [si].pq_lastkey,VERYLARGE ; to imply heap nolonger seq. ordered
  248. mov bx,[si].pq_index ; bx = offset of inserted elem.
  249. sub bx,SIZE ENTRY
  250. Heap_Walk_Loop:
  251. cmp bx,[si].pq_start ; traversed to top of heap ?
  252. jz Heap_Restructured
  253. mov cx,bx
  254. shr cx,1 ; cx points to parent of current node
  255. dec cx
  256. dec cx
  257. and cx,0fffch ; refer to comment above
  258. .errnz (SIZE ENTRY - 4)
  259. ; Test whether current node has to move up or not, if not it resets carry
  260. ; else it swaps the two nodes and sets carry
  261. call TestShuffle
  262. mov bx,cx ; next node to inspect ifnec. is parent
  263. jc Heap_Walk_Loop
  264. Heap_Restructured:
  265. smov ds,es ; get back own segment in ds
  266. cCall GlobalUnlock,<di> ; di still has the handle
  267. mov ax,di ; return true
  268. cInsert_Done:
  269. cEnd
  270. ;-----------------------------------------------------------------------------;
  271. ; TestShuffle: ;
  272. ; ;
  273. ; Takes as input the node addresses of a parent and on of it's childs. If the;
  274. ; key of the parent is >= key of the child, it returns with carry clear, else;
  275. ; it swaps the two nodes and returns with carry set. ;
  276. ; ;
  277. ; bx has current node address in HEAP, relative to start NODE 1 ;
  278. ; cx has address of parent node of bx ;
  279. ; ;
  280. ; -by- Amit Chatterjee [amitc] Tue Aug 9 12:00:00 ;
  281. ;-----------------------------------------------------------------------------;
  282. cProc TestShuffle,<NEAR,PUBLIC>,<si,di>
  283. cBegin
  284. lea di,[si][SIZE PQ] ; di points to node 1
  285. add di,cx ; di points to parent
  286. lea si,[bx].SIZE PQ ; si points to child node
  287. mov ax,[si].e_key ; childs key
  288. cmp ax,[di].e_key ; key of parent
  289. jb Nodes_Tobe_Swapped
  290. ;
  291. ; Carry cleared by comparision, use for return
  292. ;
  293. jmp short TestShuffle_Ret
  294. Nodes_Tobe_Swapped:
  295. ;
  296. ; Carry has been set by comparision, use for return
  297. ;
  298. xchg ax,[di].e_key
  299. mov [si].e_key,ax
  300. mov ax,[si].e_tag
  301. xchg ax,[di].e_tag
  302. mov [si].e_tag,ax ; swap complete
  303. TestShuffle_Ret:
  304. cEnd
  305. ;-----------------------------------------------------------------------------;
  306. ; MinPQ: ;
  307. ; Inputs: ;
  308. ; hPQ -- Handle to the heap structure ;
  309. ; Outputs: ;
  310. ; minimum tag value in the tree or PQERROR(if invalid handle) ;
  311. ; ;
  312. ; Calls Local Procedure GetMinPQ. ;
  313. ; GetMinPQ takes the handle and a flag as parameter. ;
  314. ; If the flag is TRUE, the node with the least key is deleted ;
  315. ; GetMinPQ also returns the tag value of least key in AX ;
  316. ; ;
  317. ; ;
  318. ; -by- Amit Chatterjee [amitc] Tue Aug 9 12:46:10 ;
  319. ;-----------------------------------------------------------------------------;
  320. assumes cs,SORT
  321. assumes ds,nothing
  322. cProc MinPQ,<FAR,PUBLIC,NODATA>
  323. ; parmW hPQ
  324. cBegin nogen
  325. mov cl,FALSE ; to imply node not to be deleted
  326. jmpnext ; fall through trick, refer cmacros
  327. cEnd nogen
  328. ;-----------------------------------------------------------------------------;
  329. ; ExtractPQ: ;
  330. ; Inputs: ;
  331. ; hPQ -- Handle to the heap structure ;
  332. ; Outputs: ;
  333. ; minimum tag value if heap handle is valid and heap not empty ;
  334. ; return PQERROR otherwise ;
  335. ; The node with min key is deleted ;
  336. ; Calls Local Procedure GetMinPQ ;
  337. ; ;
  338. ; -by- Amit Chatterjee [amitc] Tue Aug 9 12:54:00 ;
  339. ;-----------------------------------------------------------------------------;
  340. assumes cs,SORT
  341. assumes ds,nothing
  342. cProc ExtractPQ,<FAR,PUBLIC,NODATA>
  343. ; parmW hPQ
  344. cBegin nogen
  345. mov cl,TRUE ; to imply that node to be deleted
  346. jmpnext stop ; fall through trick, refer cmacros
  347. cEnd nogen
  348. ;-----------------------------------------------------------------------------;
  349. ; GetMinPQ: ;
  350. ; ;
  351. ; One of the inputs is a flag. If the flag is FALSE it simply returns the tag ;
  352. ; associated with the lease key value in the heap. If the flag is TRUE besides;
  353. ; returnning the above tag value it also deletes the node. ;
  354. ; ;
  355. ; ;
  356. ; hPQ --- handle of HEAP segment ;
  357. ; cl --- Deletion Flag ( Delete node if TRUE) ;
  358. ; ;
  359. ; -by- Amit Chatterjee [amitc] Tue Aug 9 13:00:00 ;
  360. ;-----------------------------------------------------------------------------;
  361. cProc GetMinPQ,<FAR,PUBLIC,NODATA>,<di,si>
  362. parmW hPQ
  363. cBegin
  364. mov di,hPQ
  365. push cx ; save flag
  366. cCall GlobalLock,<di>
  367. pop cx ; get back flag into cl
  368. or dx,ax ; invalid handle implies zero return
  369. jz Min_Cant_Proceed
  370. mov es,dx
  371. mov si,ax ; ds:si points to heap start
  372. mov bx,es:[si].pq_start ; pointer to 1st. available slot
  373. cmp bx,es:[si].pq_index ; empty if equal to next available node
  374. jb Heap_Not_Empty
  375. cCall GlobalUnlock,<di>
  376. Min_Cant_Proceed:
  377. mov ax,PQERROR
  378. jmp cGetMin_Done ; error return
  379. ; bx still has [si].pq_start
  380. Heap_Not_Empty:
  381. push es ; save heap segment
  382. smov es,ds ; save local segment is es
  383. pop ds ; ds:si points to start of heap
  384. lea dx,[si][SIZE PQ]
  385. add dx,bx ; points past deleted nodes
  386. xchg di,dx ; save di in dx and use dx's value
  387. mov ax,[di].e_tag ; get the tag associated with least key
  388. xchg di,dx ; get back values
  389. or cl,cl ; test for bl = FALSE
  390. .errnz (0 - FALSE)
  391. jnz Delete_Node ; TRUE implies get tag and delete node
  392. jmp cGetMin_Ret ; return after unlocking heap
  393. Delete_Node:
  394. ; bx retains [si].start
  395. add bx,SIZE ENTRY ; one more node deleted
  396. cmp bx,[si].pq_index ; is tree empty ?
  397. jb Tree_Not_Empty
  398. xor cx,cx
  399. mov [si].pq_lastkey,cx ; initialize for empty tree
  400. mov [si].pq_start,cx ; initialize for empty tree
  401. mov [si].pq_index,cx
  402. jmp cGetMin_Ret ; return after unlocking heap
  403. Tree_Not_Empty:
  404. ; ax has return tag value
  405. ; bx has [si].pq_start + SIZE ENTRY
  406. cmp [si].pq_lastkey,VERYLARGE ; implies keys in random order
  407. jae Min_Restructure_Heap ; maybe restructuring necessary
  408. mov [si].pq_start,bx ; updates past deleted entry
  409. jmp cGetMin_Ret
  410. Min_Restructure_Heap:
  411. ; dx still has offset to NODE 1, because
  412. ; if LASTKEY = VERYLARGE, pq_start has to be zero
  413. push ax ; save return tag value
  414. mov bx,dx ; offset to first active node
  415. xchg di,dx ; get pointer into di ,save di
  416. add di,[si].pq_index ; dx points to next available slot
  417. sub di,SIZE ENTRY ; point to last filled node
  418. mov ax,di ; last node being moved upfront
  419. sub ax,SIZE PQ ; point ax one node ahead of last
  420. mov [si].pq_index,ax ; update it
  421. mov cx,[di].e_key
  422. mov [bx].e_key,cx ; move from last position to NODE 1
  423. mov cx,[di].e_tag
  424. mov [bx].e_tag,cx
  425. xchg di,dx ; restore di,dx
  426. xor cx,cx ; start traversing heap from root
  427. Min_Traverse_Heap:
  428. mov bx,cx
  429. shl bx,1
  430. add bx,SIZE ENTRY ; bx has left child addr of parent in cx
  431. cmp bx,[si].pq_index ; compare with next available slot
  432. jae Min_Heap_Fixed ; heap restored
  433. push cx ; save current parent
  434. mov cx,bx ; have lchild in cx
  435. add cx,SIZE ENTRY ; cx now get address of rchild
  436. cmp cx,[si].pq_index ; test against last node
  437. jae Right_Child_Not_Present
  438. call GetLesserChild ; gets child with lesser key in bx
  439. Right_Child_Not_Present:
  440. pop cx ; get back parent
  441. ;
  442. ; cx has node number of parent node and bx has node no of child node with
  443. ; least key. If parents key value is greater it should be swapped
  444. ;
  445. call TestShuffle
  446. ; swaps the two nodes if necessary.
  447. mov cx,bx ; lesser child is next parent
  448. jmp Min_Traverse_Heap
  449. Min_Heap_Fixed:
  450. pop ax ; get back return tag value
  451. cGetMin_Ret:
  452. push ax ; save return value
  453. smov ds,es ; get back own ds
  454. cCall GlobalUnlock,<di> ; unlock heap
  455. pop ax ; get back return value
  456. cGetMin_Done:
  457. cEnd
  458. ;-----------------------------------------------------------------------------;
  459. ; GetLesserChild: ;
  460. ; ;
  461. ; Given two child node numbers, it returns the child which has a lesser key ;
  462. ; ;
  463. ; cx has RCHILD NODE address ;
  464. ; bx has LCHILD NODE address ;
  465. ; si points to start of heap ;
  466. ; will return node address of lesser child in bx ;
  467. ; ;
  468. ; -by- Amit Chatterjee [amitc] Tue Aug 9 13:50 ;
  469. ;-----------------------------------------------------------------------------;
  470. cProc GetLesserChild,<NEAR,PUBLIC,NODATA>,<di,si>
  471. cBegin
  472. lea di,[si][SIZE PQ] ; dx now points to NODE 1
  473. mov si,di ; si also points to start of NODE 1
  474. add di,cx ; di get address of rchild
  475. mov ax,[si+bx].e_key ; rchilds key
  476. cmp ax,[di].e_key ; compare with rchild
  477. jb Right_Child_Lesser ; bx still has the correct child no.
  478. mov bx,cx ; get RCHILD address into bx
  479. Right_Child_Lesser:
  480. cEnd
  481. ;
  482. ;-----------------------------------------------------------------------------;
  483. ; DeletePQ: ;
  484. ; Inputs: ;
  485. ; hPQ --- handle to a heap structure ;
  486. ; OutPuts: nothing ;
  487. ; Preserves: DI ;
  488. ; ;
  489. ; -by- Amit Chatterjee [amitc] Tue Aug 9 14:15:45 ;
  490. ;-----------------------------------------------------------------------------
  491. ;
  492. assumes cs,SORT
  493. assumes ds,nothing
  494. cProc DeletePQ,<FAR,PUBLIC,NODATA>
  495. parmW hPQ
  496. cBegin
  497. cCall GlobalFree,<hPQ> ; free the handle
  498. cEnd
  499. ;-----------------------------------------------------------------------------;
  500. ;SizePQ: ;
  501. ; Input: ;
  502. ; hPQ --- Handle to a heap structure ;
  503. ; entry --- number of nodes by which heap is to be expanded ;
  504. ; Output: ;
  505. ; Returns the total number of node slots in new heap, if successful
  506. ; else return PQERROR ;
  507. ; ;
  508. ; -by- Amit Chatterjee [amitc] Tue Aug 9 14:31:40 ;
  509. ;-----------------------------------------------------------------------------
  510. assumes cs,SORT
  511. assumes ds,nothing
  512. cProc SizePQ,<FAR,PUBLIC,NODATA>,<si,di>
  513. parmW hPQ
  514. parmW cEntry
  515. cBegin
  516. mov di,hPQ
  517. cCall GlobalLock,<di> ; lock to get back segment address
  518. or ax,dx ; Invalid handle implies NULL return
  519. jz Siz_Cant_Proceed
  520. mov es,dx
  521. xor si,si ; offset will always be zro
  522. mov ax,cEntry ; additional nodes
  523. or ax,ax ; if zero return original numof nodes
  524. jnz Size_Tobe_Increased
  525. mov ax,es:[si].pq_maxentry ; offset past last node
  526. shr ax,1
  527. shr ax,1 ; ax <--- ax / SIZE ENTRY
  528. .errnz (SIZE ENTRY - 4)
  529. jmp short cSize_Ret ; return after unlocking handle
  530. Size_Tobe_Increased:
  531. shl ax,1
  532. shl ax,1 ; ax <-- ax * SIZE ENTRY, = extra bytes
  533. .errnz (SIZE ENTRY - 4)
  534. add ax,es:[si].pq_maxentry ; number of byte for new node array
  535. cmp ax,es:[si].pq_index ; next available slot
  536. jae Valid_Increase
  537. mov ax,PQERROR ; error code
  538. jmp short cSize_Ret ; return after releasing handle
  539. Valid_Increase:
  540. push ax ; save number of bytes in node block
  541. add ax,SIZE PQ ; size of header
  542. push ax
  543. cCall GlobalUnlock,<di> ; unlock handle
  544. xor dx,dx ; high word for size
  545. pop ax ; get back size
  546. cCall GlobalReAlloc,<di,dx,ax,GMEM_MOVEABLE>
  547. or ax,ax
  548. jz Siz_Cant_Proceed
  549. mov di,ax ; new handle
  550. cCall GlobalLock,<ax> ; lock it
  551. mov es,dx ; set new segment
  552. pop cx ; get back total no of nodes into cx
  553. jmp short Reloc_Successful
  554. Siz_Cant_Proceed:
  555. pop cx ; balance stack
  556. dec ax
  557. .errnz (-1 - PQERROR)
  558. jmp short cSize_End
  559. Reloc_Successful:
  560. mov es:[si].pq_maxentry,cx ; total number of slots now
  561. shr cx,1
  562. shr cx,1 ; no of nodes = bytes / SIZE ENTRY
  563. .errnz (SIZE ENTRY - 4)
  564. mov ax,cx ; return value
  565. cSize_Ret:
  566. cCall GlobalUnlock,<di>
  567. cSize_End:
  568. cEnd
  569. ;-----------------------------------------------------------------------------;
  570. ;CompactList: ;
  571. ; Input: ;
  572. ; ds:si --- pointer to heap structure ;
  573. ; Output: ;
  574. ; all deleted elements are removed from heap structure ;
  575. ; Registers trashed:
  576. ; AX,BX,CX,DX
  577. ;
  578. ; -by- Ken Sykes [kensy] Tue Nov 12 1991 10:20:00am ;
  579. ;-----------------------------------------------------------------------------
  580. CompactList proc near
  581. mov ax,[si].pq_index ; next available slot in node area
  582. sub ax,[si].pq_start ; ax had pointer to available slot
  583. mov [si].pq_index,ax ; next available slot will come up
  584. lea dx,[si][SIZE PQ] ; points to NODE 1
  585. mov ax,[si].pq_start ; pointer to 1st active node rel to 1
  586. add ax,dx ; ax has offset to first valid node.
  587. mov bx,ax
  588. mov cx,[si].pq_maxentry ; pointer past end of node slots
  589. sub cx,[si].pq_start ; pointer to strt of active block
  590. shr cx,1 ; will do a REP MOVSW
  591. .errnz (1 and SIZE ENTRY)
  592. push es ; es has local segment
  593. smov es,ds ; moth es ds point to heap segment
  594. push si
  595. push di ; save start to heap and its handle
  596. mov si,bx ; si points to start of valid nodes
  597. mov di,dx ; dx points to node 1
  598. cld
  599. rep movsw ; Compacted
  600. pop di
  601. pop si
  602. pop es ; restore local segment in es
  603. mov [si].pq_start,cx ; after compaction deleted nodes = 0
  604. ret
  605. CompactList endp
  606. ;-----------------------------------------------------------------------------;
  607. sEnd SORT
  608. end