将GCC内嵌汇编转换为Delphi内嵌汇编

7

请注意,以下是一段GCC内联汇编代码:

int   src = 0;
dword n;
__asm(
            "sar %%cl,%%edx"
            : "=d" (n) // saves in eax,edx
            : "c" (src), "d" (n) // the inputs
            );

我的Delphi尝试如下:
asm
mov ecx, &src
mov edx, &n
sar cl,edx
mov eax,edx
end;

请问这个是否正确?


5
我的建议是将此代码转换成Pascal而不是汇编语言。 - David Heffernan
1个回答

10

在Delphi中,内联汇编与GCC中的工作方式不同。首先,Delphi中没有与宏和模板相关的支持,因此如果要使用一种声明一次的通用汇编例程,您必须将其声明为函数:

function ShiftArithmeticRight(aShift: Byte; aValue: LongInt): LongInt;
{$IFDEF WIN64}
asm
  sar edx,cl
  mov eax,edx
end;
{$ELSE}
{$IFDEF CPU386}
asm
  mov cl,al
  sar edx,cl
  mov eax,edx
end;
{$ELSE}
begin
  if aValue < 0 then
    Result := not (not aValue shr aShift)
  else
    Result := aValue shr aShift;
end;
{$ENDIF}
{$ENDIF}

在Delphi中,内联汇编必须在使用的地方实现,并且仅支持32位。在这样的asm块中,您可以自由使用EAX、ECX和EDX,以及周围代码中的任何标识符。例如:

var
  lValue: LongInt;
  lShift: Byte;
begin
  // Enter pascal code here
  asm
    mov cl,lShift
    sar lValue,cl
  end;
  // Enter pascal code here
end;

我修复了原回答中的一个错误。 SAR 是一项有符号操作,因此 aValue 参数应该是 LongInt 而不是 LongWord。 - Henrick Hellström
汇编语言只有在您想确保编译器完全按照您的意图执行操作,并且如果编译器实现 shr 运算符在不同版本之间发生更改(例如始终为位移 shr 在一个版本中,但对于有符号类型则为 sar 在另一个版本中),这种情况下才会有用。 - Henrick Hellström
1
不要误会我的意思。你写了一个覆盖所有基础的绝妙答案。我点赞并鼓励Alexis接受。我只是希望能看到一些指导,特别是对于那些在汇编语言方面没有像你这样熟练的程序员来说,更需要指引。如果你明白我的意思,最适合你的可能并不适合每个人。 - David Heffernan
@HenrickHellström,您的纯Pascal版本在aShift = 1aValue = -5时失败。它返回了-2而不是-3 - JRL
@HenrickHellström 现在没问题了。 - JRL
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接