Metropoli BBS
VIEWER: realloc.asm MODE: TEXT (CP437)
;──────────────────────────────────────────────────────────────────────────────
;                             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
[ RETURN TO DIRECTORY ]