Delphi asm到purepascal
我正在尝试将Delphi 5代码迁移到Delphi XE7-WIN64,在下面的代码块中,我遇到了一个混合汇编代码的问题。我也是个新手Delphi asm到purepascal,delphi,assembly,delphi-5,delphi-xe7,Delphi,Assembly,Delphi 5,Delphi Xe7,我正在尝试将Delphi 5代码迁移到Delphi XE7-WIN64,在下面的代码块中,我遇到了一个混合汇编代码的问题。我也是个新手 procedure IterateMenus(Func: Pointer; Menu1, Menu2: TElMenuItem); var I, J: Integer; IIndex, JIndex: Byte; Menu1Size, Menu2Size: Integer; Done: Boolean; function Iterate(v
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;
过程迭代(Func:Pointer;Menu1、Menu2:TElMenuItem);
变量
一、 J:整数;
IIndex,JIndex:字节;
Menu1Size,Menu2Size:整数;
完成:布尔;
函数迭代(变量I:Integer;MenuItem:TElMenuItem;AFunc:Pointer):布尔;
变量
项目:项目;
开始
如果MenuItem=nil,则退出;
结果:=假;
而不是结果和(IIIndex,则中断;
asm
MOV EAX,项目
移动EDX,[EBP+8]
推送DWORD PTR[EDX]
呼叫DWORD PTR AFunc
添加ESP,4
MOV结果,AL
结束;
公司(一);
结束;
结束;
开始
I:=0;
J:=0;
菜单1大小:=0;
Menu2Size:=0;
如果Menu1为零,则
Menu1Size:=Menu1.Count;
如果Menu2为零,则
Menu2Size:=Menu2.Count;
完成:=错误;
未完成和((I 如果IIndex,则asm代码正在调用项上的方法。我得说,不管是谁写的代码都需要检查他们的脑袋。就好像他们不知道方法指针一样
解决这个问题的方法是查找调用函数的代码,并查看作为Func
参数传递的内容。这就是asm
块调用的内容。将Func
参数的类型更改为适当的过程类型,并用对该方法指针的调用替换asm
块
好的,现在我看到原始代码在本地过程中快速而松散地运行。您应该做的是将Func
设置为匿名方法类型:
Func: TFunc<TElMenuItem, Boolean>;
Func:TFunc;
然后将本地函数转换为匿名方法
升级Delphi版本的常用方法是同时升级第三方库。如果你这样做的话,我想你就不需要移植15年前的库代码了 我猜最初的程序员编写了奇怪的代码,以绕过不支持本地函数指针的Delphi。(这是一个有时让我恼火的限制。)
以下几点应该行得通。(当然,我对asm的要求不是很严格。我会首先通过D5中的调试器测试asm代码,以确认CALL DWORD PTR AFunc
行正在传递我期望的值。)
1) 删除函数指针类型并移动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);
你能显示“Func”的函数签名吗。也就是说,函数Func期望哪些参数作为参数传递给IterateMenus?在原始代码中查找-IterateMenus调用中使用了哪些Func?了解它的原型是有用的。[EBP+8]看起来像I变量,AL是func返回值(布尔值)的低字节。@VilleKrumlinde用“func”更新了问题。我猜最初的程序员编写了奇怪的代码来绕过Delphi,不支持本地函数指针。(这是一个有时会让我恼火的限制。)“我猜最初的程序员编写奇怪的代码是为了绕过Delphi,不支持本地函数指针。”——请在此记录;启动并发布该模式的“原始程序员”正是andershejlsberg,他是turbopascal编译器的开发人员和Delphi的首席架构师(现在是MS的杰出工程师)。是的,它解决了无法引用嵌套过程的问题。这项技术是在Turbo Vision的Turbo Pascal 6.0中引入的。在许多方面,这是真正的“闭包”的第一个化身。Turbo Pascal的对象单元的TCollection.foreach迭代器机制基于类似的构造。诀窍可能来自那里。FPC btw支持适当的本地功能类型。(“本地”程序指令)真的吗?为什么呢它解决了一个非常现实的问题,即能够迭代一系列项并执行操作,而不必设置一些全局状态或在不透明的“上下文”中传递。是的,今天显然有更好的解决方案,但当时它非常有用。仅从目前的技术水平来评论一个解决方案是不真诚的,也是傲慢的缩影。电灯在当时是一个相当大的创新,但是按照你的逻辑,它是昏暗和耗电的,这是贫穷和不必要的(夸张的目的是为了说明)。@David,如果工具当时处于今天的状态,我会很清楚地同意你的评估,并会质疑该代码作者的理智。与许多事情一样,忽视或忽视历史可能会在不经意间让人对许多有效的解决方案甚至是构建下一个伟大解决方案的平台产生怀疑。我们今天并不比过去的开发人员更聪明(在能力倾向的意义上);我们只是有事后诸葛亮的优势。“如果我看得更远,那是因为我站在巨人的肩膀上”——艾萨克·牛顿。
Result := AFunc(Item);