我正在尝试将Delphi 5代码迁移到Delphi XE7-WIN64,我在下面的块中面临混合汇编代码的问题.我也是新手. procedure IterateMenus(Func: Pointer; Menu1, Menu2: TElMenuItem);var I, J: Integer; IIndex, JIndex: Byte; Menu
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;
我试图将asm块转换为purepascal,因为delphi x64不允许混合代码,asm不是程序员友好的.
到目前为止,我理解Item的地址被移到了EAX,
然后我什么也没得到. EBP来自哪里?什么是ESP和AL?
上面的代码片段来自ELPack的ELmenus.pas.
基本上什么是asm代码块的PurePascal版本?
对于func我找到了这个
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;
我猜测原始程序员编写的奇怪代码绕过Delphi不支持本地函数指针. (这是一个让我偶尔烦恼的限制.)
以下应该有效. (虽然我的确不是那么敏锐.我会首先通过D5中的调试器来测试asm代码,以确认行CALL DWORD PTR AFunc正在传递我期望的值.)
1)Delcare一个函数指针类型并移动UpdateItem,使其不再是本地的.
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)进行以下更改:
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)最后汇编程序块变为:
Result := AFunc(Item);
