home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / cs0929a.zip / malloc.lst < prev    next >
File List  |  1999-09-29  |  71KB  |  1,662 lines

  1.  
  2. Module: D:\dev\csrc\os2dd\scd\malloc.c
  3. Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
  4.  
  5. Segment: _TEXT  PARA   0000060f bytes  
  6.  
  7. //
  8. // malloc.c
  9. // 25-Jan-99
  10. //
  11. // static void dumpheap(void);
  12. // static void SignatureCheck ( PMEMBLOCK p, PSZ idText );
  13. // static void HeapCheck ( PSZ idText );
  14. // static PMEMBLOCK make_new_free(PMEMBLOCK pmbOldFree, unsigned uRequest);
  15. // static unsigned _msize(void __near *pvBlock);
  16. // static void __near * npvAllocateBlock( PMEMBLOCK pmb, USHORT uRequest, PMEMBLOCK pmbPrev );
  17. // static void remove(PMEMBLOCK pmb);
  18. // static void compact(void);
  19. // void __near *malloc( unsigned uSize );
  20. // void free(void __near *pvBlock);
  21. // unsigned _memfree(void);
  22. // void __near *realloc(void __near *pvBlock, unsigned usLength);
  23. // unsigned HeapInit(unsigned uSize);
  24.  
  25. #include "cs40.h"
  26.  
  27. #define HEMP_DBG 1
  28.  
  29. // putting this in class BSS means won't blowout file size and extra HEAP_SIZE bytes!
  30. // as it does if using the original  #pragma data_seg ("_HEMP","ENDDS");
  31.  
  32. #pragma data_seg ("_HEMP");     // yes, _HEMP
  33.  
  34. #define DEFAULT_HEAP 4096
  35. #define HEAP_SIZE    8192 // max heap size
  36. //#define SIGNATURE    0xBEEFDEAD  // "DEADBEEF" when view in hex in word order.
  37. #define SIGNATURE  0x3477ADDE  // 'DEAD7734' in ascii view
  38.  
  39. typedef struct _MEMBLOCK {
  40.    unsigned long ulSignature;
  41.    unsigned uSize;
  42.    struct _MEMBLOCK *pmbNext;
  43.    char achBlock[1];
  44. } MEMBLOCK, __near *PMEMBLOCK;
  45.  
  46. #define HDR_SIZE  ( sizeof(MEMBLOCK) - 1 )
  47.  
  48. // We won't leave a hole in memory any smaller than MIN_FragSize.
  49. #define MIN_FragSize  4
  50.  
  51. //--- Global Variables used to manage the heap:
  52. // (no reason to be extern globals, so making them static, 26-Jan-99)
  53.  
  54. static PMEMBLOCK pmbUsed=0;    // Points to head of list of allocated memory blocks.
  55.                         // Newly allocated blocks are inserted into head of list.
  56. static PMEMBLOCK pmbFree;      // Points to head of list of available memory blocks.
  57. static unsigned uMemFree;      // N bytes available for allocation.
  58.  
  59. static USHORT fMemoryDoc = 0;
  60. static USHORT nAlloc = 0;           // Current number of allocated blocks.
  61. static USHORT cAlloc = 0;           // Total memory in allocated blocks incl. headers.
  62. static USHORT nAllocCalls = 0;      // Cumulative total, number of malloc() calls.
  63. static USHORT nFree  = 0;           // Current number of free blocks.
  64. static USHORT cFree  = 0;           // Total memory in free blocks incl. headers.
  65. static USHORT nFreeCalls  = 0;      // Cumulative total, number of free() calls.
  66. static USHORT nCompact = 0;         // Num of times we've joined two adjacent free blocks into a single larger block
  67. static USHORT cTotalHeap = HEAP_SIZE;
  68.  
  69. static char __near acHeap[HEAP_SIZE];
  70.                         // The heap.  NOTE:  This must be the last data definition in the HEAP segment,
  71.                         // although not done currently, we are planning to size the heap down at INIT
  72.                         // time.  If this is done, any vbls in the HEAP segment that
  73.                         // appear after the HEAP would become unaddressable.
  74.  
  75. #ifdef HEMP_DBG
  76.  
  77. //--- Heap methods:
  78.  
  79. //static void dumpheap(void)
  80. void dumpheap(void)
  81. {
  82.    int i;
  83.    PMEMBLOCK pmb;
  84.    unsigned u=0;
  85.  
  86.  0000  53                dumpheap_       push    bx
  87.  0001  51                                push    cx
  88.  0002  52                                push    dx
  89.  0003  56                                push    si
  90.  0004  57                                push    di
  91.  0005  55                                push    bp
  92.  0006  89 e5                             mov     bp,sp
  93.  0008  83 ec 04                          sub     sp,0004H
  94.  
  95.    pmb=pmbUsed;
  96.  000b  8b 36 00 00                       mov     si,_pmbUsed
  97.  000f  31 d2                             xor     dx,dx
  98.  
  99. if (gCLflags & FLAGS_CL_DDPRINT)    ddprintf("~HEAP: Heap Dump - Used blocks\n");
  100.  0011  8a 26 01 00                       mov     ah,_gCLflags+1H
  101.  0015  89 56 fc                          mov     [bp-4H],dx
  102.  0018  f6 c4 40                          test    ah,40H
  103.  001b  74 0a                             je      L1
  104.  001d  1e                                push    ds
  105.  001e  68 00 00                          push    offset L78
  106.  0021  e8 00 00                          call    _ddprintf
  107.  0024  83 c4 04                          add     sp,0004H
  108.  
  109.    for (i=0; i<32; i++) {
  110.       if (!pmb) break;
  111.  0027  31 ff             L1              xor     di,di
  112.  0029  85 f6                             test    si,si
  113.  002b  74 2f                             je      L4
  114.  
  115. if (gCLflags & FLAGS_CL_DDPRINT)       ddprintf("~  pmb=%p, btyes=%u\n",(void __far *) pmb, pmb->uSize);
  116.  002d  f6 06 01 00 40    L2              test    byte ptr _gCLflags+1H,40H
  117.  0032  74 10                             je      L3
  118.  0034  8b 5c 04                          mov     bx,[si+4H]
  119.  0037  53                                push    bx
  120.  0038  1e                                push    ds
  121.  0039  56                                push    si
  122.  003a  1e                                push    ds
  123.  003b  68 20 00                          push    offset L79
  124.  003e  e8 00 00                          call    _ddprintf
  125.  0041  83 c4 0a                          add     sp,000aH
  126.  0044  8b 4e fc          L3              mov     cx,[bp-4H]
  127.  
  128.       u+=pmb->uSize;
  129.       pmb=pmb->pmbNext;
  130.  0047  8b 44 04                          mov     ax,[si+4H]
  131.  
  132.  004a  47                                inc     di
  133.  004b  01 c1                             add     cx,ax
  134.  
  135.    }
  136.  004d  8b 74 06                          mov     si,[si+6H]
  137.  0050  89 4e fc                          mov     [bp-4H],cx
  138.  0053  83 ff 20                          cmp     di,0020H
  139.  0056  7d 04                             jge     L4
  140.  0058  85 f6                             test    si,si
  141.  005a  75 d1                             jne     L2
  142.  
  143. if (gCLflags & FLAGS_CL_DDPRINT)    ddprintf("~  Total used = %u\n",u);
  144.  
  145.    u=0;
  146.  005c  f6 06 01 00 40    L4              test    byte ptr _gCLflags+1H,40H
  147.  0061  74 0e                             je      L5
  148.  0063  8b 76 fc                          mov     si,[bp-4H]
  149.  0066  56                                push    si
  150.  0067  1e                                push    ds
  151.  0068  68 36 00                          push    offset L80
  152.  006b  e8 00 00                          call    _ddprintf
  153.  006e  83 c4 06                          add     sp,0006H
  154.  
  155.  0071  8b 36 00 00       L5              mov     si,_pmbFree
  156.  
  157.    pmb=pmbFree;
  158.  0075  31 ff                             xor     di,di
  159.  
  160. if (gCLflags & FLAGS_CL_DDPRINT)    ddprintf("~HEAP: Heap Dump - Free blocks\n");
  161.  0077  8a 1e 01 00                       mov     bl,_gCLflags+1H
  162.  007b  89 7e fe                          mov     [bp-2H],di
  163.  007e  f6 c3 40                          test    bl,40H
  164.  0081  74 0a                             je      L6
  165.  0083  1e                                push    ds
  166.  0084  68 4a 00                          push    offset L81
  167.  0087  e8 00 00                          call    _ddprintf
  168.  008a  83 c4 04                          add     sp,0004H
  169.  
  170.    for (i=0; i<32; i++) {
  171.       if (!pmb) break;
  172.  008d  31 ff             L6              xor     di,di
  173.  008f  85 f6                             test    si,si
  174.  0091  74 2f                             je      L9
  175.  
  176. if (gCLflags & FLAGS_CL_DDPRINT)       ddprintf("~  pmb=%p, bytes=%u\n",(void __far *) pmb, pmb->uSize);
  177.  0093  f6 06 01 00 40    L7              test    byte ptr _gCLflags+1H,40H
  178.  0098  74 10                             je      L8
  179.  009a  8b 44 04                          mov     ax,[si+4H]
  180.  009d  50                                push    ax
  181.  009e  1e                                push    ds
  182.  009f  56                                push    si
  183.  00a0  1e                                push    ds
  184.  00a1  68 6a 00                          push    offset L82
  185.  00a4  e8 00 00                          call    _ddprintf
  186.  00a7  83 c4 0a                          add     sp,000aH
  187.  00aa  8b 56 fe          L8              mov     dx,[bp-2H]
  188.  
  189.       u+=pmb->uSize;
  190.       pmb=pmb->pmbNext;
  191.  00ad  8b 44 04                          mov     ax,[si+4H]
  192.  
  193.  00b0  47                                inc     di
  194.  00b1  01 c2                             add     dx,ax
  195.  
  196.    }
  197.  00b3  8b 74 06                          mov     si,[si+6H]
  198.  00b6  89 56 fe                          mov     [bp-2H],dx
  199.  00b9  83 ff 20                          cmp     di,0020H
  200.  00bc  7d 04                             jge     L9
  201.  00be  85 f6                             test    si,si
  202.  00c0  75 d1                             jne     L7
  203.  
  204. if (gCLflags & FLAGS_CL_DDPRINT)    ddprintf("~  Total free = %u\n",u);
  205.  
  206.  00c2  f6 06 01 00 40    L9              test    byte ptr _gCLflags+1H,40H
  207.  00c7  74 0e                             je      L10
  208.  00c9  8b 5e fe                          mov     bx,[bp-2H]
  209.  00cc  53                                push    bx
  210.  00cd  1e                                push    ds
  211.  00ce  68 80 00                          push    offset L83
  212.  00d1  e8 00 00                          call    _ddprintf
  213.  00d4  83 c4 06                          add     sp,0006H
  214.  
  215. if (gCLflags & FLAGS_CL_DDPRINT)    ddprintf("~ alloc:currblks=%u, calls=%u;  free:currblks=%u, calls=%u\n",
  216.               nAlloc,nAllocCalls,nFree,nFreeCalls);
  217.  00d7  f6 06 01 00 40    L10             test    byte ptr _gCLflags+1H,40H
  218.  00dc  74 1d                             je      L11
  219.  00de  8b 0e 00 00                       mov     cx,_nFreeCalls
  220.  00e2  51                                push    cx
  221.  00e3  8b 36 00 00                       mov     si,_nFree
  222.  00e7  56                                push    si
  223.  00e8  8b 3e 00 00                       mov     di,_nAllocCalls
  224.  00ec  57                                push    di
  225.  00ed  a1 00 00                          mov     ax,_nAlloc
  226.  00f0  50                                push    ax
  227.  00f1  1e                                push    ds
  228.  00f2  68 94 00                          push    offset L84
  229.  00f5  e8 00 00                          call    _ddprintf
  230.  00f8  83 c4 0c                          add     sp,000cH
  231.  
  232. }
  233.  
  234. #endif
  235.  
  236.  
  237.  00fb  89 ec             L11             mov     sp,bp
  238.  00fd  5d                                pop     bp
  239.  00fe  5f                                pop     di
  240.  00ff  5e                                pop     si
  241.  0100  5a                                pop     dx
  242.  0101  59                                pop     cx
  243.  0102  5b                                pop     bx
  244.  0103  c3                                ret     
  245.  
  246. static void SignatureCheck ( PMEMBLOCK p, PSZ idText )
  247. {
  248.  
  249.    bool bGoodPointer;
  250.  
  251.    // Set bGoodPointer to indicate whether or not 'p' points within heap.
  252.  0104  52                SignatureCheck_ push    dx
  253.  0105  56                                push    si
  254.  0106  57                                push    di
  255.  0107  89 c6                             mov     si,ax
  256.  
  257.    bGoodPointer = (((USHORT) p) >= ((USHORT) acHeap))
  258.                   && (((USHORT) p) <= (((USHORT) acHeap) + HEAP_SIZE)) ;
  259.                               //### heap might have less than HEAP_SIZE bytes
  260.  
  261.    // Check for correct signature.
  262.  0109  3d 00 00                          cmp     ax,offset _acHeap
  263.  010c  72 0a                             jb      L12
  264.  010e  3d 00 20                          cmp     ax,offset _acHeap+2000H
  265.  0111  77 05                             ja      L12
  266.  0113  b8 01 00                          mov     ax,0001H
  267.  0116  eb 02                             jmp     L13
  268.  0118  31 c0             L12             xor     ax,ax
  269.  011a  89 c2             L13             mov     dx,ax
  270.  
  271.    if (bGoodPointer)
  272.  011c  85 c0                             test    ax,ax
  273.  011e  74 1a                             je      L16
  274.  
  275.       bGoodPointer = (p->ulSignature == SIGNATURE);
  276.  
  277.  0120  8b 54 02                          mov     dx,[si+2H]
  278.  0123  8b 3c                             mov     di,[si]
  279.  0125  81 fa 77 34                       cmp     dx,3477H
  280.  0129  75 0b                             jne     L14
  281.  012b  81 ff de ad                       cmp     di,0addeH
  282.  012f  75 05                             jne     L14
  283.  0131  b8 01 00                          mov     ax,0001H
  284.  0134  eb 02                             jmp     L15
  285.  0136  31 c0             L14             xor     ax,ax
  286.  0138  89 c2             L15             mov     dx,ax
  287.  
  288.    if (! bGoodPointer)
  289.    {
  290. #ifdef HEMP_DBG
  291.  013a  85 d2             L16             test    dx,dx
  292.  013c  75 15                             jne     L18
  293.  
  294. if (gCLflags & FLAGS_CL_DDPRINT)       ddprintf( "~Heap pointer out of range, or signature exception: %p %s\n", p, idText );
  295. #endif
  296.  013e  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  297.  0143  74 0d                             je      L17
  298.  0145  51                                push    cx
  299.  0146  53                                push    bx
  300.  0147  56                                push    si
  301.  0148  1e                                push    ds
  302.  0149  68 d0 00                          push    offset L85
  303.  014c  e8 00 00                          call    _ddprintf
  304.  014f  83 c4 0a                          add     sp,000aH
  305.  
  306.       int3();
  307.    }
  308.  return;
  309.  idText;
  310.  0152  cc                L17             int     3
  311.  
  312. }
  313.  
  314.  0153  5f                L18             pop     di
  315.  0154  5e                                pop     si
  316.  0155  5a                                pop     dx
  317.  0156  c3                                ret     
  318.  0157  fc                                cld     
  319.  
  320. static void HeapCheck ( PSZ idText )
  321. {
  322.    PMEMBLOCK p;
  323.  0158  53                HeapCheck_      push    bx
  324.  0159  51                                push    cx
  325.  015a  56                                push    si
  326.  015b  57                                push    di
  327.  
  328.    for ( nAlloc = 0, cAlloc = 0, p = pmbUsed; p; p = p->pmbNext ) {
  329.  015c  31 d2                             xor     dx,dx
  330.  015e  8b 36 00 00                       mov     si,_pmbUsed
  331.  0162  89 16 00 00                       mov     _nAlloc,dx
  332.  0166  89 16 00 00                       mov     _cAlloc,dx
  333.  016a  85 f6                             test    si,si
  334.  016c  74 2c                             je      L20
  335.  016e  ba 0c 01                          mov     dx,offset L86
  336.  
  337.       ++nAlloc;
  338.       cAlloc += p->uSize + HDR_SIZE;
  339.       //SignatureCheck( p,(PSZ) "HeapCheck() Used list" );
  340.       //SignatureCheck( p,(PSZ)0);
  341.  0171  8b 0e 00 00       L19             mov     cx,_nAlloc
  342.  0175  8b 3e 00 00                       mov     di,_cAlloc
  343.  
  344.       SignatureCheck( p,(PSZ)"HCUL");
  345.  0179  89 d3                             mov     bx,dx
  346.  017b  8b 44 04                          mov     ax,[si+4H]
  347.  017e  41                                inc     cx
  348.  017f  05 08 00                          add     ax,0008H
  349.  0182  89 0e 00 00                       mov     _nAlloc,cx
  350.  0186  01 c7                             add     di,ax
  351.  0188  8c d9                             mov     cx,ds
  352.  018a  89 f0                             mov     ax,si
  353.  018c  89 3e 00 00                       mov     _cAlloc,di
  354.  0190  e8 00 00                          call    SignatureCheck_
  355.  
  356.    }
  357.  0193  8b 74 06                          mov     si,[si+6H]
  358.  0196  85 f6                             test    si,si
  359.  0198  75 d7                             jne     L19
  360.  
  361.    for ( nFree = 0, cFree = 0, p = pmbFree; p; p = p->pmbNext ) {
  362.  019a  31 c0             L20             xor     ax,ax
  363.  019c  8b 36 00 00                       mov     si,_pmbFree
  364.  01a0  a3 00 00                          mov     _nFree,ax
  365.  01a3  a3 00 00                          mov     _cFree,ax
  366.  01a6  85 f6                             test    si,si
  367.  01a8  74 2c                             je      L22
  368.  01aa  ba 12 01                          mov     dx,offset L87
  369.  
  370.       ++nFree;
  371.  01ad  8b 1e 00 00       L21             mov     bx,_nFree
  372.  
  373.       cFree += p->uSize + HDR_SIZE;
  374.       //SignatureCheck( p,(PSZ) "HeapCheck() Free list" );
  375.       //SignatureCheck( p,(PSZ)0);
  376.  01b1  8b 44 04                          mov     ax,[si+4H]
  377.  01b4  8b 0e 00 00                       mov     cx,_cFree
  378.  01b8  05 08 00                          add     ax,0008H
  379.  01bb  43                                inc     bx
  380.  01bc  01 c1                             add     cx,ax
  381.  01be  89 1e 00 00                       mov     _nFree,bx
  382.  01c2  89 0e 00 00                       mov     _cFree,cx
  383.  
  384.       SignatureCheck( p,(PSZ)"HCFL");
  385.  01c6  89 d3                             mov     bx,dx
  386.  01c8  89 f0                             mov     ax,si
  387.  01ca  8c d9                             mov     cx,ds
  388.  01cc  e8 00 00                          call    SignatureCheck_
  389.  
  390.    }
  391.  01cf  8b 74 06                          mov     si,[si+6H]
  392.  01d2  85 f6                             test    si,si
  393.  01d4  75 d7                             jne     L21
  394.  
  395.    if (fMemoryDoc & 1) {
  396.  01d6  f6 06 00 00 01    L22             test    byte ptr _fMemoryDoc,01H
  397.  01db  74 26                             je      L24
  398.  
  399.       if (cAlloc + cFree != cTotalHeap) {
  400. #ifdef HEMP_DBG
  401.  01dd  a1 00 00                          mov     ax,_cAlloc
  402.  01e0  8b 36 00 00                       mov     si,_cFree
  403.  01e4  8b 3e 00 00                       mov     di,_cTotalHeap
  404.  01e8  01 f0                             add     ax,si
  405.  01ea  39 f8                             cmp     ax,di
  406.  01ec  74 15                             je      L24
  407.  
  408. if (gCLflags & FLAGS_CL_DDPRINT)          ddprintf( "~Heap Alloc + Free != Total\n" );
  409.  01ee  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  410.  01f3  74 0a                             je      L23
  411.  01f5  1e                                push    ds
  412.  01f6  68 18 01                          push    offset L88
  413.  01f9  e8 00 00                          call    _ddprintf
  414.  01fc  83 c4 04                          add     sp,0004H
  415.  
  416.          dumpheap();
  417. #endif
  418.  01ff  e8 00 00          L23             call    dumpheap_
  419.  
  420.          int3();
  421.       }
  422.    }
  423.  return;
  424.  idText;
  425.  0202  cc                                int     3
  426.  
  427. }
  428.  
  429.  
  430.  
  431. // Threshold for creating a new free block.
  432. #define  MIN_Leftover  (HDR_SIZE + MIN_FragSize)
  433.  
  434. /* make_new_free()
  435.    Formats the back part of an existing free MEMBLOCK as a new, smaller
  436.    "Free" MEMBLOCK.  Doesn't update Global vbls (caller responsibility).
  437.       IN:   pmbOldFree - pointer to existing memory block.
  438.             uSize - offset, which won't be included in new allocation.
  439.                     it's assumed HDR is not included in uSize.
  440.       OUT:  pointer to new free MEMBLOCK, is  a new block of free memory,
  441.             is created at pmbOldFree + uRequest.  The memory block header
  442.             in both the new block and the old block are properly initialized
  443.             on return, but we don't update the Free list or Allocated list.
  444.       OUT:  NULL if the new free memory block is smaller than the
  445.             framentation threshold.
  446.  
  447. The fragmentation consideration comes into play when we find a block that's
  448. big enough to hold the requested memory, but not big enough for the leftover
  449. part to be useful as another free block.
  450.  
  451.     _______________________free block_______________________________________
  452.    |  free    |                                                             |
  453.    |  block   |       space available                                       |
  454.    |  header  |          (pmbFree->uSize bytes long)                        |
  455.    |(HDR_SIZE |                                                             |
  456.    |__bytes)__|_____________________________________________________________|
  457.  
  458.    <-- HDR --> <------------------------- l -------------------------------->
  459.  
  460. Must either be allocated in total, or must become:
  461.  
  462.     _______________________used block_______________________________________
  463.    |  used    |                                     |  free    |            |
  464.    |  block   |  space allocated                    |  block   | space      |
  465.    |  header  |  == uSize (following DWORD align't) |  header  | available  |
  466.    |(HDR_SIZE |     (pmbUsed->uSize bytes long)     |(HDR_SIZE |            |
  467.    |__bytes)__|_____________________________________|__bytes)__|____________|
  468.  
  469.    <-- HDR --> <-------------- n ------------------><-- HDR --> <--- m ----->
  470.  
  471. To be split into an allocated and a new, smaller free block, 'm' must be at
  472. least MIN_FragSize bytes long.
  473.  
  474. Everything should remain 4 byte aligned since the HDR_SIZE, MIN_FragSize,
  475. and the space allocated (after we munge it) are all multiples of 4.
  476.  
  477. This means that in order for a free block to be chosen, one of the following
  478. equation must hold
  479.  
  480.   Case 1:  n  <=  l  < (n + HDR + MIN_FragSize)
  481.   Here, we'll allocate the entire block.  This makes the block somewhat
  482.   larger than the request, but prevents some degree of fragmentation.
  483.  
  484.   Case 2:  (n + HDR + MIN_FragSize) <= l
  485.   We split the block into an allocated part to satisfy the allocation request,
  486.   and a free block which can be allocated in a subsequent request.
  487. */
  488.  
  489.  0203  5f                L24             pop     di
  490.  0204  5e                                pop     si
  491.  0205  59                                pop     cx
  492.  0206  5b                                pop     bx
  493.  0207  c3                                ret     
  494.  
  495. static PMEMBLOCK make_new_free(PMEMBLOCK pmbOldFree, unsigned uRequest)
  496. {
  497.    PMEMBLOCK pmbNewFree;     // If we create a new free block, it goes here.
  498.  
  499.    // Which of the two cases (as described in function header) have we got?
  500.    // We know we're big enough to satisfy request, is there enough leftover
  501.    // for a new free block?
  502.  
  503.  0208  53                make_new_free_  push    bx
  504.  0209  51                                push    cx
  505.  020a  56                                push    si
  506.  020b  89 c6                             mov     si,ax
  507.  
  508.     if ((uRequest + MIN_Leftover) > pmbOldFree->uSize) {
  509.        // Not enough leftover, allocate the entire free block.  Don't
  510.        // change pmbOldFree->uSize.
  511.  020d  89 d3                             mov     bx,dx
  512.  020f  8b 4c 04                          mov     cx,[si+4H]
  513.  0212  83 c3 0c                          add     bx,000cH
  514.  0215  39 cb                             cmp     bx,cx
  515.  0217  76 04                             jbe     L25
  516.  
  517.        pmbNewFree = 0;
  518.     }
  519.  0219  31 db                             xor     bx,bx
  520.  
  521.     else {
  522.        // We've got enough leftover to make a new free block.
  523.  021b  eb 2a                             jmp     L26
  524.  
  525.        pmbNewFree = (PMEMBLOCK) ((char __near *) pmbOldFree + HDR_SIZE + uRequest );
  526.  021d  8d 5c 08          L25             lea     bx,[si+8H]
  527.  0220  01 d3                             add     bx,dx
  528.  
  529.        pmbNewFree->ulSignature = SIGNATURE;
  530.  0222  c7 07 de ad                       mov     word ptr [bx],0addeH
  531.  
  532.        pmbNewFree->uSize = pmbOldFree->uSize - (uRequest + HDR_SIZE);
  533.  0226  89 d0                             mov     ax,dx
  534.  0228  c7 47 02 77 34                    mov     word ptr [bx+2H],3477H
  535.  022d  05 08 00                          add     ax,0008H
  536.  0230  8b 54 04                          mov     dx,[si+4H]
  537.  0233  29 c2                             sub     dx,ax
  538.  0235  89 57 04                          mov     [bx+4H],dx
  539.  
  540.        pmbNewFree->pmbNext = pmbOldFree->pmbNext;
  541.  
  542.        // Update the size of the free block that was passed in.
  543.  0238  8b 54 06                          mov     dx,[si+6H]
  544.  
  545.        pmbOldFree->uSize -= (pmbNewFree->uSize + HDR_SIZE);
  546.     }
  547.  
  548.    return pmbNewFree;
  549.  023b  8b 47 04                          mov     ax,[bx+4H]
  550.  023e  89 57 06                          mov     [bx+6H],dx
  551.  0241  05 08 00                          add     ax,0008H
  552.  0244  29 44 04                          sub     [si+4H],ax
  553.  
  554. }
  555.  
  556.  
  557. /**@internal _msize
  558.  */
  559.  0247  89 d8             L26             mov     ax,bx
  560.  0249  5e                                pop     si
  561.  024a  59                                pop     cx
  562.  024b  5b                                pop     bx
  563.  024c  c3                                ret     
  564.  024d  89 c0                             mov     ax,ax
  565.  024f  fc                                cld     
  566.  
  567. static unsigned _msize(void __near *pvBlock)
  568. {
  569.    PMEMBLOCK pmb;
  570.  
  571.  0250  53                _msize_         push    bx
  572.  
  573.    if (!pvBlock)
  574.       return 0;
  575.  
  576.  0251  85 c0                             test    ax,ax
  577.  0253  74 08                             je      L27
  578.  
  579.    pmb = (PMEMBLOCK) ((char __near *) pvBlock - HDR_SIZE);
  580.  
  581.  0255  89 c3                             mov     bx,ax
  582.  
  583.    return pmb->uSize;
  584.  0257  8b 47 fc                          mov     ax,[bx-4H]
  585.  025a  83 eb 08                          sub     bx,0008H
  586.  
  587. }
  588.  
  589.  
  590. /**@internal pmbAllocateBlock
  591.  *  Update all data structures for allocation of one memory block.  It's
  592.  *  assumed, on entry, that the block is large enough for the requested
  593.  *  allocation.
  594.  * @param PMEMBLOCK pmb - the current memory block on the Free list to
  595.  *  allocate.
  596.  * @param USHORT uRequest - size of the memory request to fill, not counting
  597.  *  memory block header.
  598.  * @param PMEMBLOCK pmbPrev - the memory block which precedes the block being
  599.  *  allocated in the Free list.  NULL if no predecessor (ie, pmb is pointed to
  600.  *  by ::pmbFree).
  601.  * @return PMEMBLOCK - pointer to the data part of the allocated memory block,
  602.  *  suitable for return to malloc() caller.
  603.  */
  604. static void __near *
  605.  025d  5b                L27             pop     bx
  606.  025e  c3                                ret     
  607.  025f  fc                                cld     
  608.  
  609. npvAllocateBlock( PMEMBLOCK pmb, USHORT uRequest, PMEMBLOCK pmbPrev )
  610. {
  611.    //pmb points to the selected block.
  612.    //pmbPrev points to the block prior to the selected block, NULL if pmbFree.
  613.    PMEMBLOCK pmbOldNext;            // Original free block that follows the block being allocated.
  614.    PMEMBLOCK pmbNewFree;            // Leftover free memory from the allocated block.
  615.  
  616.    // Split this block into an allocated + free part if it's big enough.
  617.  0260                    npvAllocateBlock_:
  618.  0260  56                                push    si
  619.  0261  57                                push    di
  620.  0262  89 c6                             mov     si,ax
  621.  0264  89 df                             mov     di,bx
  622.  
  623.    pmbNewFree = make_new_free( pmb, uRequest );
  624.  
  625.    // Update global memory counter.
  626.  0266  e8 00 00                          call    make_new_free_
  627.  0269  89 c3                             mov     bx,ax
  628.  
  629.    uMemFree -= (pmb->uSize + HDR_SIZE);
  630.  
  631.    // Add this block into the front of the Allocated list.
  632.    pmbOldNext = pmb->pmbNext;
  633.  026b  8b 44 04                          mov     ax,[si+4H]
  634.  026e  8b 16 00 00                       mov     dx,_uMemFree
  635.  0272  05 08 00                          add     ax,0008H
  636.  0275  29 c2                             sub     dx,ax
  637.  0277  89 16 00 00                       mov     _uMemFree,dx
  638.  
  639.  027b  8b 16 00 00                       mov     dx,_pmbUsed
  640.  
  641.    pmb->pmbNext = pmbUsed;
  642.  027f  8b 44 06                          mov     ax,[si+6H]
  643.  0282  89 54 06                          mov     [si+6H],dx
  644.  
  645.    pmbUsed = pmb;
  646.  
  647.    // Remove the new allocation from the Free list.
  648.  0285  89 36 00 00                       mov     _pmbUsed,si
  649.  
  650.    if (pmbNewFree) {                // If we split off a new free block
  651.  0289  85 db                             test    bx,bx
  652.  028b  74 12                             je      L29
  653.  
  654.       pmbNewFree->pmbNext = pmbOldNext;
  655.  028d  89 47 06                          mov     [bx+6H],ax
  656.  
  657.       if (pmbPrev)                  // If we're not at head of Free list
  658.  0290  85 ff                             test    di,di
  659.  0292  74 05                             je      L28
  660.  
  661.          pmbPrev->pmbNext = pmbNewFree;
  662.  0294  89 5d 06                          mov     [di+6H],bx
  663.  
  664.       else
  665.  0297  eb 16                             jmp     L31
  666.  
  667.          pmbFree = pmbNewFree;
  668.    }
  669.    else {                           // We allocated the entire free block.
  670.  0299  89 1e 00 00       L28             mov     _pmbFree,bx
  671.  029d  eb 10                             jmp     L31
  672.  
  673.       if (pmbPrev)                  // If we're not at head of Free list
  674.  029f  85 ff             L29             test    di,di
  675.  02a1  74 09                             je      L30
  676.  
  677.          pmbPrev->pmbNext = pmbOldNext;
  678.       else
  679.  02a3  89 45 06                          mov     [di+6H],ax
  680.  02a6  8d 44 08                          lea     ax,[si+8H]
  681.  02a9  5f                                pop     di
  682.  02aa  5e                                pop     si
  683.  02ab  c3                                ret     
  684.  
  685.          pmbFree = pmbOldNext;
  686.    }
  687.  
  688.  02ac  a3 00 00          L30             mov     _pmbFree,ax
  689.  
  690.    return (void __near *) pmb->achBlock;
  691.  02af  8d 44 08          L31             lea     ax,[si+8H]
  692.  
  693. }
  694.  
  695.  
  696. /* malloc()
  697. This function searches the list of free blocks until it finds one big enough
  698. to hold the amount of memory requested, which is passed in uSize.  The uSize
  699. request is sized up for:
  700.   - a memory block header
  701.   - four byte alignment
  702.   - minimum fragmentation
  703.  
  704. See helper function make_new_free() for discussion of fragmentation handling.
  705. */
  706.  
  707.  02b2  5f                                pop     di
  708.  02b3  5e                                pop     si
  709.  02b4  c3                                ret     
  710.  02b5  89 c0                             mov     ax,ax
  711.  02b7  fc                                cld     
  712.  
  713. void __near *malloc( unsigned uSize )
  714. {
  715.    USHORT uRequest;                    // Request size after alignment.
  716.    PMEMBLOCK pmb, pmbPrev;             // Use to walk free lists.
  717.    void __near *npvReturn = 0;         // Return value.
  718.  
  719.  02b8  53                malloc_         push    bx
  720.  02b9  51                                push    cx
  721.  02ba  52                                push    dx
  722.  02bb  56                                push    si
  723.  02bc  57                                push    di
  724.  02bd  89 c3                             mov     bx,ax
  725.  
  726.    ++nAllocCalls;                      // Diagnostics.
  727.    //HeapCheck((PSZ) "malloc() entry" );
  728.    //HeapCheck((PSZ)0);
  729.    HeapCheck((PSZ)"MEXX");
  730.  
  731.  02bf  8b 16 00 00                       mov     dx,_nAllocCalls
  732.  02c3  42                                inc     dx
  733.  02c4  b8 36 01                          mov     ax,offset L89
  734.  02c7  89 16 00 00                       mov     _nAllocCalls,dx
  735.  02cb  8c da                             mov     dx,ds
  736.  02cd  31 ff                             xor     di,di
  737.  02cf  e8 00 00                          call    HeapCheck_
  738.  
  739.    if (! uSize) return 0;
  740.  
  741.  02d2  85 db                             test    bx,bx
  742.  02d4  75 04                             jne     L32
  743.  02d6  31 c0                             xor     ax,ax
  744.  02d8  eb 6a                             jmp     L40
  745.  
  746.    uRequest = (uSize + 3) & -4;        // Force DWORD alignment.
  747.  
  748.  02da  8d 57 03          L32             lea     dx,[bx+3H]
  749.  
  750.    if (pmbFree->uSize >= uRequest)
  751.  02dd  8b 36 00 00                       mov     si,_pmbFree
  752.  02e1  80 e2 fc                          and     dl,0fcH
  753.  02e4  3b 54 04                          cmp     dx,[si+4H]
  754.  02e7  77 0b                             ja      L33
  755.  02e9  89 f0                             mov     ax,si
  756.  
  757.       npvReturn = npvAllocateBlock( pmbFree, uRequest, NULL );
  758.  02eb  31 db                             xor     bx,bx
  759.  02ed  e8 00 00                          call    npvAllocateBlock_
  760.  02f0  89 c7                             mov     di,ax
  761.  
  762.    else {
  763.  02f2  eb 20                             jmp     L36
  764.  
  765.       pmbPrev = pmbFree;
  766.  02f4  89 f3             L33             mov     bx,si
  767.  
  768.       for ( pmb=pmbFree->pmbNext; pmb; pmbPrev=pmb, pmb=pmb->pmbNext)
  769.  02f6  8b 74 06                          mov     si,[si+6H]
  770.  02f9  85 f6                             test    si,si
  771.  02fb  74 17                             je      L36
  772.  
  773.          if (pmb->uSize >= uRequest) {
  774.  02fd  3b 54 04          L34             cmp     dx,[si+4H]
  775.  0300  77 09                             ja      L35
  776.  
  777.             npvReturn = npvAllocateBlock( pmb, uRequest, pmbPrev );
  778.  0302  89 f0                             mov     ax,si
  779.  0304  e8 00 00                          call    npvAllocateBlock_
  780.  0307  89 c7                             mov     di,ax
  781.  
  782.             break;
  783.  0309  eb 09                             jmp     L36
  784.  
  785.          }
  786.    }
  787.  
  788.  030b  89 f3             L35             mov     bx,si
  789.  030d  8b 74 06                          mov     si,[si+6H]
  790.  0310  85 f6                             test    si,si
  791.  0312  75 e9                             jne     L34
  792.  
  793.    if (npvReturn)
  794.       //SignatureCheck( (PMEMBLOCK) (((PUCHAR) npvReturn) - HDR_SIZE), (PSZ) "malloc() exit, allocated block" );
  795.       //SignatureCheck( (PMEMBLOCK) (((PUCHAR) npvReturn) - HDR_SIZE), (PSZ)0);
  796.  0314  85 ff             L36             test    di,di
  797.  0316  74 0d                             je      L37
  798.  0318  bb 3c 01                          mov     bx,offset L90
  799.  
  800.       SignatureCheck( (PMEMBLOCK) (((PUCHAR) npvReturn) - HDR_SIZE), (PSZ)"MEAB");
  801.  031b  8d 45 f8                          lea     ax,[di-8H]
  802.  031e  8c d9                             mov     cx,ds
  803.  0320  e8 00 00                          call    SignatureCheck_
  804.  
  805.    else {
  806.       // Out of Memory !!!
  807. //    pError->vLog( HEAP_Err_NoMemory, (USHORT) uSize );
  808.  
  809. #ifdef HEMP_DBG
  810.  0323  eb 15                             jmp     L39
  811.  
  812. if (gCLflags & FLAGS_CL_DDPRINT)       ddprintf("~Out of memory, dumpheap()...\n");
  813.  0325  f6 06 01 00 40    L37             test    byte ptr _gCLflags+1H,40H
  814.  032a  74 0a                             je      L38
  815.  032c  1e                                push    ds
  816.  032d  68 42 01                          push    offset L91
  817.  0330  e8 00 00                          call    _ddprintf
  818.  0333  83 c4 04                          add     sp,0004H
  819.  
  820.       dumpheap();
  821. #endif
  822.  0336  e8 00 00          L38             call    dumpheap_
  823.  
  824.       int3();
  825.    }
  826.  
  827.    //HeapCheck((PSZ) "malloc() exit" );
  828.    //HeapCheck((PSZ)0);
  829.  0339  cc                                int     3
  830.  
  831.    HeapCheck((PSZ)"MXXX");
  832.  033a  b8 62 01          L39             mov     ax,offset L92
  833.  033d  8c da                             mov     dx,ds
  834.  033f  e8 00 00                          call    HeapCheck_
  835.  
  836.    return npvReturn;
  837.  0342  89 f8                             mov     ax,di
  838.  
  839. }
  840.  
  841. /* void compact(void)
  842. This function compacts the free blocks together.  This function is a
  843. companion to free(), and thus the algorithm is tailored to how free()
  844. works.  Change the algorithm in free(), and you'll have to change this
  845. function too.
  846.  
  847. When free() frees a block, it sets the head of the free list, pmbFree, to
  848. point to it.  Then the newly freed block points to whatever the old pmbFree
  849. pointed to.  In other words, each new free block is added to the head of
  850. the free list.
  851.  
  852. If compact() is always called after a block is freed, then it can be
  853. guaranteed that the free list is always compacted (i.e. you won't find
  854. two adjacent free blocks anywhere in the heap) _before_ each call to free().
  855. Therefore, the newly freed block can be located in only one of the
  856. following positions:
  857. 1. Not adjacent to any other free blocks (compacting not necessary)
  858. 2. Physically before another free block
  859. 3. Physically after another free block
  860. 4. Between two free blocks (i.e. the block occupies the entire space
  861.    between two free blocks)
  862.  
  863. Since the newly freed block is the first in the free list, compact()
  864. starts with the second block in the list (i.e. pmbFree->pmbNext).
  865. Each free block is then compared with the newly freed block for
  866. adjacency.  If a given block is located before the new block, then it
  867. can't possibly be also located after, and vice versa.  Hence, the
  868. "else if" statement in the middle of the loop.
  869.  
  870. Also, the newly freed block can only be adjacent to at most two other
  871. blocks.  Therefore, the operation of combining two adjacent free blocks can
  872. only happen at most twice.  The variable nFreed counts the number of times
  873. two blocks are combined.  The function exits if nFreed reaches two.  nFreed
  874. is initially 0.
  875.  
  876. Helper macro after() takes a PMEMBLOCK (call it pmb) as a parameter,
  877. and calculates where an adjacent free block would exist if it were
  878. physically located after pmb.
  879.  
  880. Helper function remove() removes an element from the free list.
  881. */
  882.  
  883. #define after(pmb) ((PMEMBLOCK) ((char __near *) pmb + pmb->uSize + HDR_SIZE))
  884.  
  885.  0344  5f                L40             pop     di
  886.  0345  5e                                pop     si
  887.  0346  5a                                pop     dx
  888.  0347  59                                pop     cx
  889.  0348  5b                                pop     bx
  890.  0349  c3                                ret     
  891.  034a  89 c0                             mov     ax,ax
  892.  
  893. static void remove(PMEMBLOCK pmb)
  894. {
  895.    PMEMBLOCK pmbPrev;
  896.  
  897.  034c  53                remove_         push    bx
  898.  034d  56                                push    si
  899.  034e  57                                push    di
  900.  034f  8b 3e 00 00                       mov     di,_pmbFree
  901.  0353  89 c6                             mov     si,ax
  902.  
  903.    if (pmb == pmbFree) {
  904.  0355  39 f8                             cmp     ax,di
  905.  0357  75 05                             jne     L41
  906.  
  907.       pmbFree = pmbFree->pmbNext;
  908.  0359  8b 7d 06                          mov     di,[di+6H]
  909.  
  910.       return;
  911.    }
  912.  
  913.  035c  eb 20                             jmp     L44
  914.  
  915.    for (pmbPrev=pmbFree; pmbPrev; pmbPrev=pmbPrev->pmbNext)
  916.  035e  89 fb             L41             mov     bx,di
  917.  0360  85 ff                             test    di,di
  918.  0362  74 1a                             je      L44
  919.  
  920.       if (pmbPrev->pmbNext == pmb) {
  921.  0364  3b 77 06          L42             cmp     si,[bx+6H]
  922.  0367  75 0e                             jne     L43
  923.  
  924.          pmbPrev->pmbNext = pmb->pmbNext;
  925.          return;
  926.  0369  8b 74 06                          mov     si,[si+6H]
  927.  036c  89 77 06                          mov     [bx+6H],si
  928.  036f  89 3e 00 00                       mov     _pmbFree,di
  929.  0373  5f                                pop     di
  930.  0374  5e                                pop     si
  931.  0375  5b                                pop     bx
  932.  0376  c3                                ret     
  933.  
  934.       }
  935.  0377  8b 5f 06          L43             mov     bx,[bx+6H]
  936.  037a  85 db                             test    bx,bx
  937.  037c  75 e6                             jne     L42
  938.  
  939. }
  940.  
  941.  037e  89 3e 00 00       L44             mov     _pmbFree,di
  942.  0382  5f                                pop     di
  943.  0383  5e                                pop     si
  944.  0384  5b                                pop     bx
  945.  0385  c3                                ret     
  946.  0386  89 c0                             mov     ax,ax
  947.  
  948. static void compact(void)
  949. {
  950.    PMEMBLOCK pmb;
  951.    int iFreed = 0;
  952.  
  953.  0388  53                compact_        push    bx
  954.  0389  51                                push    cx
  955.  038a  52                                push    dx
  956.  038b  56                                push    si
  957.  038c  57                                push    di
  958.  038d  55                                push    bp
  959.  038e  89 e5                             mov     bp,sp
  960.  0390  83 ec 02                          sub     sp,0002H
  961.  
  962.    for (pmb=pmbFree->pmbNext; pmb; pmb=pmb->pmbNext) {
  963.  0393  8b 3e 00 00                       mov     di,_pmbFree
  964.  0397  31 d2                             xor     dx,dx
  965.  0399  8b 7d 06                          mov     di,[di+6H]
  966.  039c  89 56 fe                          mov     [bp-2H],dx
  967.  039f  85 ff                             test    di,di
  968.  03a1  0f 84 ff 00                       je      L61
  969.  
  970.       if (pmb == pmb->pmbNext) {
  971. #ifdef HEMP_DBG
  972.  03a5  8b 5d 06          L45             mov     bx,[di+6H]
  973.  03a8  39 df                             cmp     di,bx
  974.  03aa  75 14                             jne     L47
  975.  
  976. if (gCLflags & FLAGS_CL_DDPRINT)          ddprintf("~HEAP: heap loop, %p points to itself\n", (void __far *) pmb);
  977. #endif
  978.  03ac  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  979.  03b1  74 0c                             je      L46
  980.  03b3  1e                                push    ds
  981.  03b4  53                                push    bx
  982.  03b5  1e                                push    ds
  983.  03b6  68 68 01                          push    offset L93
  984.  03b9  e8 00 00                          call    _ddprintf
  985.  03bc  83 c4 08                          add     sp,0008H
  986.  
  987.          int3();
  988.       }
  989.  
  990.  03bf  cc                L46             int     3
  991.  
  992.       if (after(pmb)  == pmbFree) {
  993. #ifdef HEMP_DBG
  994.  03c0  8b 5d 04          L47             mov     bx,[di+4H]
  995.  03c3  01 fb                             add     bx,di
  996.  03c5  8b 0e 00 00                       mov     cx,_pmbFree
  997.  03c9  83 c3 08                          add     bx,0008H
  998.  03cc  39 cb                             cmp     bx,cx
  999.  03ce  75 61                             jne     L53
  1000.  
  1001. if (gCLflags & FLAGS_CL_DDPRINT)  ddprintf("~HEAP: compact found pointer %p (size=%u) before pmbFree %p\n", (void __far *) pmb, pmb->uSize, (void __far *) pmbFree);
  1002. #endif
  1003.  03d0  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  1004.  03d5  74 12                             je      L48
  1005.  03d7  1e                                push    ds
  1006.  03d8  51                                push    cx
  1007.  03d9  8b 5d 04                          mov     bx,[di+4H]
  1008.  03dc  53                                push    bx
  1009.  03dd  1e                                push    ds
  1010.  03de  57                                push    di
  1011.  03df  1e                                push    ds
  1012.  03e0  68 90 01                          push    offset L94
  1013.  03e3  e8 00 00                          call    _ddprintf
  1014.  03e6  83 c4 0e                          add     sp,000eH
  1015.  
  1016.          pmb->uSize += HDR_SIZE + pmbFree->uSize;
  1017.  03e9  a1 00 00          L48             mov     ax,_pmbFree
  1018.  03ec  89 c3                             mov     bx,ax
  1019.  03ee  8b 5f 04                          mov     bx,[bx+4H]
  1020.  03f1  8b 4d 04                          mov     cx,[di+4H]
  1021.  03f4  83 c3 08                          add     bx,0008H
  1022.  03f7  01 d9                             add     cx,bx
  1023.  
  1024.          remove(pmbFree);
  1025.  03f9  89 c6                             mov     si,ax
  1026.  03fb  89 4d 04                          mov     [di+4H],cx
  1027.  03fe  39 c0                             cmp     ax,ax
  1028.  0400  75 09                             jne     L49
  1029.  0402  8b 5c 06                          mov     bx,[si+6H]
  1030.  0405  89 1e 00 00                       mov     _pmbFree,bx
  1031.  0409  eb 1a                             jmp     L52
  1032.  040b  89 c3             L49             mov     bx,ax
  1033.  040d  85 c0                             test    ax,ax
  1034.  040f  74 14                             je      L52
  1035.  0411  3b 77 06          L50             cmp     si,[bx+6H]
  1036.  0414  75 08                             jne     L51
  1037.  0416  8b 74 06                          mov     si,[si+6H]
  1038.  0419  89 77 06                          mov     [bx+6H],si
  1039.  041c  eb 07                             jmp     L52
  1040.  041e  8b 5f 06          L51             mov     bx,[bx+6H]
  1041.  0421  85 db                             test    bx,bx
  1042.  0423  75 ec                             jne     L50
  1043.  
  1044.          if (++iFreed == 2) goto exit;
  1045.  0425  8b 76 fe          L52             mov     si,[bp-2H]
  1046.  0428  46                                inc     si
  1047.  0429  89 76 fe                          mov     [bp-2H],si
  1048.  042c  83 fe 02                          cmp     si,0002H
  1049.  042f  eb 68                             jmp     L59
  1050.  
  1051.       } else if (after(pmbFree) == pmb) {
  1052. #ifdef HEMP_DBG
  1053.  0431  89 cb             L53             mov     bx,cx
  1054.  0433  8b 77 04                          mov     si,[bx+4H]
  1055.  0436  01 ce                             add     si,cx
  1056.  0438  83 c6 08                          add     si,0008H
  1057.  043b  39 fe                             cmp     si,di
  1058.  043d  75 5c                             jne     L60
  1059.  
  1060. if (gCLflags & FLAGS_CL_DDPRINT)  ddprintf("~HEAP: compact found pointer %p (size=%u) after pmbFree %p\n", (void __far *) pmb, pmb->uSize, (void __far *) pmbFree);
  1061. #endif
  1062.  043f  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  1063.  0444  74 12                             je      L54
  1064.  0446  1e                                push    ds
  1065.  0447  51                                push    cx
  1066.  0448  8b 75 04                          mov     si,[di+4H]
  1067.  044b  56                                push    si
  1068.  044c  1e                                push    ds
  1069.  044d  57                                push    di
  1070.  044e  1e                                push    ds
  1071.  044f  68 ce 01                          push    offset L95
  1072.  0452  e8 00 00                          call    _ddprintf
  1073.  0455  83 c4 0e                          add     sp,000eH
  1074.  
  1075.          pmbFree->uSize += HDR_SIZE + pmb->uSize;
  1076.  0458  a1 00 00          L54             mov     ax,_pmbFree
  1077.  045b  8b 5d 04                          mov     bx,[di+4H]
  1078.  045e  89 c6                             mov     si,ax
  1079.  0460  83 c3 08                          add     bx,0008H
  1080.  0463  01 5c 04                          add     [si+4H],bx
  1081.  
  1082.          remove(pmb);
  1083.  0466  89 fe                             mov     si,di
  1084.  0468  39 c7                             cmp     di,ax
  1085.  046a  75 09                             jne     L55
  1086.  046c  8b 5d 06                          mov     bx,[di+6H]
  1087.  046f  89 1e 00 00                       mov     _pmbFree,bx
  1088.  0473  eb 1a                             jmp     L58
  1089.  0475  89 c3             L55             mov     bx,ax
  1090.  0477  85 c0                             test    ax,ax
  1091.  0479  74 14                             je      L58
  1092.  047b  3b 77 06          L56             cmp     si,[bx+6H]
  1093.  047e  75 08                             jne     L57
  1094.  0480  8b 74 06                          mov     si,[si+6H]
  1095.  0483  89 77 06                          mov     [bx+6H],si
  1096.  0486  eb 07                             jmp     L58
  1097.  0488  8b 5f 06          L57             mov     bx,[bx+6H]
  1098.  048b  85 db                             test    bx,bx
  1099.  048d  75 ec                             jne     L56
  1100.  
  1101.          if (++iFreed == 2) goto exit;
  1102.       }
  1103.  048f  8b 56 fe          L58             mov     dx,[bp-2H]
  1104.  0492  42                                inc     dx
  1105.  0493  89 56 fe                          mov     [bp-2H],dx
  1106.  0496  83 fa 02                          cmp     dx,0002H
  1107.  0499  74 09             L59             je      L61
  1108.  
  1109.    }
  1110.  
  1111. exit:
  1112.  049b  8b 7d 06          L60             mov     di,[di+6H]
  1113.  049e  85 ff                             test    di,di
  1114.  04a0  0f 85 01 ff                       jne     L45
  1115.  
  1116.    nCompact += iFreed;
  1117.  04a4  8b 46 fe          L61             mov     ax,[bp-2H]
  1118.  04a7  01 06 00 00                       add     _nCompact,ax
  1119.  
  1120. }
  1121.  
  1122.  04ab  89 ec                             mov     sp,bp
  1123.  04ad  5d                                pop     bp
  1124.  04ae  5f                                pop     di
  1125.  04af  5e                                pop     si
  1126.  04b0  5a                                pop     dx
  1127.  04b1  59                                pop     cx
  1128.  04b2  5b                                pop     bx
  1129.  04b3  c3                                ret     
  1130.  
  1131. void free(void __near *pvBlock)
  1132. {
  1133.    PMEMBLOCK pmb,pmbPrev,pmbBlock;
  1134.    int fSentinel;
  1135.  
  1136.  04b4  53                free_           push    bx
  1137.  04b5  51                                push    cx
  1138.  04b6  52                                push    dx
  1139.  04b7  56                                push    si
  1140.  04b8  57                                push    di
  1141.  04b9  55                                push    bp
  1142.  04ba  89 e5                             mov     bp,sp
  1143.  04bc  83 ec 02                          sub     sp,0002H
  1144.  
  1145.    ++nFreeCalls;
  1146.  04bf  ff 06 00 00                       inc     word ptr _nFreeCalls
  1147.  
  1148.    if (!pvBlock) return;     // support freeing of NULL
  1149.  
  1150.  04c3  85 c0                             test    ax,ax
  1151.  04c5  0f 84 99 00                       je      L68
  1152.  
  1153.    pmbBlock=(PMEMBLOCK) ((char __near *) pvBlock - HDR_SIZE);
  1154.  
  1155.    //SignatureCheck( pmbBlock,(PSZ) "free() entry, Block to be freed" );
  1156.    //SignatureCheck( pmbBlock,(PSZ)0);
  1157.  04c9  89 c7                             mov     di,ax
  1158.  
  1159.    SignatureCheck( pmbBlock,(PSZ)"FEBF");
  1160.    //HeapCheck((PSZ) "free() entry" );
  1161.    //HeapCheck((PSZ)0);
  1162.  04cb  bb 0a 02                          mov     bx,offset L96
  1163.  04ce  83 ef 08                          sub     di,0008H
  1164.  04d1  8c d9                             mov     cx,ds
  1165.  04d3  89 f8                             mov     ax,di
  1166.  04d5  8c da                             mov     dx,ds
  1167.  04d7  e8 00 00                          call    SignatureCheck_
  1168.  
  1169.    HeapCheck((PSZ)"FEXX");
  1170.  
  1171.  04da  b8 10 02                          mov     ax,offset L97
  1172.  04dd  e8 00 00                          call    HeapCheck_
  1173.  
  1174.    uMemFree += pmbBlock->uSize + HDR_SIZE;
  1175.  
  1176.  04e0  8b 45 04                          mov     ax,[di+4H]
  1177.  04e3  8b 1e 00 00                       mov     bx,_uMemFree
  1178.  04e7  05 08 00                          add     ax,0008H
  1179.  04ea  01 c3                             add     bx,ax
  1180.  
  1181.    if (pmbBlock == pmbUsed) {       // are we freeing the first block?
  1182.  04ec  8b 0e 00 00                       mov     cx,_pmbUsed
  1183.  04f0  89 1e 00 00                       mov     _uMemFree,bx
  1184.  04f4  39 cf                             cmp     di,cx
  1185.  04f6  75 15                             jne     L62
  1186.  
  1187.       pmbUsed = pmbUsed->pmbNext;   // the 2nd block is now the 1st
  1188.  04f8  8b 45 06                          mov     ax,[di+6H]
  1189.  04fb  a3 00 00                          mov     _pmbUsed,ax
  1190.  
  1191.       pmbBlock->pmbNext = pmbFree;  // this block is now free, so it points to 1st free block
  1192.  04fe  a1 00 00                          mov     ax,_pmbFree
  1193.  0501  89 45 06                          mov     [di+6H],ax
  1194.  
  1195.       pmbFree = pmbBlock;           // this is now the 1st free block
  1196.  0504  89 0e 00 00                       mov     _pmbFree,cx
  1197.  
  1198.       compact();
  1199.  0508  e8 00 00                          call    compact_
  1200.  
  1201.       goto exit;
  1202.    }
  1203.  
  1204.  050b  eb 4d                             jmp     L67
  1205.  
  1206.    pmbPrev=pmbUsed;
  1207.    fSentinel = FALSE;
  1208.  050d  89 cb             L62             mov     bx,cx
  1209.  050f  89 4e fe                          mov     [bp-2H],cx
  1210.  
  1211.  0512  8b 77 06                          mov     si,[bx+6H]
  1212.  
  1213.    for (pmb=pmbUsed->pmbNext; pmb; pmbPrev=pmb, pmb=pmb->pmbNext)
  1214.  0515  31 c0                             xor     ax,ax
  1215.  0517  85 f6                             test    si,si
  1216.  0519  74 3f                             je      L67
  1217.  
  1218.       if (pmb == pmbBlock) {
  1219.  051b  39 fe             L63             cmp     si,di
  1220.  051d  75 31                             jne     L66
  1221.  
  1222.          if (fSentinel) {
  1223. #ifdef HEMP_DBG
  1224.  051f  85 c0                             test    ax,ax
  1225.  0521  74 14                             je      L65
  1226.  
  1227. if (gCLflags & FLAGS_CL_DDPRINT)             ddprintf("~HEAP: free sentinel triggered, pmb=%p\n", (void __far *) pmb);
  1228. #endif
  1229.  0523  f6 06 01 00 40                    test    byte ptr _gCLflags+1H,40H
  1230.  0528  74 0c                             je      L64
  1231.  052a  1e                                push    ds
  1232.  052b  57                                push    di
  1233.  052c  1e                                push    ds
  1234.  052d  68 16 02                          push    offset L98
  1235.  0530  e8 00 00                          call    _ddprintf
  1236.  0533  83 c4 08                          add     sp,0008H
  1237.  
  1238.             int3();
  1239.  0536  cc                L64             int     3
  1240.  
  1241.          }
  1242.  0537  8b 5e fe          L65             mov     bx,[bp-2H]
  1243.  
  1244.          pmbPrev->pmbNext = pmb->pmbNext;   // delete this block from the chain
  1245.  053a  8b 44 06                          mov     ax,[si+6H]
  1246.  053d  89 47 06                          mov     [bx+6H],ax
  1247.  
  1248.          pmbBlock->pmbNext = pmbFree;
  1249.  0540  a1 00 00                          mov     ax,_pmbFree
  1250.  0543  89 45 06                          mov     [di+6H],ax
  1251.  
  1252.          pmbFree = pmbBlock;
  1253.  0546  89 3e 00 00                       mov     _pmbFree,di
  1254.  
  1255.          compact();
  1256.  054a  e8 00 00                          call    compact_
  1257.  
  1258.          fSentinel = TRUE;
  1259.  054d  b8 01 00                          mov     ax,0001H
  1260.  
  1261.       }
  1262.  
  1263. exit: //--- Check things are still intact.
  1264.    //HeapCheck((PSZ) "free() exit" );
  1265.    //HeapCheck((PSZ)0);
  1266.  0550  89 76 fe          L66             mov     [bp-2H],si
  1267.  0553  8b 74 06                          mov     si,[si+6H]
  1268.  0556  85 f6                             test    si,si
  1269.  0558  75 c1                             jne     L63
  1270.  
  1271.    HeapCheck((PSZ)"FXXX");
  1272.  055a  b8 3e 02          L67             mov     ax,offset L99
  1273.  055d  8c da                             mov     dx,ds
  1274.  055f  e8 00 00                          call    HeapCheck_
  1275.  
  1276. }
  1277.  
  1278.  0562  89 ec             L68             mov     sp,bp
  1279.  0564  5d                                pop     bp
  1280.  0565  5f                                pop     di
  1281.  0566  5e                                pop     si
  1282.  0567  5a                                pop     dx
  1283.  0568  59                                pop     cx
  1284.  0569  5b                                pop     bx
  1285.  056a  c3                                ret     
  1286.  056b  fc                                cld     
  1287.  
  1288. unsigned _memfree(void)
  1289. {
  1290.    return uMemFree;
  1291.  056c  a1 00 00          _memfree_       mov     ax,_uMemFree
  1292.  
  1293. }
  1294.  
  1295.  056f  c3                                ret     
  1296.  
  1297. void __near *realloc(void __near *pvBlock, unsigned usLength)
  1298. {
  1299.    void __near *pv;
  1300.  
  1301.  0570  53                realloc_        push    bx
  1302.  0571  51                                push    cx
  1303.  0572  56                                push    si
  1304.  0573  57                                push    di
  1305.  0574  55                                push    bp
  1306.  0575  89 e5                             mov     bp,sp
  1307.  0577  83 ec 04                          sub     sp,0004H
  1308.  057a  89 46 fe                          mov     [bp-2H],ax
  1309.  
  1310.    if (!pvBlock)                 // if ptr is null, alloc block
  1311.  057d  85 c0                             test    ax,ax
  1312.  057f  75 08                             jne     L69
  1313.  
  1314.       return malloc(usLength);
  1315.  
  1316.  0581  89 d0                             mov     ax,dx
  1317.  0583  e8 00 00                          call    malloc_
  1318.  0586  e9 7e 00                          jmp     L77
  1319.  
  1320.    if (!usLength) {              // if length is 0, free block
  1321.  0589  85 d2             L69             test    dx,dx
  1322.  058b  75 0d                             jne     L70
  1323.  
  1324.       free(pvBlock);
  1325.  058d  e8 00 00                          call    free_
  1326.  
  1327.       return 0;
  1328.    }
  1329.  
  1330.  0590  31 c0                             xor     ax,ax
  1331.  0592  89 ec                             mov     sp,bp
  1332.  0594  5d                                pop     bp
  1333.  0595  5f                                pop     di
  1334.  0596  5e                                pop     si
  1335.  0597  59                                pop     cx
  1336.  0598  5b                                pop     bx
  1337.  0599  c3                                ret     
  1338.  
  1339.    pv=malloc(usLength);          // attempt to allocate the new block
  1340.  059a  89 d0             L70             mov     ax,dx
  1341.  059c  e8 00 00                          call    malloc_
  1342.  059f  89 46 fc                          mov     [bp-4H],ax
  1343.  
  1344.    if (!pv)                      // can't do it?
  1345.       return 0;                  // just fail.  Version 2 will try harder
  1346.  
  1347.  05a2  85 c0                             test    ax,ax
  1348.  05a4  74 61                             je      L77
  1349.  
  1350.    MEMCPY(pv, pvBlock, min( _msize(pvBlock), usLength));
  1351.  05a6  8b 46 fe                          mov     ax,[bp-2H]
  1352.  05a9  e8 00 00                          call    _msize_
  1353.  05ac  39 d0                             cmp     ax,dx
  1354.  05ae  73 0a                             jae     L71
  1355.  05b0  8b 46 fe                          mov     ax,[bp-2H]
  1356.  05b3  e8 00 00                          call    _msize_
  1357.  05b6  89 c1                             mov     cx,ax
  1358.  05b8  eb 02                             jmp     L72
  1359.  05ba  89 d1             L71             mov     cx,dx
  1360.  05bc  8b 76 fe          L72             mov     si,[bp-2H]
  1361.  05bf  8c da                             mov     dx,ds
  1362.  05c1  8b 7e fc                          mov     di,[bp-4H]
  1363.  05c4  8e c2                             mov     es,dx
  1364.  05c6  fc                                cld     
  1365.  05c7  1e                                push    ds
  1366.  05c8  8e da                             mov     ds,dx
  1367.  05ca  85 c9                             test    cx,cx
  1368.  05cc  74 2f                             je      L76
  1369.  05ce  f7 c1 20 00                       test    cx,0020H
  1370.  05d2  72 27                             jb      L75
  1371.  05d4  f7 c7 03 00                       test    di,0003H
  1372.  05d8  74 12                             je      L74
  1373.  05da  f7 c7 01 00                       test    di,0001H
  1374.  05de  74 08                             je      L73
  1375.  05e0  a4                                movsb   
  1376.  05e1  49                                dec     cx
  1377.  05e2  f7 c7 02 00                       test    di,0002H
  1378.  05e6  74 04                             je      L74
  1379.  05e8  a5                L73             movsw   
  1380.  05e9  83 e9 02                          sub     cx,0002H
  1381.  05ec  88 cb             L74             mov     bl,cl
  1382.  05ee  c1 e9 02                          shr     cx,02H
  1383.  05f1  f3 66 a5                          repe    movsd    
  1384.  05f4  80 e3 03                          and     bl,03H
  1385.  05f7  74 04                             je      L76
  1386.  05f9  88 d9                             mov     cl,bl
  1387.  05fb  f3 a4             L75             repe    movsb    
  1388.  05fd  1f                L76             pop     ds
  1389.  
  1390.    free(pvBlock);
  1391.  05fe  8b 46 fe                          mov     ax,[bp-2H]
  1392.  0601  e8 00 00                          call    free_
  1393.  
  1394.    return pv;
  1395.  0604  8b 46 fc                          mov     ax,[bp-4H]
  1396.  
  1397. }
  1398.  
  1399. #pragma code_seg ("_INITTEXT");
  1400.  
  1401. extern endHeap, endData;
  1402.  
  1403. // probably only want to use HEAP_SIZE for size since it's hard-coded a lot above
  1404. // this uSize arg is probably for a future thing
  1405.  
  1406.  0607  89 ec             L77             mov     sp,bp
  1407.  0609  5d                                pop     bp
  1408.  060a  5f                                pop     di
  1409.  060b  5e                                pop     si
  1410.  060c  59                                pop     cx
  1411.  060d  5b                                pop     bx
  1412.  060e  c3                                ret     
  1413.  
  1414. No disassembly errors
  1415.  
  1416. List of external symbols
  1417.  
  1418. Symbol
  1419. ----------------
  1420. _pmbUsed         000004fc 000004ee 00000287 0000027d 00000160 0000000d
  1421. _gCLflags        00000525 00000441 000003d2 000003ae 00000327 000001f0 00000140 000000d9 000000c4 00000095
  1422.                  00000079 0000005e 0000002f 00000013
  1423. _ddprintf        00000531 00000453 000003e4 000003ba 00000331 000001fa 0000014d 000000f6 000000d2 000000a5
  1424.                  00000088 0000006c 0000003f 00000022
  1425. _pmbFree         00000548 00000541 00000506 000004ff 00000471 00000459 00000407 000003ea 000003c7 00000395
  1426.                  00000380 00000371 00000351 000002df 000002ad 0000029b 0000019e 00000073
  1427. _nFreeCalls      000004c1 000000e0
  1428. _nFree           000001c0 000001af 000001a1 000000e5
  1429. _nAllocCalls     000002c9 000002c1 000000ea
  1430. _nAlloc          00000184 00000173 00000164 000000ee
  1431. _acHeap          0000010f 0000010a
  1432. _cAlloc          000001de 0000018e 00000177 00000168
  1433. SignatureCheck_  000004d8 00000321 000001cd 00000191
  1434. _cFree           000001e2 000001c4 000001b6 000001a4
  1435. _fMemoryDoc      000001d8
  1436. _cTotalHeap      000001e6
  1437. dumpheap_        00000337 00000200
  1438. make_new_free_   00000267
  1439. _uMemFree        0000056d 000004f2 000004e5 00000279 00000270
  1440. HeapCheck_       00000560 000004de 00000340 000002d0
  1441. npvAllocateBlock_ 
  1442.                  00000305 000002ee
  1443. _nCompact        000004a9
  1444. compact_         0000054b 00000509
  1445. malloc_          0000059d 00000584
  1446. free_            00000602 0000058e
  1447. _msize_          000005b4 000005aa
  1448. ------------------------------------------------------------
  1449.  
  1450. Segment: CONST  WORD   00000243 bytes  
  1451.  0000  7e 48 45 41 50 3a 20 48 L78             - ~HEAP: H
  1452.  0008  65 61 70 20 44 75 6d 70                 - eap Dump
  1453.  0010  20 2d 20 55 73 65 64 20                 -  - Used 
  1454.  0018  62 6c 6f 63 6b 73 0a 00                 - blocks..
  1455.  0020  7e 20 20 70 6d 62 3d 25 L79             - ~  pmb=%
  1456.  0028  70 2c 20 62 74 79 65 73                 - p, btyes
  1457.  0030  3d 25 75 0a 00 00                       - =%u...
  1458.  0036  7e 20 20 54 6f 74 61 6c L80             - ~  Total
  1459.  003e  20 75 73 65 64 20 3d 20                 -  used = 
  1460.  0046  25 75 0a 00                             - %u..
  1461.  004a  7e 48 45 41 50 3a 20 48 L81             - ~HEAP: H
  1462.  0052  65 61 70 20 44 75 6d 70                 - eap Dump
  1463.  005a  20 2d 20 46 72 65 65 20                 -  - Free 
  1464.  0062  62 6c 6f 63 6b 73 0a 00                 - blocks..
  1465.  006a  7e 20 20 70 6d 62 3d 25 L82             - ~  pmb=%
  1466.  0072  70 2c 20 62 79 74 65 73                 - p, bytes
  1467.  007a  3d 25 75 0a 00 00                       - =%u...
  1468.  0080  7e 20 20 54 6f 74 61 6c L83             - ~  Total
  1469.  0088  20 66 72 65 65 20 3d 20                 -  free = 
  1470.  0090  25 75 0a 00                             - %u..
  1471.  0094  7e 20 61 6c 6c 6f 63 3a L84             - ~ alloc:
  1472.  009c  63 75 72 72 62 6c 6b 73                 - currblks
  1473.  00a4  3d 25 75 2c 20 63 61 6c                 - =%u, cal
  1474.  00ac  6c 73 3d 25 75 3b 20 20                 - ls=%u;  
  1475.  00b4  66 72 65 65 3a 63 75 72                 - free:cur
  1476.  00bc  72 62 6c 6b 73 3d 25 75                 - rblks=%u
  1477.  00c4  2c 20 63 61 6c 6c 73 3d                 - , calls=
  1478.  00cc  25 75 0a 00                             - %u..
  1479.  00d0  7e 48 65 61 70 20 70 6f L85             - ~Heap po
  1480.  00d8  69 6e 74 65 72 20 6f 75                 - inter ou
  1481.  00e0  74 20 6f 66 20 72 61 6e                 - t of ran
  1482.  00e8  67 65 2c 20 6f 72 20 73                 - ge, or s
  1483.  00f0  69 67 6e 61 74 75 72 65                 - ignature
  1484.  00f8  20 65 78 63 65 70 74 69                 -  excepti
  1485.  0100  6f 6e 3a 20 25 70 20 25                 - on: %p %
  1486.  0108  73 0a 00 50                             - s..P
  1487.  010c  48 43 55 4c 00 70       L86             - HCUL.p
  1488.  0112  48 43 46 4c 00 20       L87             - HCFL. 
  1489.  0118  7e 48 65 61 70 20 41 6c L88             - ~Heap Al
  1490.  0120  6c 6f 63 20 2b 20 46 72                 - loc + Fr
  1491.  0128  65 65 20 21 3d 20 54 6f                 - ee != To
  1492.  0130  74 61 6c 0a 00 65                       - tal..e
  1493.  0136  4d 45 58 58 00 00       L89             - MEXX..
  1494.  013c  4d 45 41 42 00 6f       L90             - MEAB.o
  1495.  0142  7e 4f 75 74 20 6f 66 20 L91             - ~Out of 
  1496.  014a  6d 65 6d 6f 72 79 2c 20                 - memory, 
  1497.  0152  64 75 6d 70 68 65 61 70                 - dumpheap
  1498.  015a  28 29 2e 2e 2e 0a 00 3d                 - ().....=
  1499.  0162  4d 58 58 58 00 61       L92             - MXXX.a
  1500.  0168  7e 48 45 41 50 3a 20 68 L93             - ~HEAP: h
  1501.  0170  65 61 70 20 6c 6f 6f 70                 - eap loop
  1502.  0178  2c 20 25 70 20 70 6f 69                 - , %p poi
  1503.  0180  6e 74 73 20 74 6f 20 69                 - nts to i
  1504.  0188  74 73 65 6c 66 0a 00 65                 - tself..e
  1505.  0190  7e 48 45 41 50 3a 20 63 L94             - ~HEAP: c
  1506.  0198  6f 6d 70 61 63 74 20 66                 - ompact f
  1507.  01a0  6f 75 6e 64 20 70 6f 69                 - ound poi
  1508.  01a8  6e 74 65 72 20 25 70 20                 - nter %p 
  1509.  01b0  28 73 69 7a 65 3d 25 75                 - (size=%u
  1510.  01b8  29 20 62 65 66 6f 72 65                 - ) before
  1511.  01c0  20 70 6d 62 46 72 65 65                 -  pmbFree
  1512.  01c8  20 25 70 0a 00 00                       -  %p...
  1513.  01ce  7e 48 45 41 50 3a 20 63 L95             - ~HEAP: c
  1514.  01d6  6f 6d 70 61 63 74 20 66                 - ompact f
  1515.  01de  6f 75 6e 64 20 70 6f 69                 - ound poi
  1516.  01e6  6e 74 65 72 20 25 70 20                 - nter %p 
  1517.  01ee  28 73 69 7a 65 3d 25 75                 - (size=%u
  1518.  01f6  29 20 61 66 74 65 72 20                 - ) after 
  1519.  01fe  70 6d 62 46 72 65 65 20                 - pmbFree 
  1520.  0206  25 70 0a 00                             - %p..
  1521.  020a  46 45 42 46 00 64       L96             - FEBF.d
  1522.  0210  46 45 58 58 00 61       L97             - FEXX.a
  1523.  0216  7e 48 45 41 50 3a 20 66 L98             - ~HEAP: f
  1524.  021e  72 65 65 20 73 65 6e 74                 - ree sent
  1525.  0226  69 6e 65 6c 20 74 72 69                 - inel tri
  1526.  022e  67 67 65 72 65 64 2c 20                 - ggered, 
  1527.  0236  70 6d 62 3d 25 70 0a 00                 - pmb=%p..
  1528.  023e  46 58 58 58 00          L99             - FXXX.
  1529.  
  1530. No disassembly errors
  1531.  
  1532. ------------------------------------------------------------
  1533.  
  1534. Segment: _DATA  WORD   00000014 bytes  
  1535.  0000  00 00                   _pmbUsed        - ..
  1536.  0002  00 00                   _fMemoryDoc     - ..
  1537.  0004  00 00                   _nAlloc         - ..
  1538.  0006  00 00                   _cAlloc         - ..
  1539.  0008  00 00                   _nAllocCalls    - ..
  1540.  000a  00 00                   _nFree          - ..
  1541.  000c  00 00                   _cFree          - ..
  1542.  000e  00 00                   _nFreeCalls     - ..
  1543.  0010  00 00                   _nCompact       - ..
  1544.  0012  00 20                   _cTotalHeap     - . 
  1545.  
  1546. No disassembly errors
  1547.  
  1548. ------------------------------------------------------------
  1549.  
  1550. Segment: _BSS  PARA   00002004 bytes  
  1551.  
  1552. No disassembly errors
  1553.  
  1554. ------------------------------------------------------------
  1555.  
  1556. Segment: _INITTEXT  PARA   00000046 bytes  
  1557.  
  1558. unsigned HeapInit(unsigned uSize) {
  1559.  
  1560.  0000  53                HeapInit_       push    bx
  1561.  0001  51                                push    cx
  1562.  0002  52                                push    dx
  1563.  0003  56                                push    si
  1564.  
  1565.  unsigned max_heap=((unsigned)&endHeap - (unsigned)&endData) & ~0xFFF; // align to K
  1566.  
  1567. // if (!uSize) uSize = DEFAULT_HEAP;
  1568.  0004  ba 00 00                          mov     dx,offset _endHeap
  1569.  0007  81 ea 00 00                       sub     dx,offset _endData
  1570.  000b  30 d2                             xor     dl,dl
  1571.  000d  80 e6 f0                          and     dh,0f0H
  1572.  
  1573.  if (!uSize) uSize = HEAP_SIZE;
  1574.  0010  85 c0                             test    ax,ax
  1575.  0012  75 03                             jne     L100
  1576.  0014  b8 00 20                          mov     ax,2000H
  1577.  
  1578.  if (uSize > max_heap) uSize = max_heap;
  1579.  
  1580.  0017  39 d0             L100            cmp     ax,dx
  1581.  0019  76 02                             jbe     L101
  1582.  001b  89 d0                             mov     ax,dx
  1583.  
  1584.  pmbFree=(PMEMBLOCK) acHeap;
  1585.  pmbFree->uSize = uSize - HDR_SIZE;
  1586.  001d  ba 00 00          L101            mov     dx,offset _acHeap
  1587.  
  1588.  0020  bb de ad                          mov     bx,0addeH
  1589.  0023  b9 77 34                          mov     cx,3477H
  1590.  
  1591.  pmbFree->ulSignature = SIGNATURE;
  1592.  0026  2d 08 00                          sub     ax,0008H
  1593.  
  1594.  pmbFree->pmbNext = 0;
  1595.  0029  31 f6                             xor     si,si
  1596.  002b  89 16 00 00                       mov     _pmbFree,dx
  1597.  002f  a3 04 00                          mov     _acHeap+4H,ax
  1598.  0032  89 1e 00 00                       mov     _acHeap,bx
  1599.  0036  89 0e 02 00                       mov     _acHeap+2H,cx
  1600.  003a  89 36 06 00                       mov     _acHeap+6H,si
  1601.  
  1602.  uMemFree = pmbFree->uSize;
  1603.  
  1604.  return pmbFree->uSize;
  1605.  003e  a3 00 00                          mov     _uMemFree,ax
  1606.  
  1607. }
  1608.  
  1609.  
  1610.  0041  5e                                pop     si
  1611.  0042  5a                                pop     dx
  1612.  0043  59                                pop     cx
  1613.  0044  5b                                pop     bx
  1614.  0045  c3                                ret     
  1615.  
  1616. No disassembly errors
  1617.  
  1618. List of external symbols
  1619.  
  1620. Symbol
  1621. ----------------
  1622. _endHeap         00000005
  1623. _endData         00000009
  1624. _acHeap          0000003c 00000038 00000034 00000030 0000001e
  1625. _pmbFree         0000002d
  1626. _uMemFree        0000003f
  1627. ------------------------------------------------------------
  1628. List of public symbols
  1629.  
  1630. SYMBOL          GROUP           SEGMENT          ADDRESS
  1631. ---------------------------------------------------------
  1632. _acHeap         DGROUP          _BSS             00000000
  1633. _cAlloc         DGROUP          _DATA            00000006
  1634. _cFree          DGROUP          _DATA            0000000c
  1635. _cTotalHeap     DGROUP          _DATA            00000012
  1636. _fMemoryDoc     DGROUP          _DATA            00000002
  1637. _memfree_                       _TEXT            0000056c
  1638. _msize_                         _TEXT            00000250
  1639. _nAlloc         DGROUP          _DATA            00000004
  1640. _nAllocCalls    DGROUP          _DATA            00000008
  1641. _nCompact       DGROUP          _DATA            00000010
  1642. _nFree          DGROUP          _DATA            0000000a
  1643. _nFreeCalls     DGROUP          _DATA            0000000e
  1644. _pmbFree        DGROUP          _BSS             00002002
  1645. _pmbUsed        DGROUP          _DATA            00000000
  1646. _uMemFree       DGROUP          _BSS             00002000
  1647. compact_                        _TEXT            00000388
  1648. dumpheap_                       _TEXT            00000000
  1649. free_                           _TEXT            000004b4
  1650. HeapCheck_                      _TEXT            00000158
  1651. HeapInit_                       _INITTEXT        00000000
  1652. make_new_free_                  _TEXT            00000208
  1653. malloc_                         _TEXT            000002b8
  1654. npvAllocateBlock_ 
  1655.                                 _TEXT            00000260
  1656. realloc_                        _TEXT            00000570
  1657. remove_                         _TEXT            0000034c
  1658. SignatureCheck_                 _TEXT            00000104
  1659.  
  1660. ------------------------------------------------------------
  1661.  
  1662.