【发布时间】:2017-01-05 11:18:18
【问题描述】:
根据 http://www.freepascal.org/docs-html/rtl/system/roldword.html
RolDWord 将一个 4 字节的 int 向左旋转(Free Pascal)。
Delphi 中有 RolDWord 吗?
【问题讨论】:
标签: delphi
根据 http://www.freepascal.org/docs-html/rtl/system/roldword.html
RolDWord 将一个 4 字节的 int 向左旋转(Free Pascal)。
Delphi 中有 RolDWord 吗?
【问题讨论】:
标签: delphi
您可以使用这些功能:
function rolw(Value: Word; N: Integer): Word;
asm
{$IF Defined(CPUX86)}
MOV CL, DL
ROL AX, CL
{$ELSEIF Defined(CPUX64)}
MOV AX, CX
MOV CL, DL
ROL AX, CL
{$ELSE}
{$Message Fatal 'rolw has not been implemented for this architecture.'}
{$ENDIF}
end;
function rorw(Value: Word; N: Integer): Word;
asm
{$IF Defined(CPUX86)}
MOV CL, DL
ROR AX, CL
{$ELSEIF Defined(CPUX64)}
MOV AX, CX
MOV CL, DL
ROR AX, CL
{$ELSE}
{$Message Fatal 'rorw has not been implemented for this architecture.'}
{$ENDIF}
end;
function roldw(Value: Cardinal; N: Integer): Cardinal;
asm
{$IF Defined(CPUX86)}
MOV CL, DL
ROL EAX, CL
{$ELSEIF Defined(CPUX64)}
MOV EAX, ECX
MOV CL, DL
ROL EAX, CL
{$ELSE}
{$Message Fatal 'roldw has not been implemented for this architecture.'}
{$ENDIF}
end;
function rordw(Value: Cardinal; N: Integer): Cardinal;
asm
{$IF Defined(CPUX86)}
MOV CL, DL
ROR EAX, CL
{$ELSEIF Defined(CPUX64)}
MOV EAX, ECX
MOV CL, DL
ROR EAX, CL
{$ELSE}
{$Message Fatal 'rordw has not been implemented for this architecture.'}
{$ENDIF}
end;
然而,正如Johan 和LU RD 指出的那样,内联Pascal 版本是可移植的,并且通常对于此功能更快,因为内联对于如此小的功能非常重要。
看起来像这样:
{$IFOPT Q+}{$DEFINE OVERFLOWCHECKSON}{$ENDIF}
{$Q-}
function rolw_pas(Value: Word; N: Integer): Word; inline;
begin
Result:= ((Value shl N) and $ffff) or (Value shr (16-N));
end;
function rorw_pas(Value: Word; N: Integer): Word; inline;
begin
Result:= (Value shr N) or ((Value shl (16-N)) and $ffff);
end;
function roldw_pas(Value: Cardinal; N: Integer): Cardinal; inline;
begin
Result:= (Value shl N) or (Value shr (32-N));
end;
function rordw_pas(Value: Cardinal; N: Integer): Cardinal; inline;
begin
Result:= (Value shr N) or (Value shl (32-N));
end;
{$IFDEF OVERFLOWCHECKSON}{$Q+}{$ENDIF}
请注意,我们确实需要确保禁用溢出检查。
【讨论】:
在 purepascal 中,您可以按如下方式使用移位。
function rolw(input: dword; shift: cardinal): dword; inline;
begin
Result:= (input shl shift) or (input shr (32-shift));
end;
RorW 的工作原理完全相同。
好处
它适用于任何版本的 Delphi,包括移动编译器。
asm 代码实际上更慢,因为它不能被内联,根据 LURD 的时间(在他的系统和他的输入数据上),纯 pascal 版本在 x86 上快 3.5 倍,在 x64 上快 25%。但是对于不同的输入数据,时间可能会完全不同,所以如果性能是一个驱动因素,请确保您使用代表您实际问题的数据进行基准测试。
源代码更短,因为您不需要针对不同 CPU 类型的不同版本。
如果你有一个更大的 asm 块,一定要使用 ror/rol 指令;它们具有与移位指令完全相同的延迟,但在 1 条指令而不是 3 条指令中执行操作。
【讨论】:
shift := shift mod 32。