简体   繁体   English

如何使用内联汇编与.Net使用英特尔的RDRAND

[英]How to use Intel's RDRAND using inline assembly with .Net

I'm using an Intel Ivy Bridge CPU and want to use the RDRAND opcode ( https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide ) in C#. 我正在使用Intel Ivy Bridge CPU,并且想使用RDRAND操作码( https://software.intel.com/zh-cn/articles/intel-digital-random-number-generator-drng-software-implementation-guide )在C#中。

How can I call this CPU instruction via C#? 如何通过C#调用此CPU指令? I've seen an example of executing assembly code from c# here: x86/x64 CPUID in C# 我在这里看到了一个从c#执行汇编代码的示例: C#中的x86 / x64 CPUID

But I'm not sure how to use it for RDRAND. 但是我不确定如何将其用于RDRAND。 The code doesn't need to check whether the CPU executing the code supports the instruction or not. 该代码不需要检查执行该代码的CPU是否支持该指令。

I've seen this C++ example of executing assembly byte code coming from drng_samples of Intel: 我已经看过这个C ++示例,它执行来自Intel的drng_samples的汇编字节代码:

int rdrand32_step (uint32_t *rand)
{
    unsigned char ok;

    /* rdrand edx */
    asm volatile(".byte 0x0f,0xc7,0xf0; setc %1"
        : "=a" (*rand), "=qm" (ok)
        :
        : "edx"
    );

    return ok;
}

How can the example of executing assembly code in C# be combined with the C++ code coming from the Intel drng sample code? 如何在C#中执行汇编代码的示例与来自Intel drng示例代码的C ++代码结合在一起?

There are answers out on SO that will generate (unmanaged) assembly code at runtime for managed code to call back into. 有关于SO的答案,它们将在运行时生成(非托管的)汇编代码,以供托管代码回调。 That's all very interesting, but I propose that you simply use C++/CLI for this purpose, because it was designed to simplify interop scenarios. 这都是非常有趣的,但是我建议您为此目的简单地使用C ++ / CLI,因为它旨在简化互操作方案。 Create a new Visual C++ CLR class library and give it a single rdrandwrapper.cpp : 创建一个新的Visual C ++ CLR类库,并给它一个rdrandwrapper.cpp

#include <immintrin.h>

using namespace System;

namespace RdRandWrapper {

#pragma managed(push, off)
  bool getRdRand(unsigned int* pv) {
    const int max_rdrand_tries = 10;
    for (int i = 0; i < max_rdrand_tries; ++i) {
      if (_rdrand32_step(pv)) return true;
    }
    return false;
  }
#pragma managed(pop)

  public ref class RandomGeneratorError : Exception
  {
  public:
    RandomGeneratorError() : Exception() {}
    RandomGeneratorError(String^ message) : Exception(message) {}
  };

  public ref class RdRandom
  {
  public:
    int Next() {
      unsigned int v;
      if (!getRdRand(&v)) {
        throw gcnew RandomGeneratorError("Failed to get hardware RNG number.");
      }
      return v & 0x7fffffff;
    }
  };
}

This is a very bare-bones implementation that just tries to mimic Random.Next in getting a single non-negative random integer. 这是一个非常简单的实现,它只是试图模仿Random。 Random.Next是获取单个非负随机整数。 Per the question, it does not attempt to verify that RDRAND is actually available on the CPU, but it does handle the case where the instruction is present but fails to work. 对于每个问题,它不会尝试验证RDRAND在CPU上是否实际可用,但会处理存在指令但无法正常工作的情况。 (This "cannot happen" on current hardware unless it's broken, as detailed here .) (这除非是打破“不可能发生”在当前的硬件,详见这里 )。

The resulting assembly is a mixed assembly that can be consumed by managed C# code. 生成的程序集是混合的程序集,可以由托管C#代码使用。 Make sure to compile your assembly as either x86 or x64, same as your unmanaged code (by default, projects are set to compile as "Any CPU", which will not work correctly since the unmanaged code has only one particular bitness). 确保将程序集与非托管代码一样编译为x86或x64(默认情况下,项目设置为编译为“ Any CPU”,由于非托管代码只有一个特定的位数,因此将无法正常工作)。

using System;
using RdRandWrapper;

class Program {
  static void Main(string[] args) {
    var r = new RdRandom();
    for (int i = 0; i != 10; ++i) {
      Console.WriteLine(r.Next());
    }
  }
}

I make no claims as to performance, but it's probably not great. 我对性能没有要求,但可能并不理想。 If you wanted to get many random values this way, you would probably want a Next(int[] values) overload to get many random values in one call, to reduce the overhead of interop. 如果要以这种方式获取许多随机值,则可能希望Next(int[] values)重载在一个调用中获得许多随机值,以减少互操作的开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM