;──────────────────────────────────────────────────────────────────────────────
; Reallocate Mem Block
;──────────────────────────────────────────────────────────────────────────────
;
; Borland C++ 4.0 for WIN32 prototype:
; PTR __pascal realloc (PTR ptr, DWORD size);
;
; version 0.2
; - White Shadow -
;
.386p
Ideal
Segment _DATA dword public use32 'DATA'
EndS _DATA
Segment _BSS dword public use32 'BSS'
EndS _BSS
Group DGROUP _DATA, _BSS
Struc MEMBLOCK
base dd ?
size dd ?
handle dd ?
EndS
extrn _lowheapblock:MEMBLOCK, _extheapblock:MEMBLOCK
extrn _database:dword
extrn MBMALLOC:near, MBREALLOC:near, MBGETSIZE:near
extrn MALLOC:near, FREE:near
Public REALLOC
;──────────────────────────────────────────────────────────────────────────────
Segment _TEXT byte public use32 'CODE'
Assume cs:_TEXT, ds:DGROUP
; -- argument stack offsets
arg1 = 4 ; -> MemArea
arg2 = 0 ; - requested size
REALLOC: push esi edi ebp
pct = (4)+(3*4) ; # bytes pushed on stack after last argument
;-- Just do MALLOC ?
mov eax, [esp+pct+arg1] ; -> MemArea
or eax, eax
jnz NotMalloc
;--------------- Do MALLOC
;PTR __pascal malloc (DWORD size);
mov eax, [esp+pct+arg2] ; requested size
push eax
call MALLOC
jmp Exit ; eax -> new MemArea (or null)
;---------------
NotMalloc: ;-- low MB first
mov esi, offset _lowheapblock
mov edi, offset _extheapblock
;-- Low or ext first?
mov ebx, [_extheapblock.base] ; linear -> to MB base
sub ebx, [_database] ; DGROUP -> to MB base
cmp eax, ebx
jb LowBlock
;-- ext MB first
xchg esi, edi
;---------------
LowBlock:
; eax -> MemArea to free
; esi -> first MEMBLOCK to try
; edi -> second MEMBLOCK to try
;-- Get size of MemArea; will indicate a bad pointer
; DWORD __pascal mbgetsize (MEMBLOCK *mb, PTR ptr);
push esi
push eax
call MBGETSIZE
;-- Error if MemNode size is null
or eax, eax
jz Exit ; exit null
mov ebp, eax ; store size for copy if needed
;-- Try to resize within primary MEMBLOCK
; PTR __pascal mbrealloc (MEMBLOCK *mb, PTR ptr, DWORD size);
mov eax, [esp+pct+arg1]
mov ecx, [esp+pct+arg2]
push esi ; -> MEMBLOCK
push eax ; -> MemArea
push ecx ; requested size
call MBREALLOC
;-- Was resize OK within primary MEMBLOCK ?
or eax, eax
jnz Exit ; return with MemArea pointer
;-- Were we trying to resize to 0 ?
cmp [dword esp+pct+arg2], 0
jz Exit ; exit null
;-- Try to MALLOC enough memory in the secondary MEMBLOCK
; PTR __pascal mbmalloc (MEMBLOCK *mb, DWORD size);
mov eax, [esp+pct+arg2]
push edi ; -> MEMBLOCK
push eax ; requested size
call MBMALLOC
;-- Did MALLOC also fail ?
or eax, eax
jz Exit ; exit null
;-- Copy across MEMBLOCKs
mov ecx, ebp ; size of org MemArea
and ebp, 03h
shr ecx, 2
mov esi, [esp+pct+arg1] ; -> old MemArea
mov edi, eax ; -> new MemArea
rep movsd
mov ecx, ebp
rep movsb
;-- Free old MemArea
; void __pascal free (PTR ptr);
mov ebp, eax ; store new MemArea ptr
mov eax, [esp+pct+arg1] ; -> old MemArea
push eax
call FREE
;-- Exit with -> new MemArea
mov eax, ebp
;---------------
Exit: pop ebp edi esi
ret 8 ; 2 args
;──────────────────────────────────────────────────────────────────────────────
EndS _TEXT
End