< p>
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 (Ibegin
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 ((Ibegin
IIndex := High(Byte);< br /> JIndex := High(Byte);
if (IIIndex := Menu1[I].GroupIndex;
if (JJIndex := Menu2[J].GroupIndex;
if IIndex <= JIndex then
Done := Iterate(I, Menu1, Func)
else
begin
IIndex := JIndex;
Done := Iterate(J, Menu2, Func);
end;
while (IInc(I);
while (JInc(J);
end;
end;
I am trying to convert the asm block to purepascal, because delphi x64 does not allow mixed code, asm is not programmer-friendly.
So far, I understand the address of the Item I was moved to EAX,
and I got nothing. Where did EBP come from? What are ESP and AL?
The above code snippet comes from ELmenus.pas of ELPack.
Basically what is the PurePascal version of the asm code block?
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;< /pre>
The following should work. (Although I am not that sharp. I will first test the asm code through the debugger in D5 to confirm that the line CALL DWORD PTR AFunc is passing the value I expect.)
1) Delcare a function pointer type and move UpdateItem to make it No longer local.
type
TMenuOperation = function (AMenuItem: TElMenuItem): Boolean;
//Or if you want to move the UpdateItem to a method of a class..
//TMenuOperation = function (AMenuItem: TElMenuItem): Boolean of object;
2) Make the following changes:
procedure IterateMenus(Func: Pointer; Menu1, Menu2: TElMenuItem);
//becomes
procedure IterateMenus(Func: TMenuOperation; Menu1, Menu2: TElMenuItem);
//...
function Iterate(var I: Integer; MenuItem: TElMenuItem; AFunc: Pointer): Boolean;
var
Item: TMenuItem;
//becomes
function Iterate(var I: Integer; MenuItem: TElMenuItem; AFunc: TMenuOperation): Boolean;
var
Item: TElMenuItem;
//. ..
Item := MenuItem[I];
//becomes
Item := MenuItem[I] as TElMenuItem;
3) Finally the assembler block becomes:
Result := AFunc(Item);
I am trying to migrate Delphi 5 code to Delphi XE7-WIN64, and I am facing the problem of mixed assembly code in the block below. I am also a novice .
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 (Ibegin
Item := MenuItem[I];
if Item.GroupIndex> IIndex then Break;
asm
MOV EAX,Item< br /> 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 ((Ibegin
IIndex := High (Byte);
JIndex := High(Byte);
if (IIIndex := Menu1[I].GroupIndex;
if (JJIndex := Menu2[J].GroupIndex;
if IIndex <= JIndex then
Done := Iterate(I, Menu1, Func)
else
begin
IIndex := JIndex;
Done := Iterate(J, Menu2, Func);
end;
while (IInc(I);
while (JInc(J);
end;
end;
I tried to convert the asm block to purepascal, because Because delphi x64 does not allow mixed code, asm is not programmer-friendly.
So far, I understand that the address of Item is moved to EAX,
and then I get nothing. Where does EBP come from? What are ESP and AL?
The above code snippet comes from ELmenus.pas of ELPack.
Basically what is the PurePascal version of the asm code block?
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;< /pre>I guess the strange code written by the original programmer bypasses Delphi's lack of support for local function pointers. (This is a limitation that occasionally annoys me.)
< /p>
The following should work. (Although I am really not that sharp. I will first test the asm code through the debugger in D5 to confirm that the line CALL DWORD PTR AFunc is passing the value I expect.)
1) Delcare a function pointer type and move UpdateItem so that it is no longer local.
type
TMenuOperation = function (AMenuItem: TElMenuItem) : Boolean;
//Or if you want to move the UpdateItem to a method of a class..
//TMenuOperation = function (AMenuItem: TElMenuItem): Boolean of object;2) Make the following changes:
procedure IterateMenus(Func: Pointer; Menu1, Menu2: TElMenuItem);
//becomes
procedure IterateMenus(Func : TMenuOperation; Menu1, Menu2: TElMenuItem);
//...
function Iterate(var I: Integer; MenuItem: TElMenuItem; AFunc: Pointer): Boolean;
var
Item: TMenuItem;
//becomes
function Iterate(var I: Integer; MenuItem: TElMenuItem; AFunc: TMenuOperation): Boolean;
var
Item: TElMenuItem;
//...
Item := MenuItem[I];
//becomes
Item := MenuItem [I] as TElMenuItem;3) The final assembler block becomes:
Result := AFunc(Item);