Metropoli BBS
VIEWER: bmwalk.asm MODE: TEXT (CP437)
;──────────────────────────────────────────────────────────────────────────────
;                                MEMBLOCK Walk
;──────────────────────────────────────────────────────────────────────────────
;
; Borland C++ 4.0 for WIN32 prototype:
; void  __pascal mbwalk (MEMBLOCK *mb, WalkMBInf *inf);
;
; version 0.3
; - White Shadow -
;
.386p
Ideal
include "bmmalloc.inc"

Public MBWALK


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


; -- argument stack offsets
arg1 = 4                ; -> MEMBLOCK
arg2 = 0                ; -> WalkMBInf

INFFLAG_ResetWalk       = 01h
INFFLAG_AllocArea       = 02h
INFFLAG_LastNode        = 04h
INFFLAG_CorruptMB       = 08h
INFFLAG_UninitMB        = 10h

MBWALK:         push ebx esi ebp
pct = (4)+(3*4)

                ;-- 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]
                add  ebp, ebx                   ; -> last byte of MB + 1

                ;-- MEMBLOCK uninitalized?
                cmp  ebp, ebx
                je   UninitMB

If DebugMode    ;-- Check MEMBLOCK signature
                cmp  [dword ebx], MBSig
                jne  CorruptMB
                add  ebx, MBSigSize             ; -> first node
EndIf

                ;-- Continue?
                mov  esi, [esp+pct+arg2]        ; -> WalkMBInf
                test [esi+WalkMBInf.flags], INFFLAG_ResetWalk
                jz   ContinuedWalk

                ;-- Reset to begining of MEMBLOCK
                mov  [esi+WalkMBInf.flags], 0   ; kill all flags

                jmp  GetNodeInf

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

ContinuedWalk:
                ;-- Already at last node, or corrupted MB?
                test [esi+WalkMBInf.flags], INFFLAG_LastNode OR INFFLAG_CorruptMB
                jnz  Exit

                ;-- Get last MemNode adx
                mov  ebx, [esi+WalkMBInf.adx]
                sub  ebx, size MemNode

                ;-- Check last node
                mov  eax, [ebx+MemNode.size]
If DebugMode
                xor  eax, NodeSigKey
                cmp  [ebx+MemNode.sig], eax
                jne  CorruptMB
                xor  eax, NodeSigKey
EndIf

                ;-- point to Ret node
                and  eax, 7fffffffh
                add  ebx, size MemNode
                add  ebx, eax
                cmp  ebx, ebp                   ; past end?
                jae  CorruptMB

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

GetNodeInf:
; ebx -> MemNode to return
; esi -> WalkMBInf

If DebugMode    ;-- Ret node valid?
                mov  eax, [ebx+MemNode.size]
                xor  eax, NodeSigKey
                cmp  [ebx+MemNode.sig], eax
                jne  CorruptMB
EndIf

                ;-- MemArea adx
                mov  eax, ebx
                add  eax, size MemNode
                mov  [esi+WalkMBInf.adx], eax

                ;-- Free area?
                and  [esi+WalkMBInf.flags], NOT (INFFLAG_AllocArea)
                test [ebx+MemNode.size], 80000000h
                jz   FreeArea
                or   [esi+WalkMBInf.flags], INFFLAG_AllocArea
FreeArea:

                ;-- Area size
                mov  eax, [ebx+MemNode.size]
                and  eax, 7fffffffh
                mov  [esi+WalkMBInf.size], eax

                ;-- Point to next node
                add  ebx, size MemNode
                add  ebx, eax

                ;-- Is MemNode to ret the last node?
                cmp  ebx, ebp
                ja   CorruptMB                  ; no, error
                jb   Exit                       ; no, more nodes

                ;-- Set last node flag
                or   [esi+WalkMBInf.flags], INFFLAG_LastNode

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

Exit:           pop  ebp esi ebx
                ret  8                          ; 2 args

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

CorruptMB:      mov  ebx, [esp+pct+arg2]        ; -> WalkMBInf
                or   [ebx+WalkMBInf.flags], INFFLAG_CorruptMB
                jmp  Exit

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

UninitMB:       mov  ebx, [esp+pct+arg2]        ; -> WalkMBInf
                or   [ebx+WalkMBInf.flags], INFFLAG_UninitMB
                jmp  Exit


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