assembly - 将 Turbo Pascal 内联代码转换为 Object Pascal

标签 assembly inline pascal x86-16 turbo-pascal

在将旧的 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 之后的指令处继续代码执行代码。
有了这些知识,可以分析汇编代码:
使用给出的汇编代码,您可以调用 任何 functionprocedure通过编写具有与要调用的函数相同的参数以及指向实际函数的附加参数的辅助函数(在您的情况下: 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/

相关文章:

PascalScript 中的 JSON 解析器

c++ - c中的BSS段,进展方式

encryption - 识别密码学密码

ios - 如何在 UICollectionView Swift 中内联播放视频?

jQuery UI slider : how to inline it?

algorithm - 对包含 7 个整数的数组进行排序的最快方法是什么?

Delphi 数组 : Variable Myvar might not been initialized

performance - Perf overcounting simple CPU-bound loop : mysterious kernel work?

assembly - 在用户模式下,x86 CPU可以读取任何寄存器的值吗?

html - 使内联 block 在顶部而不是底部对齐