delphi - 将 ASM 指令 RDRand 转换为 Win64

标签 delphi assembly x86-64 rdrand

我有这个函数(RDRand - 由 David Heffernan 编写)在 32 位中接缝工作正常,但在 64 位中失败:

function TryRdRand(out Value: Cardinal): Boolean;
{$IF defined(CPU64BITS)}
asm .noframe
{$else}
asm
{$ifend}
  db   $0f
  db   $c7
  db   $f1
  jc   @success
  xor  eax,eax
  ret
@success:
  mov  [eax],ecx
  mov  eax,1
end;

函数的文档在这里:https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide

特别是它写的:

Essentially, developers invoke this instruction with a single operand: the destination register where the random value will be stored. Note that this register must be a general purpose register, and the size of the register (16, 32, or 64 bits) will determine the size of the random value returned.

After invoking the RDRAND instruction, the caller must examine the carry flag (CF) to determine whether a random value was available at the time the RDRAND instruction was executed. As Table 3 shows, a value of 1 indicates that a random value was available and placed in the destination register provided in the invocation. A value of 0 indicates that a random value was not available. In current architectures the destination register will also be zeroed as a side effect of this condition.

我对 ASM 的了解很低,我错过了什么?

我也不太明白这条指令:

  ...
  xor  eax,eax
  ret
  ...

它的具体作用是什么?

最佳答案

如果您想要一个执行完全相同的函数,那么我认为它看起来像这样:

function TryRdRand(out Value: Cardinal): Boolean;
asm
{$if defined(WIN64)}
  .noframe
  // rdrand eax
  db   $0f
  db   $c7
  db   $f0
  jnc  @fail
  mov  [rcx],eax
{$elseif defined(WIN32)}
  // rdrand ecx
  db   $0f
  db   $c7
  db   $f1
  jnc  @fail
  mov  [eax],ecx
{$else}
{$Message Fatal 'TryRdRand not implemented for this platform'}
{$endif}
  mov  eax,1
  ret
@fail:
  xor  eax,eax
end;

Peter Cordes提出的建议在 asm 中实现重试循环对我来说看起来很明智。我不会尝试在这里实现它,因为我认为它在某种程度上超出了您的问题范围。

此外,Peter 指出,在 x64 中,您可以读取带有 REX.W=1 前缀的 64 位随机值。看起来像这样:

function TryRdRand(out Value: NativeUInt): Boolean;
asm
{$if defined(WIN64)}
  .noframe
  // rdrand rax
  db   $48  // REX.W = 1
  db   $0f
  db   $c7
  db   $f0
  jnc  @fail
  mov  [rcx],rax
{$elseif defined(WIN32)}
  // rdrand ecx
  db   $0f
  db   $c7
  db   $f1
  jnc  @fail
  mov  [eax],ecx
{$else}
{$Message Fatal 'TryRdRand not implemented for this platform'}
{$endif}
  mov  eax,1
  ret
@fail:
  xor  eax,eax
end;

关于delphi - 将 ASM 指令 RDRand 转换为 Win64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66699335/

相关文章:

assembly - Ivy 桥上RDRAND的耗竭特性是什么?

linux - 如果涉及 MAP_FIXED,无限堆栈不能超过初始的 132KiB?

assembly - 学习汇编——回显程序名

delphi - 是否可以包含基于组件属性的文件(链接)?

delphi - 如何像那里一样正确发送 POST 请求?

assembly - 我将使用什么编译器来编写机器语言?

在linux中从C代码调用汇编函数

C++ - 常量和优化

delphi - THttpClient 没有在 Delphi 中关闭连接

delphi - 如何将 TZipFile.FileComment 作为字符串读取?