我有这个函数(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;
特别是它写的:
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/