首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Turbo Pascal内联代码转换为Object Pascal

将Turbo Pascal内联代码转换为Object Pascal
EN

Stack Overflow用户
提问于 2021-01-24 21:20:46
回答 2查看 192关注 0票数 4

在将旧的Turbo Pascal单元转换为现代对象Pascal时,我遇到了以下问题:

代码语言:javascript
复制
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-},收集结果并将其传递给调用函数。函数在为非类型化数据提供二叉树的单元中使用

代码语言:javascript
复制
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,我发现这对应于:

代码语言:javascript
复制
{$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位的。

EN

回答 2

Stack Overflow用户

发布于 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)来间接调用带有任何参数的任何 functionprocedure (在您的示例中为:Less),该函数具有与要调用的函数相同的参数,外加一个指向实际函数的附加参数。

该代码等同于以下DelphiFreePascal代码:

代码语言:javascript
复制
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显然不支持),你可能需要汇编。

但在这种情况下,不同的编译器需要不同的汇编代码!

因此,如果不了解编译器的内部结构,就不可能翻译汇编代码。

编辑

我不确定你的编译器到底是如何工作的。但是,如果我的原始代码不起作用,下面的代码可能会起作用:

代码语言:javascript
复制
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;
票数 7
EN

Stack Overflow用户

发布于 2021-01-27 23:58:13

解决方案如下:在处理动态类型的单元内部定义

代码语言:javascript
复制
 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. }

这是从外部调用

代码语言:javascript
复制
{$F+} function VariableLess(var a, b : Index) : boolean; {$F-}
begin
...
end;

InsVarBBTree(Baum, TempStr, SizeOf(TempStr), TMyCompare(@VariableLess), OK)

感谢所有帮助这件事的人

恩格尔伯特

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65871027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档