Как я могу получить случайное число от процессора Intel с помощью ассемблера?

Мне нужно получить случайное число от генератора случайных чисел Intel в процессоре (Intel Core i3). Я не хочу использовать какую-либо библиотеку. Я хочу использовать пасту ассемблера в C++, но я не знаю, какие регистры и инструкции следует использовать.


person Polina Sazonova    schedule 10.07.2012    source источник


Ответы (2)


Вызов инструкции RDRAND на поддерживаемых процессорах (в настоящее время только на процессорах Ivy Bridge и Haswell Intel) поместит случайное значение в указанный регистр. Например, это даст вам случайное 64-битное значение:

RDRAND %rax

В случае успеха будет установлен бит переноса. Дополнительную информацию см. в Руководстве по внедрению программного обеспечения Bull Mountain. («Bull Mountain» — это кодовое название аппаратного ГСЧ Intel.)

person Community    schedule 10.07.2012
comment
Можете ли вы уточнить, является ли это генератором PRNG или генератором входа? - person Mark B; 10.07.2012
comment
Нажмите на ссылку. TLDR: это настоящий генератор случайных чисел. - person Gunther Piez; 10.07.2012

... но я не знаю, какие регистры и инструкции следует использовать.

Ниже показан встроенный ассемблер, который я использую на машинах Linux с GCC. Я считаю, что я скопировал значительную часть из руководства Intel. Вероятно, его написал Дэвид Джонстон, который дает замечательные технические ответы на rdand вопросы. Он также занимается разработкой аппаратного обеспечения в Intel.


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 (я думаю, что это все процессоры, поддерживающие RDRAND).

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? Это не отвечает на ваш непосредственный вопрос, но может быть альтернативой для вас (и может помочь другие).

person jww    schedule 04.05.2014
comment
Это началось как моя работа, но то, что у вас есть, было очищено и улучшено экспертами по программному обеспечению низкого уровня в Intel, которые приложили усилия для кросс-компилятора и совместимости кросс-слов. - person David Johnston; 26.01.2015
comment