在将旧的 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);
该代码应该调用一个
外部函数 {$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. }
因此,单元本身无法提供比较功能,这是定义有效负载的单元的工作。
使用在线反汇编器,我发现这对应于:
{$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位的。
call 6
是一个调用指令,跳转到下一条指令 (e8 00 00
)。我不太理解这段代码的工作原理。它似乎会影响返回地址。紧接在此函数下面定义的是什么函数? - fuzcall next_insn
/pop ax
只是获取 AX=IP。如果我数对了的话,是的,我认为 AX+8 返回地址正在计算retf
之后。我认为它使用 push/push/retf 作为当前 CS 和指针参数偏移量的远跳转?也许是某种在近距离和远距离调用之间的适配器?这在 x86-64 中都是无意义的,因为你不想进行远程调用。x86-64 具有 RIP 相关 LEA,因此如果您确实想制造虚假的返回地址,则可以获得 RIP,不匹配的 call/ret 对性能不利。 - Peter Cordes