;──────────────────────────────────────────────────────────────────────────────
; 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