在将旧的 Turbo Pascal 单位转换为现代 Object 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 位的。
最佳答案
我刚刚编译了一些 inline
用于 MS-DOS 的 Turbo Pascal 5 上的函数来检查 Turbo Pascal 如何生成代码:
对于非 inline
函数调用,Turbo Pascal 将所有函数参数压入堆栈。第一个被首先推送(所以 SS:SP
指向 最后一个 函数参数)。然后是 ( far
) call
被执行。该函数使用 retf n
返回,这意味着调用的函数从堆栈中删除所有参数。
在 inline
函数,简单地给出原始字节 替换 call
操作说明。这意味着 SS:SP
指向参数,而不是返回地址。内联机器语言代码必须pop
来自堆栈的参数。并且它不能使用 ret
返回但只需在 inline
之后的指令处继续代码执行代码。
有了这些知识,可以分析汇编代码:
使用给出的汇编代码,您可以调用 任何 function
或 procedure
通过编写具有与要调用的函数相同的参数以及指向实际函数的附加参数的辅助函数(在您的情况下: VariableLess
)间接使用任何参数(在您的情况下: Less
)。
代码等于以下德尔福 或 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;
关于assembly - 将 Turbo Pascal 内联代码转换为 Object Pascal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65871027/