Хабрахабр

CPU-функции RDRAND и RDSEED стали доступнее

Всем привет!

Решил разобраться со встроенными в процессор функциями RDRAND и RDSEED. Сам я криптографией не занимаюсь, но кому то вполне может пригодится мое небольшое исследование. Хмм. Компилятор Delphi сказал Undeclared identifier. 2. Уже давно существует BMI, BMI2, AVX, AVX2 и даже AVX-512, а дельфийцы остановились на SSE4. Скомпилируем код сами. Не беда.

Конечно же CPUID. Сначала сделал проверку на поддержку данных функций процессором. Надеюсь никто не додумается запустить CPUID на 486 машине, ибо ее там еще не было. Использовать CPUID можно начиная с первых Pentium процессоров. Кстати RDRAND и RDSEED до процессоров IvyBridge также не существует.

function CPU_support_RDRAND: Boolean;
asm mov rax, $01 cpuid test ecx, 40000000h //тестируем 30-й бит setne al
end; function CPU_support_RDSEED: Boolean;
asm mov rcx, 0 mov rax, $07 //страница №7 cpuid test ebx, 40000h //тестируем 18-й бит setne al
end;

Оказалось, что мой Core i7 G6950X Extreme поддерживает данные функции. Поэтому дальше решил скомпилировать байт-код вручную. Для опытных приведу код REX и REX.W префиксов. Возможно вы захотите записать результат в другой регистр:

const REX_RDRAND32: Byte = $F0; //(11b:REG, 110b:OPCODE, 000b:EAX) REX_RDSEED32: Byte = $F8; //(11b:REG, 111b:OPCODE, 000b:EAX) REX_W_RDRAND64: Byte = $48; //(11b:REG, 110b:OPCODE, 000b:RAX) REX_W_RDSEED64: Byte = $48; //(11b:REG, 111b:OPCODE, 000b:RAX)

Функции могут работать как в 32-х битном режиме, так и в 64-х битном. Поэтому сделал обе и даже в двух вариантах. В итоге получилось 4 функции:

function RDRand32: DWord;
asm @Retry: db $0F, $C7, $F0 //RDRAND EAX (CF = 1 говорит о корректности данных) jnc @Retry
end; function RDSeed32: DWord;
asm @Retry: db $0F, $C7, $F8 //RDSEED EAX (CF = 1 говорит о корректности данных) jnc @Retry
end; function RDRand64: QWord;
asm .NOFRAME @Retry: db $48, $0F, $C7, $F0 //RDRAND RAX (CF = 1 говорит о корректности данных) jnc @Retry
end; function RDSeed64: QWord;
asm .NOFRAME @Retry: db $48, $0F, $C7, $F8 //RDSEED RAX (CF = 1 говорит о корректности данных) jnc @Retry
end;

По скорости они медленней, чем библиотечная функция Random. RDRand примерно на 35%, а RDSeed процентов на 50% и даже более, но качество уникальности генерируемых значений значительно выше. На данном ресурсе есть неплохие статьи на эту тему, ну а моя миссия (сделать функции доступными в Delphi) завершена. В Lazarus не тестировал, но скорее всего будет работать без каких либо изменений. В конец объявления функции нужно лишь добавить резервное слово assembler.

Там можно найти прототип функций Random32 и Random64 на основе встроенных в процессор. Здесь исходные тексты тестового консольного приложения. Всем пока! Возможно это то, что вы искали.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть