Metropoli BBS
VIEWER: bmmalloc.asm MODE: TEXT (CP437)
;──────────────────────────────────────────────────────────────────────────────
;                          MEMBLOCK Memory Allocation
;──────────────────────────────────────────────────────────────────────────────
;
; Borland C++ 4.0 for WIN32 prototype:
; PTR   __pascal mbmalloc (MEMBLOCK *mb, DWORD size);
;
; version 0.3
; - White Shadow -
;
.386p
Ideal
include "bmmalloc.inc"

Public MBMALLOC


;──────────────────────────────────────────────────────────────────────────────
Segment _TEXT byte public use32 'CODE'
Assume  cs:_TEXT, ds:DGROUP


; -- argument stack offsets
arg1 = 4                ; -> MEMBLOCK
arg2 = 0                ; requested size in bytes

MBMALLOC:       push ebx esi ebp
pct = (4)+(3*4)         ; # bytes pushed on stack after last argument

                ;-- load MEMBLOCK info
                mov  esi, [esp+pct+arg1]        ; -> MEMBLOCK
                mov  ebx, [esi+MEMBLOCK.base]   ; linear adx of MEMBLOCK
                sub  ebx, [_database]           ; relative ofs to DGROUP
                mov  ebp, [esi+MEMBLOCK.size]   ; size of memblock
                cmp  ebp, MBSigSize + size MemNode      ; room for ANY memory?
                jbe  ExitNull                   ; or uninitalized MB?
                add  ebp, ebx                   ; relative ofs + size

If DebugMode    ;-- check MBSig
                cmp  [dword ebx], MBSig         ; 4 byte signature
                jne  ExitNull                   ; is it there?
                add  ebx, MBSigSize             ; -> first node
EndIf

                ;-- align requested size
                mov  ecx, [esp+pct+arg2]        ; requested size
                add  ecx, 03h                   ; round up
                and  cl, NOT (03h)              ; dword alignment

                ;-- Illegal request size?
                or   ecx, ecx
                jz   ExitNull
                js   ExitNull
                ; 0 < requested size < 2^31

;---------------

CheckNextNode:
; ebx -> MemNode to check
; ecx - requested size
; ebp - MEMBLOCK relative offset + MEMBLOCK size
                ;-- get MemNode's memory area size
                mov  eax, [ebx+MemNode.size]

If DebugMode    ;-- check signature
                mov  edx, eax
                xor  edx, NodeSigKey
                cmp  [ebx+MemNode.sig], edx
                jne  CorruptMB              ; bad MemNode signature?
EndIf

                ;-- Is memory area free?
                test eax, 80000000h
                jnz  NotFree                ; skip fit check

                ;-- Does requested size fit into memory area?
                cmp  eax, ecx
                jae  Fit                    ; found first fit

NotFree:    ;-- point to next MemNode
                add  ebx, size MemNode
                and  eax, 7fffffffh
                add  ebx, eax

                ;-- Any more MemNodes?
                cmp  ebx, ebp
                jb   CheckNextNode          ; below MEMBLOCK end marker?
                ja   CorruptMB              ; error if above MEMBLOCK end
                jmp  ExitNull               ; must be equal, then no fit!

;---------------

Fit:
; eax - MemNode's memory area size
; ebx -> MemNode to infiltrate
; ecx - requested size
                ;-- store memory ptr
                mov  esi, ebx
                add  esi, size MemNode          ; DGROUP memory pointer to
                                                ;  allocated memory

                ;-- Enough room for another MemNode and memory area?
                mov  edx, eax
                sub  edx, ecx                   ; memory left over
                cmp  edx, size MemNode
                jbe  UseWholeNode

                ;-- modify first node
                mov  edx, ecx                   ; requested size
                or   edx, 80000000h             ; mark as used
                mov  [ebx+MemNode.size], edx
If DebugMode
                xor  edx, NodeSigKey
                mov  [ebx+MemNode.sig], edx     ; update MemNode signature
EndIf

                ;-- write second node data
                add  ebx, size MemNode
                add  ebx, ecx                   ; -> new MemNode
                sub  eax, ecx
                sub  eax, size MemNode          ; new MemNode's memory area size
                mov  [ebx+MemNode.size], eax    ; leave as free memory
If DebugMode
                xor  eax, NodeSigKey
                mov  [ebx+MemNode.sig], eax     ; write signature
EndIf

                ;-- done
                jmp  short Exit

;---------------

UseWholeNode:
; eax - MemNode's memory area size

                ;-- rape whole MemNode
                or   eax, 80000000h             ; mark as used
                mov  [ebx+MemNode.size], eax
If DebugMode
                xor  eax, NodeSigKey
                mov  [ebx+MemNode.sig], eax     ; update signature
EndIf

;---------------

Exit:
; esi -> memory area
                mov  eax, esi
                pop  ebp esi ebx
                ret  8                          ; 2 args

;---------------

ExitNull:       xor  esi, esi
                jmp  short Exit

;---------------

CorruptMB:
If DebugMode
                mov  ebx, [esp+pct+arg1]        ; -> MEMBLOCK
                mov  ebx, [ebx+MEMBLOCK.base]   ; linear adx of MEMBLOCK
                sub  ebx, [_database]           ; relative ofs to DGROUP
                mov  [dword ebx], MBSigInvl     ; not MBSig!
EndIf
                jmp  short ExitNull


;──────────────────────────────────────────────────────────────────────────────
EndS            _TEXT
End
[ RETURN TO DIRECTORY ]