Here is a 32 bit version of ASSERT.

unit Asserts;
{
OVERVIEW
Because C/C++ allows #defines, it is much easier to implement a non intrusive assert() here, we can copy the assert code, but the procedure call still happens.  So, we should at the outer level also ifdef out the actual call to assert.  This can be accomplished by coding the call to
assert just like normal.  Then search for asserts() after you finish with  regular expressions and place the conditionals #ifdefs at the beginning and  end.  You must create a (DEFINE of _NDEBUG) to avoid calling the debug  procedures, or create the define in the projects option of delphi.  The  address passed back by the assert module tells you the "find|error" address
to use via the logical segment numbering scheme implemented by Borland's  RunError procedure.

NOTES

We use the conditional define _NDEBUG instead of just the ifopt option for the cases where you don't want debug info, but you want the asserts to stay intact.  If you wish, you can put the following in your code to automatically change based on debug info.

I've included the export of the convert addr function from the SysUtils unit, but it is not needed to find the address because return address will return a "Search...FindError..." compatible address.  I'm not really sure why  borland created the ConvertAddr function, it's still a mystery to me.

(* ifopt D- *)
   (* define _NDEBUG*)
(* endif *)

interface

procedure Assert(assertedCond : boolean; const msgStr : string);
function ConvertAddr(Address: Pointer): Pointer; assembler;
 

implementation
uses WinProcs, SysUtils, WinTypes;

// (Done) Directly stolen(panged) from sysutils unit for use in the
// assert module.
{$STACKFRAMES ON }
function ConvertAddr(Address: Pointer): Pointer; assembler;
asm
        TEST    EAX,EAX         { Always convert nil to nil }
        JE      @@1
        SUB     EAX,OFFSET TextStart
@@1:
end;
 

// (Done) Error when the assumption made is not correct.
procedure Assert(assertedCond : boolean; const msgStr : string);
{$ifndef _NDEBUG}
var
   msgOut : array[0..100] of char;
   hexStr : array[0..30] of char;
   progOfs : cardinal;
   tmpStr : string;
{$endif}

begin
   {$ifndef _NDEBUG} // Are we allowed to assert?
      if (not assertedCond) then begin
         // Get the logical segment used by the Find|Error menu option of delphi
         // Delphi32 is sooo much nicer, it gives us these handy functions examples in
         // ConvertAddr and ReturnAddr
         asm
            // Find the return address and back up four past the return address
            // so we get the right area for the call from the Assert.  Otherwise
            // we get one line past the assert.
            MOV      EAX,[EBP + 4];
            SUB      EAX, 4
            MOV      progOfs, EAX
         end;
 
         // construct msg\nat location ssss:oooo using the logical address
         StrPCopy(msgOut, msgStr);
         tmpStr := chr(10) + 'at location ' +
                   IntToHex(progOfs,SizeOf(progOfs) * 2);
         StrPCopy(hexStr, tmpStr);
         StrCat(msgOut, hexStr);
         MessageBox(0, msgOut, 'Assert Failed', MB_ICONSTOP+MB_SYSTEMMODAL+MB_OK);
 
         // Now, terminate the program because of assertion problem
         halt;
      end;
   {$endif}
end;

end.