在将旧的Turbo Pascal单元转换为现代对象Pascal时,我遇到了以下问题:
function Less (var a, b; Relation : POINTER) : boolean;
inline($5B/$59/$0E/$E8/$00/$00/$58/$05/$08/$00/$50/$51/$53/$CB);代码应该调用external function {$F+} function VariableLess(var a, b : Index) : boolean; {$F-},收集结果并将其传递给调用函数。函数在为非类型化数据提供二叉树的单元中使用
procedure InsVarBBTree(var B: BBTree; var E; S: word; A: pointer; var ok: boolean);
{ puts variable E of size S into tree B. The order relation address is A. }因此,单元本身不能提供比较功能,即定义有效载荷的单元的工作。
使用online disassembler,我发现这对应于:
{$ASMMODE intel}
function Less (var a, b; Relation : POINTER) : boolean; assembler;
asm
pop bx
pop cx
push cs
call 6
pop ax
add ax, 8
push ax
push cx
push bx
retf
end;但是,编译器不喜欢push语句。我应该怎么做才能让它在现代的64位机器上工作呢?我意识到代码是16位的。
发布于 2021-01-25 05:36:19
我刚刚在MS-DOS的Turbo Pascal5上编译了一些inline函数来检查Turbo Pascal是如何生成代码的:
对于非inline函数调用,Turbo Pascal将所有函数参数推送到堆栈。首先推送第一个参数(因此SS:SP指向的最后一个函数参数)。然后执行(far) call。该函数使用retf n返回,这意味着被调用的函数将从堆栈中删除所有参数。
在inline函数中,简单地给出的原始字节替换 call指令。这意味着SS:SP指向参数,而不是返回地址。内联机器语言代码必须pop来自堆栈的参数。并且它不能使用ret返回,而只是在inline代码之后的指令处继续代码执行。
有了这些知识,就可以分析汇编代码:
使用给定的汇编代码,您可以通过编写一个辅助函数(在您的示例中为:VariableLess)来间接调用带有任何参数的任何 function或procedure (在您的示例中为:Less),该函数具有与要调用的函数相同的参数,外加一个指向实际函数的附加参数。
该代码等同于以下Delphi或FreePascal代码:
type
TMyCompare = function(var a, b) : boolean;
function Less (var a, b; Relation : TMyCompare) : boolean;
begin
Less := Relation(a, b);
end;如果你的编译器支持函数指针(type TMyCompare = function ...),你可以这样做。
或者,您甚至可以将程序中出现的所有Less(x,y,z)替换为z(x,y)。这将会更有效率。
当然,指向函数(VariableLess)的指针不应该是pointer类型,而应该是TMyCompare类型。
如果你的编译器不支持函数指针( Turbo Pascal显然不支持),你可能需要汇编。
但在这种情况下,不同的编译器需要不同的汇编代码!
因此,如果不了解编译器的内部结构,就不可能翻译汇编代码。
编辑
我不确定你的编译器到底是如何工作的。但是,如果我的原始代码不起作用,下面的代码可能会起作用:
function Less (var a, b; Relation : Pointer) : boolean;
type
TMyCompare = function(var a, b) : boolean;
var
Relation2 : TMyCompare;
begin
Relation2 := TMyCompare(Relation);
Less := Relation2(a, b);
end;发布于 2021-01-27 23:58:13
解决方案如下:在处理动态类型的单元内部定义
type
TMyCompare = function(var a, b) : boolean;
function Less (var a, b; Relation : TMyCompare) : boolean;
begin
Result := Relation(a, b);
end;
procedure InsVarBBTree(var B: BBTree; var E; S: word; A: TMyCompare;
var ok: boolean);
{ puts variable E of size S into tree B. The order relation address is A. }这是从外部调用
{$F+} function VariableLess(var a, b : Index) : boolean; {$F-}
begin
...
end;
InsVarBBTree(Baum, TempStr, SizeOf(TempStr), TMyCompare(@VariableLess), OK)感谢所有帮助这件事的人
恩格尔伯特
https://stackoverflow.com/questions/65871027
复制相似问题