The MASM Forum

General => The Workshop => Topic started by: jack on May 03, 2021, 10:48:33 AM

Title: test for RdSeed
Post by: jack on May 03, 2021, 10:48:33 AM
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
Title: Re: test for RdSeed
Post by: hutch-- on May 03, 2021, 09:12:56 PM
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.
Title: Re: test for RdSeed
Post by: jack on May 03, 2021, 09:19:59 PM
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?
Title: Re: test for RdSeed
Post by: hutch-- on May 03, 2021, 10:12:35 PM
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.
Title: Re: test for RdSeed
Post by: hutch-- on May 03, 2021, 10:33:05 PM
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
Title: Re: test for RdSeed
Post by: jack on May 03, 2021, 11:44:10 PM
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
.....
Title: Re: test for RdSeed
Post by: jack on May 04, 2021, 12:29:15 AM
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
Title: Re: test for RdSeed
Post by: 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.
Title: Re: test for RdSeed
Post by: hutch-- on May 04, 2021, 09:16:33 AM
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

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Title: Re: test for RdSeed
Post by: Greenhorn on May 06, 2021, 12:32:16 AM
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.
Title: Re: test for RdSeed
Post by: InfiniteLoop on May 20, 2021, 08:21:19 AM
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