如何使用内联汇编与.Net使用英特尔的RDRAND [英] How to use Intel's RDRAND using inline assembly with .Net

查看:131
本文介绍了如何使用内联汇编与.Net使用英特尔的RDRAND的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Intel Ivy Bridge CPU,并希望使用RDRAND操作码(

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#.

如何通过C#调用此CPU指令?我在这里看到了从c#执行汇编代码的示例:在C#中使用x86/x64 CPUID

How can I call this CPU instruction via C#? I've seen an example of executing assembly code from c# here: x86/x64 CPUID in C#

但是我不确定如何将其用于RDRAND.该代码无需检查执行该代码的CPU是否支持该指令.

But I'm not sure how to use it for RDRAND. The code doesn't need to check whether the CPU executing the code supports the instruction or not.

我已经看过这个C ++示例,它执行来自英特尔的drng_samples :

I've seen this C++ example of executing assembly byte code coming from drng_samples of Intel:

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;
}

如何将在C#中执行汇编代码的示例与来自英特尔drng示例代码的C ++代码结合起来?

How can the example of executing assembly code in C# be combined with the C++ code coming from the Intel drng sample code?

推荐答案

有一些关于SO的答案,这些答案将在运行时生成(非托管的)汇编代码,供托管代码回调.这都是非常有趣的,但是我建议您为此目的简单地使用C ++/CLI,因为它旨在简化互操作方案.创建一个新的Visual C ++ CLR类库,并给它一个rdrandwrapper.cpp:

There are answers out on SO that will generate (unmanaged) assembly code at runtime for managed code to call back into. 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. Create a new Visual C++ CLR class library and give it a single 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;
    }
  };
}

这是一个非常简单的实现,它只是试图模仿Random.Next来获取单个非负随机整数.对于每个问题,它不会尝试验证RDRAND在CPU上是否实际可用,但会处理存在该指令但无法正常工作的情况. (在此处中有详细说明,除非当前硬件已损坏,否则不会发生").

This is a very bare-bones implementation that just tries to mimic Random.Next in getting a single non-negative random integer. 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. (This "cannot happen" on current hardware unless it's broken, as detailed here.)

生成的程序集是混合的程序集,可以由托管C#代码使用.确保将程序集与非托管代码一样编译为x86或x64(默认情况下,项目设置为编译为"Any CPU",由于非托管代码只有一个特定的位数,因此将无法正常工作).

The resulting assembly is a mixed assembly that can be consumed by managed C# code. 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).

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());
    }
  }
}

我对性能没有任何要求,但可能并不理想.如果您想以这种方式获取许多随机值,则可能希望Next(int[] values)重载在一次调用中获得许多随机值,以减少互操作的开销.

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.

这篇关于如何使用内联汇编与.Net使用英特尔的RDRAND的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆