I am trying to migrate Delphi 5 code to Delphi XE7-WIN64 and I am facing a problem with mixed assembly code in the following block. Also I am asm newbie.
procedure IterateMenus(Func: Pointer; Menu1, Menu2: TElMenuItem);
var
I, J: Integer;
IIndex, JIndex: Byte;
Menu1Size, Menu2Size: Integer;
Done: Boolean;
function Iterate(var I: Integer; MenuItem: TElMenuItem; AFunc: Pointer): Boolean;
var
Item: TMenuItem;
begin
if MenuItem = nil then Exit;
Result := False;
while not Result and (I < MenuItem.Count) do
begin
Item := MenuItem[I];
if Item.GroupIndex > IIndex then Break;
asm
MOV EAX,Item
MOV EDX,[EBP+8]
PUSH DWORD PTR [EDX]
CALL DWORD PTR AFunc
ADD ESP,4
MOV Result,AL
end;
Inc(I);
end;
end;
begin
I := 0;
J := 0;
Menu1Size := 0;
Menu2Size := 0;
if Menu1 <> nil then
Menu1Size := Menu1.Count;
if Menu2 <> nil then
Menu2Size := Menu2.Count;
Done := False;
while not Done and ((I < Menu1Size) or (J < Menu2Size)) do
begin
IIndex := High(Byte);
JIndex := High(Byte);
if (I < Menu1Size) then
IIndex := Menu1[I].GroupIndex;
if (J < Menu2Size) then
JIndex := Menu2[J].GroupIndex;
if IIndex <= JIndex then
Done := Iterate(I, Menu1, Func)
else
begin
IIndex := JIndex;
Done := Iterate(J, Menu2, Func);
end;
while (I < Menu1Size) and (Menu1[I].GroupIndex <= IIndex) do
Inc(I);
while (J < Menu2Size) and (Menu2[J].GroupIndex <= IIndex) do
Inc(J);
end;
end;
I am trying to convert the asm block to purepascal since delphi x64 doesn't allow mixed code and asm is not programmer-friendly.
As far I understand address of Item is moved to EAX, Then I am not getting anything. Where did EBP come from? What is ESP and AL? The above code snippet is from ELmenus.pas from ELPack.
So basically what will be the PurePascal version of the asm codeblock?
For func I found this
procedure TElMenuItem.UpdateItems;
function UpdateItem(MenuItem: TElMenuItem): Boolean;
begin
Result := False;
IterateMenus(@UpdateItem, MenuItem.FMerged, MenuItem);
MenuItem.SubItemChanged(MenuItem, MenuItem, True);
end;
begin
IterateMenus(@UpdateItem, FMerged, Self);
end;
procedure TElMenuItem.PopulateMenu;
var
MenuRightToLeft: Boolean;
function AddIn(MenuItem: TElMenuItem): Boolean;
begin
MenuItem.AppendTo(FHandle, MenuRightToLeft);
Result := False;
end;
begin // all menu items use BiDiMode of their root menu
{$ifdef VCL_4_USED}
MenuRightToLeft := (FMenu <> nil) and FMenu.IsRightToLeft;
{$else}
MenuRightToLeft := false;
{$endif}
IterateMenus(@AddIn, FMerged, Self);
end;
That asm code is calling a method on
Item
. I'd say that whoever wrote the code needs their head examined. It's as if they don't know about method pointers.The way I would tackle this is to look for the code that calls the function and see what is passed as the
Func
argument. That's what is being called by theasm
block. Change the type of theFunc
argument to an appropriate procedural type and replace theasm
block with a call to that method pointer.OK, now I see that the original code is playing fast and loose with local procedures. What you should do is make
Func
be an anonymous method type:Then convert the local functions to be anonymous methods.
The usual approach to upgrading Delphi versions is to upgrade the third party libraries at the same time. Were you to do this then I guess you would not need to port the 15 year old library code.