我正在尝试将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);