首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FPC BASM32 MUL bug?

FPC BASM32 MUL bug?
EN

Stack Overflow用户
提问于 2015-12-30 06:12:43
回答 2查看 173关注 0票数 2

我在将Delphi代码移植到FPC时遇到了一个问题:

代码语言:javascript
复制
program MulTest;

{$IFDEF FPC}
  {$mode delphi}
  {$asmmode intel}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

function Mul(A, B: LongWord): LongWord;
asm
         MUL    EAX,EDX
end;

begin
  Writeln(Mul(10,20));
  Readln;
end.

以上代码在Delphi中编译并按预期工作;FPC输出MUL EAX,EDX行上的编译时错误:

错误: Asm: mul reg32,reg32操作码和操作数的无效组合

我将Lazarus1.4.4/FPC2.6.4用于Win32 (当前稳定版本)

有什么解决办法或解决办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-30 06:27:05

FreePascal是正确的。只有3种形式的MUL

代码语言:javascript
复制
MUL r/m8
MUL r/m16
MUL r/m32

执行第一个操作数(目标操作数)和第二个操作数(源操作数)的无符号乘法,并将结果存储在目标操作数中。目标操作数是位于寄存器AL、AX或EAX中的隐含操作数(取决于操作数的大小);源操作数位于通用寄存器或内存位置中。

换句话说,第一个操作数(用于输入和输出)在AL/AX/EAX,中指定,第二个输入操作数显式地指定为通用寄存器或内存地址。

因此,MUL EAX,EDX确实是一个无效的程序集指令。

如果在Delphi中编译此代码并使用调试器查看生成的程序集,您将看到对Mul(10,20)的调用生成以下程序集代码:

代码语言:javascript
复制
// Mul(10,20)
mov edx,$00000014
mov eax,$0000000a
call Mul

代码语言:javascript
复制
//MUL    EAX,EDX
mul edx

因此,正如您所看到的,Delphi实际上是解析源代码,看到第一个操作数是EAX,并为您剥离它,从而生成正确的程序集。FreePascal不是为你做这一步。

解决办法?首先编写正确的汇编代码。不要依赖编译器为您重新解释代码。

代码语言:javascript
复制
function Mul(A, B: LongWord): LongWord;
asm
         MUL    EDX
end;

或者,您可以简单地不直接编写程序集代码,让编译器为您工作。它知道如何将两个LongWord值组合在一起:

代码语言:javascript
复制
function Mul(A, B: LongWord): LongWord;
begin
  Result := A * B;
end;

虽然在本例中德尔菲确实使用了IMUL而不是MUL。来自德尔菲的文档

x / y的值为Extended类型,与xy的类型无关。对于其他算术运算符,当至少一个操作数为实时,结果为Extended类型;否则,当至少一个操作数为Int64类型时,结果为Int64类型;否则,结果为类型。如果操作数的类型是整数类型的子范围,则将其视为整数类型。

它还使用一些难看的臃肿的程序集,除非禁用堆栈帧并启用优化。通过配置这两个选项,可以让Mul()生成单个IMUL EDX指令(当然还有RET指令)。如果不想在项目范围内更改选项,可以使用Mul() / {$STACKFRAMES OFF}/{$W-}{$OPTIMIZATION ON}/{$O+}编译器指令将它们隔离为只使用{$OPTIMIZATION ON}

代码语言:javascript
复制
{$IFOPT W+}{$W-}{$DEFINE SF_Was_On}{$ENDIF}
{$IFOPT O-}{$O+}{$DEFINE O_Was_Off}{$ENDIF}
function Mul(A, B: LongWord): LongWord;
begin
  Result := A * B;
end;
{$IFDEF SF_Was_On}{W+}{$UNDEF SF_Was_On}{$ENDIF}
{$IFDEF O_Was_Off}{O-}{$UNDEF O_Was_Off}{$ENDIF}

生成:

代码语言:javascript
复制
imul edx
ret
票数 10
EN

Stack Overflow用户

发布于 2015-12-30 06:26:51

MUL总是由AL、AX或EAX (更多细节)乘以,因此您应该只指定其他操作数。

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

https://stackoverflow.com/questions/34523936

复制
相关文章

相似问题

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