[原码]用于汇编语言的小块内存管理器 By 狂编(于2011-1-6发表)

.386
.model flat, stdcall
option casemap :none

;本模块引出的4个函数
heap_init proto         ;heap_init是初始化函数,每个进程必须且只能运行一次
malloc proto dwSize:dword
free proto lpBlock:dword
realloc proto pBlock:dword,newsize:dword

HeapAlloc proto :dword,:dword,:dword
HeapFree proto :dword,:dword,:dword
HeapDestroy proto :dword
HeapReAlloc proto :dword,:dword,:dword,:dword
HeapCreate proto :dword,:dword,:dword
VirtualAlloc proto lpAddress:dword,dwSize:dword,flAllocationType:dword,flProtect:dword
VirtualFree proto pAddress:dword,dwSize:dword,dwFreeType:dword

MEM_COMMIT      equ     1000h   ;分配一块物理内存映射到指定的虚地址空间
MEM_RESERVE     equ     2000h   ;只占用了虚地址空间,并未实际分配物理内存
MEM_DECOMMIT    equ     4000h   ;释放指定地址的物理内存块,虚地址空间仍被占用
MEM_RELEASE     equ     8000h   ;释放指定的虚地址空间
PAGE_READWRITE  equ     4       ;内存页面可读可写

;内存按区、组、块三种尺寸进行管理,一个区分成32组,一个分成若干个块
;具体为每区:100000h(1MB) 分成32组,每组:8000h(32KB) 最大可用7EF0h

U64 struc
    l           dd      ?
    h           dd      ?
U64 ends

HEADER struc    ;sizeof=54h
   pNext                dd      ?       ;区头链,单向
   indGroupUse          dd      ?       ;正在使用的组序号
   bitvEntry            U64     <>      ;总位掩码,64位表示64种尺寸链表是否有效,1=存在,0=空链,小块尺寸在低位,等于各组的bitv的或
   bitvCommit           dd      ?       ;32位分别代表32组内存的映射情况,1表示未映射
   cntRegionSize        db      64 dup(?) ;空闲链表的条数计数器,每字节代表一种尺寸,最多为32条
HEADER ends

LISTHEAD struc
   pEntryNext           dw      ?
   pEntryPrev           dw      ?
LISTHEAD ends

GROUPHEAD struc ;sizeof=10Ch
   cntEntries   dd      ?               ;占用块计数器,每分配一次,计数加一,每释放一次,计数减一
   bitv         U64     <>              ;64位表示64种尺寸链表是否有效,1=存在,0=空链,尺寸较小的块的链表在低位
   listHead     LISTHEAD 64 dup(<>);链表头
GROUPHEAD ends

ENTRY struc
   sizeFront            dw      ?
   pEntryNext           dw      ?
   pEntryPrev           dw      ?
ENTRY ends

PG1 equ ((sizeof HEADER + 0Fh) and 0FFF0h)

;插入节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=新节点
INSERTNODE macro
        lea     edx,[edi].listHead.pEntryNext[-offset ENTRY.pEntryNext][ecx*4]
        mov     eax,edx                         ;edx定位在链表头
        mov     ax,[edx].ENTRY.pEntryNext       ;eax指向原第一个节点
        mov     [ebx].ENTRY.pEntryNext,ax       ;原节点当下级
        mov     [ebx].ENTRY.pEntryPrev,dx       ;链表头当上级
        mov     [edx].ENTRY.pEntryNext,bx       ;本块是链表头的下级
        mov     [eax].ENTRY.pEntryPrev,bx       ;本块是原节点的上级
        .if eax==edx                    ;若上下级相同,说明挂接前的原链表是空链,现在挂好了要在组区头设置标志位
                mov     eax,ecx
                and     cl,1Fh
                mov     edx,80000000h
                shr     edx,cl
                cmp     al,32
                sbb     cl,cl
                and     cl,4
                inc     [esi].cntRegionSize[eax];区里对应的链计数器加一
                or      [esi].bitvEntry.l[ecx],edx;这里是设置区里的标志位,不管计数器多少,设上去总没错
                or      [edi].bitv.l[ecx],edx   ;这里是设置组里的标志位
        .endif
endm

;删除节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=节点
DELETENODE macro
        mov     eax,ebx
        mov     edx,eax
        mov     dx,[ebx].ENTRY.pEntryPrev
        mov     ax,[ebx].ENTRY.pEntryNext
        mov     [edx].ENTRY.pEntryNext,ax       ;原下级当上级的下级
        mov     [eax].ENTRY.pEntryPrev,dx       ;原上级当下级的上级
        .if eax==edx                    ;如果块中链表的下级和上级相同,说明块对应空闲链表已经是最后一块了
                mov     eax,ecx                 ;这样我们就要把本组的链表标志清0
                and     cl,1Fh
                mov     edx,80000000h
                shr     edx,cl
                not     edx
                cmp     al,32
                sbb     cl,cl
                and     cl,4
                and     [edi].bitv.l[ecx],edx   ;这里是清除组里的标志位
                dec     [esi].cntRegionSize[eax];区里对应的链计数器减一
                .if zero?
                        and     [esi].bitvEntry.l[ecx],edx;这里是清除区里的标志位
                .endif
        .endif
endm

sbh_alloc_new_region proto
sbh_alloc_new_group proto :dword

.data?
_crtheap                dd      ?
sbh_pHeaderList         dd      ?
sbh_indGroupDefer       dd      ?
sbh_pHeaderDefer        dd      ?

.code
OPTION PROLOGUE:none
OPTION EPILOGUE:none
sbh_find_block proc private pvAlloc
                mov     eax, sbh_pHeaderList
                .repeat
                        mov     edx,[esp+4]     ;pvAlloc
                        sub     edx,eax
                        .break .if edx<100000h
                        mov     eax,[eax].HEADER.pNext
                .until !eax
                retn 4
sbh_find_block endp

;功能:释放一块内存
;一块内存要释放时要做的工作是,把这块内存挂接到本块尺寸对应的空闲链表上。
;但是我们还要考虑相邻的上一块和下一块是否也是空闲块,如果是的话,我们首先要
;把它们从空闲链表上取下来,再和本块结合做成一个较大的空闲块,之后再挂上去。
;最后要看看本组是不是全是空闲内存,如果全空则应把本组释放掉,还给操作系统。

sbh_free_block proc private pHeader,pvAlloc

pvA     equ     dword ptr [esp+8][12][0Ch]
pHdr    equ     dword ptr [esp+4][12][0Ch]


pEntry          equ     pvA
sizeEntry       equ     pHdr
sizePrev        equ     dword ptr [esp+8]
indEntry        equ     dword ptr [esp+4]
indPrev         equ     dword ptr [esp+0]

                push    edi
                push    esi
                push    ebx
                sub     esp,0Ch

                mov     esi, pHdr
                assume esi:ptr HEADER
                mov     ebx,pvA
                sub     ebx,2
                mov     pEntry,ebx
                mov     edi,ebx
                sub     edi,esi
                and     edi,0FFFF8000h
                .if zero?
                        add     edi,PG1
                .endif
                add     edi,esi
                assume edi:ptr GROUPHEAD
                movzx   ecx, [ebx].ENTRY.sizeFront
                and     cl,0FEh
                mov     sizeEntry, ecx
                add     ebx,ecx                         ;ebx指向下一块
                mov     cx,[ebx].ENTRY.sizeFront        ;ecx为下一块的尺寸
                .if !(cl & 1)                           ;检测一下,其标志位为0才是空闲块
                                                        ;至此,我们知道下一块是空闲,我们现在开始做合并工作
                        add     sizeEntry,ecx           ;尺寸合并在一起
                        shr     ecx,4                   ;把块从空闲链表上取下来。
                        dec     ecx
                        .if ecx>3Fh
                                mov     ecx,3Fh
                        .endif

                        DELETENODE;删除节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=节点

                .endif
                mov     eax, sizeEntry
                sar     eax, 4
                dec     eax
                .if eax>3Fh
                        mov     eax,3Fh
                .endif
                mov     indEntry, eax
                mov     ebx,pEntry
                movzx   ecx,word ptr [ebx-2]
                mov     sizePrev, ecx
                mov     edx,ecx
                shr     edx, 4
                dec     edx
                .if edx>3Fh
                        mov     edx,3Fh
                .endif
                mov     indPrev, edx
                .if !(cl & 1)                   ;上一块是空闲?
                        sub     ebx,ecx         ;pPrev
                        mov     pEntry,ebx
                        mov     eax,sizeEntry
                        add     eax,sizePrev
                        mov     sizeEntry, eax
                        shr     eax, 4
                        dec     eax
                        .if eax>3Fh
                                mov     eax,3Fh
                        .endif
                        mov     indEntry, eax
                        .if eax!=edx
                                mov     ecx,indPrev     ;把上一块从空闲链表上取下来。
                                DELETENODE;删除节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=节点
                        .endif
                .endif
                mov     eax,sizePrev
                mov     ecx,indEntry
                .if (al & 1)||(ecx!=indPrev)
                        INSERTNODE;插入节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=新节点
                .endif
                mov     ebx, pEntry
                mov     ecx, sizeEntry
                mov     [ebx],cx
                mov     [ebx][ecx][-2],cx
                dec     [edi].cntEntries
                .if zero?
                        mov     ebx,esi
                        mov     esi,sbh_pHeaderDefer
                        .if esi
                                mov     eax,sbh_indGroupDefer
                                .if eax
                                        shl     eax,0Fh
                                        add     eax,esi
                                        invoke  VirtualFree,eax,8000h,MEM_DECOMMIT
                                        mov     edx, 80000000h
                                        mov     ecx, sbh_indGroupDefer
                                        shr     edx, cl
                                        or      [esi].bitvCommit,edx
                                        dec     [esi].cntRegionSize[63]
                                        .if zero?
                                                and     byte ptr [esi].bitvEntry.l,0FEh
                                        .endif
                                .elseif [esi].bitvCommit == 7FFFFFFFh
                                        xor     ecx,ecx
                                        mov     eax,sbh_pHeaderList
                                        .while 1
                                                .break .if eax==esi
                                                mov     ecx,eax
                                                mov     eax,[eax].HEADER.pNext
                                        .endw
                                        mov     eax,[esi].pNext
                                        .if ecx || eax
                                                .if ecx
                                                        mov     [ecx].HEADER.pNext,eax
                                                .else
                                                        mov     sbh_pHeaderList,eax
                                                .endif
                                                invoke  VirtualFree,esi,0,MEM_RELEASE
                                                .if esi==ebx
                                                        xor     ebx,ebx
                                                .endif
                                        .endif
                                .endif
                        .endif
                        mov     sbh_pHeaderDefer,ebx
                        sub     edi,ebx
                        shr     edi,15
                        mov     sbh_indGroupDefer,edi
                .endif
                add     esp,0Ch
                pop     ebx
                pop     esi
                pop     edi
                retn 8
                assume esi:nothing , edi:nothing
sbh_free_block endp

sbh_alloc_block proc private dwSize

iSize           equ     dword ptr [esp+4][12][0Ch]      ;12是ebx,esi edi入栈占了,0Ch局部变量用
sizeEntry       equ     iSize                           ;重复使用,因为iSize只用一次

indEntry        equ     dword ptr [esp+8]
bitvEntryHi     equ     dword ptr [esp+4]
bitvEntryLo     equ     dword ptr [esp+0]
sizeNewFree     equ     bitvEntryHi             ;重复使用
indNewFree      equ     bitvEntryLo             ;重复使用

                push    edi
                push    esi
                push    ebx
                sub     esp,0Ch                 ;最原始的栈操作,为了节省push ebp 和 pop ebp两条指令

                mov     ecx,iSize
                add     ecx,4+0Fh               ;预留:块头尾尺寸 及 16字节对齐补数
                and     cl,0F0h
                mov     sizeEntry,ecx
                xor     eax,eax
                shr     ecx,4
                dec     eax
                dec     ecx                     ;ecx=对应链表的序号
                cdq
                mov     ebx,ecx
                and     cl,1Fh
                shr     edx,cl
                .if bl>=32
                        xchg    eax,edx ;位标志存放的位置和链表正好相反
                        inc     edx     ;低位存放大块的标志,高位放小块的
                .endif
                mov     bitvEntryLo,eax
                mov     bitvEntryHi,edx
                assume esi:ptr HEADER
                mov     esi, sbh_pHeaderList
                .repeat
                        mov     ecx,[esi].bitvEntry.h   ;ecx-edi取出链表全部标志
                        and     ecx,edx                 ;把不适合的尺寸的位屏蔽掉
                        mov     edi,[esi].bitvEntry.l
                        and     edi,eax
                        or      ecx,edi                 ;如果剩下的位非0,表示还有可用的链表
                        jnz     _ok                     ;有可用的块退出
                        mov     esi,[esi].pNext         ;否则继续扫描下一个区
                .until !esi
                mov     esi, sbh_pHeaderList
                .repeat                                 ;若没有适合的块,则检测各区是否还有未映射的组
                        cmp     [esi].bitvCommit,0
                        jnz     _ngrp
                        mov     esi,[esi].pNext
                .until !esi                             ;所有区的组已经全部映射定了,则再新开一个区
                invoke  sbh_alloc_new_region            ;开新区:返回区头地址,若失败返回0
                or      eax,eax
                jz      _res
                mov     esi,eax
                mov     eax,sbh_pHeaderList
                mov     [esi].pNext,eax
                mov     sbh_pHeaderList,esi
                jmp     _ok
        _ngrp:                                          ;找到未映射的组,则把该组映射了
                invoke  sbh_alloc_new_group,esi ;映射组:返回本次映射的组在扇区中的序号,若失败返回-1
                mov     [esi].indGroupUse,eax
                inc     eax
                jz      _res
        _ok:
                assume edi:ptr GROUPHEAD
                mov     edi,[esi].indGroupUse
                shl     edi,0Fh
                .if zero?
                        add     edi,PG1
                .endif
                add     edi,esi                         ;edi指向 indGroupUse 组头
                mov     eax,[edi].bitv.l
                and     eax,bitvEntryLo
                mov     edx,[edi].bitv.h
                and     edx,bitvEntryHi
                or      eax,edx                         ;优先检测 indGroupUse 组是否有适合块
                .if zero?
                        xor     ecx,ecx                 ;如果 indGroupUse 组没有适合块,则在本区内寻找,
                        .while 1
                                mov     edi,ecx         ;由于前面已经对本区检测,确定本区内有一个适合块
                                shl     edi,0Fh
                                .if zero?
                                        add     edi,PG1
                                .endif
                                add     edi,esi
                                mov     eax,[edi].bitv.l
                                and     eax,bitvEntryLo
                                mov     edx,[edi].bitv.h
                                and     edx,bitvEntryHi
                                or      eax,edx
                                .break .if !zero?
                                inc     ecx
                        .endw
                        mov     [esi].indGroupUse,ecx
                .endif
                                                        ;总结:运行到这里,适合块已经找到,如果没有找到,通过映射组或开新区也已经解决问题了
                                                        ;esi定位在区头,edi定位在组头,edx和eax是适合块的链表的位掩码
                xor     ecx,ecx                         ;现在根据位掩码计算出链表的序号
                .if !edx                                ;小尺寸的适合块优先使用
                        mov     cl,32
                        mov     edx,eax
                .endif
                .if !(edx & 0FFFF0000h)
                        shl     edx,16
                        add     cl,16
                .endif
                .while 1
                        shl     edx,1
                        .break .if carry?
                        inc     ecx
                .endw
                mov     indEntry, ecx                           ;ecx=链表序号
                mov     ebx,edi
                mov     bx,[edi].listHead.pEntryNext[ecx*4]     ;根据链表序号提取第一个空闲块指针
                movzx   ecx,[ebx].ENTRY.sizeFront
                sub     ecx,sizeEntry                           ;适合块的尺寸减去我们要的尺寸
                mov     sizeNewFree,ecx                         ;剩下的尺寸做成一个新的空闲块还是放在链上
                shr     ecx, 4
                dec     ecx
                .if ecx>63
                        mov     ecx,63
                .endif
                mov     indNewFree,ecx                          ;新旧块的序号如果相同,则链表可以不动
                .if ecx!=indEntry                               ;否则应该把旧的节点取消,挂接到新的链上
                        mov     ecx,indEntry
                        DELETENODE;删除节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=节点
                        .if sizeNewFree                         ;如果块还有剩余空间,则应该再挂上去
                                mov     ecx, indNewFree
                                INSERTNODE;插入节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=新节点
                        .endif
                .endif
                                ;标注头尾尺寸
                mov     ecx, sizeNewFree
                jecxz   @F              ;如果新块还有空间,则应该把这一块标注成空闲
                        mov     [ebx],cx
                        mov     [ebx+ecx-2],cx
                        add     ebx,ecx ;ebx指向我们要的这一块
                @@:
                mov     ecx,sizeEntry
                mov     eax,ecx
                or      al,1            ;加上占用块的标志位
                mov     [ebx],ax
                mov     [ebx+ecx-2],ax
                mov     ecx, [edi].cntEntries
                inc     [edi].cntEntries
                .if !ecx
                        .if esi==sbh_pHeaderDefer
                                mov     ecx,[esi].indGroupUse
                                .if ecx==sbh_indGroupDefer
                                        mov     sbh_pHeaderDefer, 0
                                .endif
                        .endif
                .endif
                lea     eax,[ebx+2]
                assume esi:nothing , edi:nothing

        _res:
                add     esp,0Ch
                pop     ebx
                pop     esi
                pop     edi
                retn 4
sbh_alloc_block endp


sbh_alloc_new_region proc private
                push    esi
                invoke  VirtualAlloc,0,100000h,MEM_RESERVE,PAGE_READWRITE
                .if eax
                        mov     esi,eax
                        assume esi:ptr HEADER
                        invoke  VirtualAlloc,eax,8000h,MEM_COMMIT,PAGE_READWRITE
                        .if eax
                                lea     edx,[esi+PG1 + offset GROUPHEAD.listHead.pEntryNext - offset ENTRY.pEntryNext]
                                mov     ecx,63
                                .repeat
                                        mov     [edx].ENTRY.pEntryNext,dx
                                        mov     [edx].ENTRY.pEntryPrev,dx
                                        add     edx,4
                                .untilcxz
                                mov     word ptr [esi+10Ch][PG1],0FFFFh
                                mov     word ptr [esi+7FFEh],0FFFFh
                                mov     word ptr [esi+10Eh][PG1],7EF0h-PG1
                                mov     word ptr [esi+7FFCh],7EF0h-PG1
                                lea     edx,[esi+PG1 + offset GROUPHEAD.listHead.pEntryNext - offset ENTRY.pEntryNext+(63*sizeof LISTHEAD)]
                                lea     ecx,[esi+10Eh][PG1]
                                mov     [edx].ENTRY.pEntryNext,cx
                                mov     [ecx].ENTRY.pEntryPrev,dx
                                mov     [edx].ENTRY.pEntryPrev,cx
                                mov     [ecx].ENTRY.pEntryNext,dx
                                mov     eax,1
                                cdq
                                mov     (GROUPHEAD ptr [esi]).bitv.l[PG1],eax
                                mov     (GROUPHEAD ptr [esi]).bitv.h[PG1],edx
                                mov     (GROUPHEAD ptr [esi]).cntEntries,edx
                                mov     [esi].bitvEntry.l,eax
                                mov     [esi].bitvEntry.h,edx
                                mov     [esi].indGroupUse,edx
                                mov     [esi].bitvCommit,7FFFFFFFh
                                mov     ecx,64/4
                                xor     eax,eax
                                lea     edx,[esi].cntRegionSize
                                .repeat
                                        mov     [edx],eax
                                        add     edx,4
                                .untilcxz
                                mov     [esi].cntRegionSize[63],1
                        .endif
                        assume esi:nothing
                .endif
                mov     eax,esi
                pop     esi
                retn
sbh_alloc_new_region endp

sbh_alloc_new_group proc private pHeader

pHdr            equ     [esp+4][8]
indCommit       equ     [esp+4][8]

                push    esi
                push    edi
                mov     esi, pHdr
                assume esi:ptr HEADER
                mov     eax,[esi].bitvCommit
                xor     edi,edi
                .while 1
                        shl     eax,1
                        .break .if carry?
                        inc     edi
                .endw
                mov     indCommit,edi
                shl     edi,0Fh
                add     edi,esi
                invoke  VirtualAlloc,edi,8000h,MEM_COMMIT,PAGE_READWRITE
                .if !eax
                        dec     eax
                        jmp     _res
                .endif
                mov     [edi].GROUPHEAD.cntEntries,0
                lea     edx,[edi].GROUPHEAD.listHead.pEntryNext[- offset ENTRY.pEntryNext]
                mov     ecx,63
                .repeat
                        mov     [edx].ENTRY.pEntryNext,dx
                        mov     [edx].ENTRY.pEntryPrev,dx
                        add     edx,4
                .untilcxz
                mov     word ptr [edi+10Ch],0FFFFh
                mov     word ptr [edi+7FFEh],0FFFFh
                mov     word ptr [edi+10Eh],7EF0h               ;7FFE-10E=7EF0
                mov     word ptr [edi+7FFCh],7EF0h              ;7FFE-10E=7EF0
                lea     edx,[edi].GROUPHEAD.listHead.pEntryNext[-2][63*sizeof LISTHEAD]
                lea     ecx,[edi+10Eh]
                mov     [edx].ENTRY.pEntryNext,cx
                mov     [ecx].ENTRY.pEntryPrev,dx
                mov     [edx].ENTRY.pEntryPrev,cx
                mov     [ecx].ENTRY.pEntryNext,dx
                mov     [edi].GROUPHEAD.bitv.l,1
                mov     [edi].GROUPHEAD.bitv.h,0
                inc     [esi].cntRegionSize[63]
                or      [esi].bitvEntry.l,1
                mov     ecx,indCommit
                mov     edx,80000000h
                mov     eax,ecx
                shr     edx,cl
                not     edx
                and     [esi].bitvCommit,edx
        _res:
                pop     edi
                pop     esi
                assume esi:nothing
                retn 4
sbh_alloc_new_group endp

sbh_resize_block proc private pHeader,pvAlloc,intNew

pHdr            equ [esp+4][12]
pvA             equ [esp+8][12]
iNew            equ [esp+12][12]

sizeEntry       equ [esp+4][12]
sizeNew         equ [esp+12][12]

                push    edi
                push    esi
                push    ebx

                assume esi:ptr HEADER
                mov     esi,pHdr
                mov     ebx,pvA
                mov     eax,iNew
                sub     ebx,2
                add     eax,4+0Fh               ;预留:块头尾尺寸 及 16字节对齐补数
                movzx   ecx,word ptr [ebx]
                and     al,0F0h                 ;对齐
                and     cl,0FEh                 ;清除占用标志
                cmp     eax,ecx                 ;块尺寸相同,无须修改,返回成功
                je      _res1
                mov     sizeNew,eax
                mov     sizeEntry,ecx
                mov     edi,ebx
                sub     edi,esi
                and     edi,0FFFF8000h
                .if zero?
                        add     edi,PG1
                .endif
                add     edi,esi                 ;edi指向组头
                assume edi:ptr GROUPHEAD
                .if eax>ecx                     ;如果块尺寸不是扩大,而是缩小,直接跳到块分割部份
                        add     ebx,ecx                 ;ebx指向下一块
                        movzx   edx,[ebx].ENTRY.sizeFront
                        test    dl,1                    ;如果要扩大,而下一块又被占用,则失败
                        jnz     _res0
                        add     ecx,edx
                        cmp     eax,ecx                 ;合并下一块后,空间仍然不足,失败
                        ja      _res0
                        mov     sizeEntry,ecx           ;修改sizeEntry,下面块分割时有用
                        mov     ecx,edx                 ;现在把下一块从链表上取下来
                        shr     ecx, 4
                        dec     ecx
                        .if ecx>63
                                mov     ecx,63
                        .endif

                        DELETENODE;删除节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=节点

                        mov     ebx,pvA
                        sub     ebx,2
                .endif
                        ;现在把sizeEntry一分为二,把剩下的部份要重新挂上去
                mov     edx,sizeNew
                mov     eax,edx                 ;把我们想要的这一块尺寸标一下
                or      al,1
                mov     [ebx].ENTRY.sizeFront,ax
                mov     [ebx][edx][-2],ax
                mov     ecx,sizeEntry
                sub     ecx,edx                         ;ecx=剩下的尺寸
                jz      _res1                           ;如果合并后的尺寸正好等于我们想要的尺寸,现在就可以返回成功
                add     ebx,edx                         ;ebx指向剩下的块
                mov     [ebx].ENTRY.sizeFront,cx        ;把剩下块的尺寸标一下
                mov     [ebx][ecx][-2],cx
                shr     ecx,4
                dec     ecx
                .if ecx>63
                        mov     ecx,63
                .endif

                INSERTNODE;插入节点:要求esi=区头,edi=组头,ecx=链表序号,ebx=新节点

        _res1:
                mov     eax, 1
                jmp     _res
        _res0:
                xor     eax,eax
        _res:
                pop     ebx
                pop     esi
                pop     edi
                retn 12
                assume esi:nothing, edi:nothing
sbh_resize_block endp

malloc proc dwSize
                mov     ecx,[esp+4];dwSize
                cmp     ecx,3FCh
                jbe     sbh_alloc_block ;直接使用跳转,节省了call指令,这种方法只适用于参数个数相等的函数
                add     ecx,0Fh
                and     cl, 0F0h
                invoke  HeapAlloc,_crtheap,0,ecx
                retn 4
malloc  endp

free proc lpBlock
pblk    equ     dword ptr [esp+4]
                mov     eax,pblk
                .if eax
                        invoke  sbh_find_block,eax
                        .if eax
                                invoke  sbh_free_block,eax,pblk
                        .else
                                invoke  HeapFree,_crtheap,0,pblk
                        .endif
                .endif
                retn 4
free endp

realloc proc  pBlock,newsize

newsiz  equ     dword ptr [esp+8]
pblk    equ     dword ptr [esp+4]
        .if !pblk
                invoke  malloc,newsiz
                jmp     _res
        .endif
        .if !newsiz
                invoke  free,pblk
                xor     eax,eax
                jmp     _res
        .endif
        xor     eax,eax
        cmp     newsiz,0FFFFFFE0h
        ja      _res
        invoke  sbh_find_block,pblk
        mov     ecx,newsiz
        .if !eax
                invoke  HeapReAlloc,_crtheap,0,pblk[4],ecx
                jmp     _res
        .endif
        .if ecx<=3FCh
                invoke  sbh_resize_block,eax,pblk[4],ecx
                .if eax
                        mov     eax,pblk
                        jmp     _res
                .endif
        .endif
        invoke  malloc,newsiz
        .if eax
                push    esi
                push    edi
                mov     edi,eax
                mov     esi,pblk[8]
                movzx   ecx,word ptr [esi-2]
                sub     ecx,4
                .if ecx>newsiz[8]
                        mov     ecx,newsiz[8]
                        add     ecx,3
                .endif
                shr     ecx,2
                rep     movsd
                pop     edi
                mov     esi,eax
                invoke  free,pblk[4]
                mov     eax,esi
                pop     esi
        .endif
_res:
        retn 8
realloc endp

heap_init proc
                invoke  HeapCreate,0,1000h,0
                mov     _crtheap, eax
                .if eax
                        invoke  sbh_alloc_new_region
                        mov     sbh_pHeaderList,eax
                        neg     eax
                        sbb     eax,eax
                        neg     eax
                        .if !eax
                                invoke  HeapDestroy,_crtheap
                                xor     eax, eax
                        .endif
                .endif
                ret
heap_init endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


                end

并不是所有的贴子都是原创,此时作者均指发表的人而不是文章的作者,作者会说明是否是转贴