当前位置: 首页 > 知识库问答 >
问题:

如何使用汇编程序从英特尔处理器获取随机数?

柴瀚昂
2023-03-14

我需要从英特尔处理器中的随机生成器(英特尔酷睿i3)获取随机数。我不想使用任何图书馆。我想在C中使用汇编程序粘贴,但我不知道应该使用哪些寄存器和指令。

共有2个答案

慕阳伯
2023-03-14

... 但我不知道应该使用哪些寄存器和指令。

下面是我在带有GCC的Linux机器上使用的内联汇编程序。我相信我从英特尔手册中撕下了很大一部分。它可能是由DavidJohnston写的,他为rdand问题提供了很棒的技术答案。他也是英特尔公司硬件的设计者。

int RDRAND_bytes(byte* buff, size_t bsize)
{
    if (!HasRDRAND())
        return -1;

    size_t idx = 0, rem = bsize;
    size_t safety = bsize / sizeof(unsigned int) + 4;

    unsigned int val;
    while (rem > 0 && safety > 0)
    {
        char rc;    
        __asm__ volatile(
                "rdrand %0 ; setc %1"
                : "=r" (val), "=qm" (rc)
        );

        // 1 = success, 0 = underflow
        if (rc)
        {
            size_t cnt = (rem < sizeof(val) ? rem : sizeof(val));
            memcpy(buff + idx, &val, cnt);

            rem -= cnt;
            idx += cnt;
        }
        else
        {
            safety--;
        }
    }

    // Wipe temp on exit
    *((volatile unsigned int*)&val) = 0;

    // 0 = success; non-0 = failure (possibly partial failure).
    return (int)(bsize - rem);
}

下面的代码用于HasRDRAND。它同时检测AMD和Intel CPU(我认为这就是所有提供RDRAND的CPU)。

struct CPUIDinfo {
    unsigned int EAX;
    unsigned int EBX;
    unsigned int ECX;
    unsigned int EDX;
};

// Be careful below. EBX/RBX needs to be preserved depending on the memory model and use of PIC.
void cpuid_info(CPUIDinfo *info, const unsigned int func, const unsigned int subfunc) {
    __asm__ __volatile__ (
            "cpuid"
            : "=a"(info->EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX)
            : "a"(func), "c"(subfunc)
    );
}

int HasAmdCpu() {
    CPUIDinfo info;
    cpuid_info(&info, 0, 0);
    if (memcmp((char *) (&info.EBX), "htuA", 4) == 0
            && memcmp((char *) (&info.EDX), "itne", 4) == 0
            && memcmp((char *) (&info.ECX), "DMAc", 4) == 0) {

        return 1;
    }


int HasIntelCpu() {
    CPUIDinfo info;
    cpuid_info(&info, 0, 0);
    if (memcmp((char *) (&info.EBX), "Genu", 4) == 0
            && memcmp((char *) (&info.EDX), "ineI", 4) == 0
            && memcmp((char *) (&info.ECX), "ntel", 4) == 0) {

        return 1;
    }

    return 0;
}

int HasRDRAND() {    
    if (!HasAmdCpu() || !HasIntelCpu())
        return 0;

    CPUIDinfo info;
    cpuid_info(&info, 1, 0);

    static const unsigned int RDRAND_FLAG = (1 << 30);
    if ((info.ECX & RDRAND_FLAG) == RDRAND_FLAG)
        return 1;

    return 0;
}

另请参见如何使用RDRAND内部函数?它不能回答你眼前的问题,但它可能是你的另一种选择(并可能帮助他人)。

华泳
2023-03-14

在支持的CPU(目前只有Ivy Bridge和Haswell Intel CPU)上调用RDRAND指令将把一个随机值放入指定的寄存器中。例如,这将为您提供一个随机的64位值:

RDRAND %rax

成功后,将设置进位。有关更多详细信息,请参阅英特尔的Bull Mountain软件实施指南。(“Bull Mountain”是英特尔硬件RNG的代号。)

 类似资料:
  • 我有一个带有四个麦克风卡(mic0-mic3)的服务器,它工作得很好。我想禁用一些麦克风,例如mic3,现在只有mic0-mic2可用。我该怎么办?

  • 问题内容: 我正在尝试创建一个程序以仅在屏幕上编写参数。我创建了一些程序来获取C函数参数,或者使用C将参数发送给我的asm程序。有没有办法只使用汇编器来获取程序参数 例如: 我正在使用(Gnu汇编器) 通常我使用 因为esp是程序/函数调用指针,但是在纯asm中,它没有获取命令行参数。 有没有办法做到这一点? 我用谷歌搜索,但是我找不到很多信息 问题答案: 在Linux上,熟悉的C语言和变量始终由

  • 我费了很大的劲才让它运转起来: 我尝试了以下方法: 我会得到: 显然,编译器将< code>%0替换为< code>%register,但仍然保留< code>'%'... 因此,我决定将 % 替换为 ,将 替换为 : 并得到结果错误: 我怀疑编译器优化了东西并内联了被调用的函数(所以没有雷特),但仍然不知道我该怎么做。 注意:我不能把编译器从clang改成gcc,因为用clang 11的不是我而

  • 如何使用Java中的Intel AVX矢量指令集?这是一个简单的问题,但答案似乎很难找到。

  • 问题内容: 我有一个数组叫做 我需要从该数组中获取一个随机值并将其存储在变量中,我该怎么做? 问题答案: 您还可以执行以下操作: 当您有关联数组时,这就是这样做的方法。

  • 问题内容: 如何做到这一点? 如果我想分析某些东西是如何编译的,我将如何获取发出的汇编代码? 问题答案: 使用该选项来gcc(或g ++)。 这将在helloworld.c上运行预处理器(cpp),执行初始编译,然后在运行汇编器之前停止。 默认情况下,这将输出一个文件。仍可以使用该选项设置输出文件。 当然,这只有在您拥有原始来源的情况下才有效。如果仅具有结果对象文件,则可以通过设置选项(或-d缩写