BUG - Asm in constructors / destructors
Hello all,
I have discovered this example of a bug with ASM code
generation: basically, Delphi 2.0 doesn't always know
when (e.g.) the EDX register is being silently trashed.
This matters in constructors and destructors, since DL
is used to pass a silent parameter which is needed by
both the entry and exit code.
------------------------------------------------------
program TestAsm;
{
** WARNING ** Buggy Code!!! Do Not Run!!!
{$DEFINE Bug}
uses
SysUtils;
type
TBadAsm = class
private
FField: Comp;
public
constructor Create(const Number: Integer);
destructor Destroy; override;
end;
TCompRec = packed record
Lo, Hi: Integer
end;
constructor TBadAsm.Create(const Number: Integer);
begin
asm
MOV EAX, 50
{
The MUL ECX instruction places the product in EDX:EAX. However, the
values
in both EAX and EDX are needed by Delphi. Delphi is smart enough to
know
to preserve EAX, but it forgets to save EDX as well **unless explicitly
reminded that EDX is destroyed** (using INC EDX) ...
}
{$IFNDEF Bug}
INC EDX
{$ENDIF}
MUL ECX
MOV ECX, Self
MOV TCompRec[ECX+OFFSET TBadAsm.FField].Lo, EAX
MOV TCompRec[ECX+OFFSET TBadAsm.FField].Hi, EDX
end
end;
destructor TBadAsm.Destroy;
begin
asm
MOV ECX, EAX
{
Destructors have identical problems to constructors: their entry and exit
code depend on the values in EAX and DL, and Delphi forgets to preserve
these values under certain conditions ...
Trying to use the `assembler' directive with destructors also fails-
Internal Error C3254 ...
{$IFNDEF Bug}
INC EDX
{$ENDIF}
MUL TCompRec[ECX+OFFSET TBadAsm.FField].Lo
end
end;
var
BadAsm: TBadAsm;
begin
BadAsm := TBadAsm.Create(100);
BadAsm.Free
end.