my CPU is Intel i9-9900K, so why does the following test fail?
mov eax, 7
xor ecx, ecx
cpuid
bt ebx, 18
jnc .exit
rdseed rax
mov qword ptr [n], rax
.exit:
that's FreeBasic inline-asm, n is a 64-bit integer
I am not much use to you here Jack, I did a lot of work on random generators some years ago and remember testing rdrand which was as slow as a wet week but I don't think my Haswell generation CPUs support rdseed.
RdSeed seems to work OK if I remove the conditional jump, but why does the test fail?
is the information about testing for the availability of RdSeed wrong?
Jack,
Try and isolate the CPUID code from the RDSEED code. Do the CPUID code in a separate proc and if it returns the right result, then run the RDSEED instruction.
PS : Guys, no miseries please.
Because my Haswell era CPU does not support RDSEED, I can get RDRAND to work OK.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include64\masm64rt.inc
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
entry_point proc
LOCAL cnt :QWORD
mov cnt, 50
lp:
rdrand rax
conout str$(rax),lf
sub cnt, 1
jnz lp
waitkey
.exit
entry_point endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
thanks hutch
it seem that the information found here is wrong https://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features
if I compile and run this C++ code https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=msvc-160 it correctly tells me that rdseed is supported
GenuineIntel
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
.....
RDRAND supported
RDSEED supported
.....
I still would like to know why the asm code fails, see https://software.intel.com/content/www/us/en/develop/articles/intel-digital-random-number-generator-drng-software-implementation-guide.html
I think that the test was right, it's just that RdSeed doesn't always succeed, when that happens the result is 0
case closed.
Jack,
Here is a seed generator that is very hard to improve on. The action is in the following small snippet.
cpuid ; set all regs to 0
rdtsc ; date time counter
pause ; spinlock pause
bswap rax ; reverse byte order
mov r11, rax ; store rax in r11
This is the form I used it in.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
NOSTACKFRAME
reseed proc
mov rax, 100 ; out of range number
cpuid ; set all regs to 0
rdtsc ; date time counter
pause ; spinlock pause
bswap rax ; reverse byte order
mov r11, rax ; store rax in r11
mov rcx, 10 ; loop count
@@:
rdtsc ; date time counter
pause ; spinlock pause
bswap rax ; reverse byte order
rol rax, 7 ; rotate left by prime
xor r11, rax ; xor rax to r11
rol r11, 5 ; rotate left by prime
sub rcx, 1 ; decrement counter
jnz @B
mov rax, r11 ; return the value in r11
ret
reseed endp
STACKFRAME
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Quote from: jack on May 04, 2021, 12:50:44 AM
I think that the test was right, it's just that RdSeed doesn't always succeed, when that happens the result is 0
case closed.
»Hardware modifies the CF flag to indicate whether the value returned in the destination register is
valid. If CF = 1, the value is valid. If CF = 0, the value is invalid and will be returned as zero. Software
must test the state of the CF flag prior to using the value returned in the destination register to
determine if the value is valid. If the returned value is invalid, software must execute the instruction
again. Software should implement a retry limit to ensure forward progress of code.
«Quotet from the AMD manuals.
Strange that it does not work.
It works perfectly:
#include <iostream>
#include <string>
#include <Windows.h>
extern "C" unsigned long long ASM_test();
int main()
{
std::cout << "ASM bit test. Does rdseed exist? = " << std::to_string((ASM_test() == -1)) << std::endl;
Sleep(120000);
return(0);
}
ASM_test proc
push rbx
mov eax, 7
xor ecx,ecx
xor edx,edx
xor ebx,ebx
cpuid
;bt ebx, 5 ;AVX2
bt ebx,18 ;RDSEED
;bt ebx, 16 ;AVX-512
jnc Done ;equal to zero
mov rax, -1
Done:
pop rbx
ret
ASM_test endp