Мне нужно изменить генератор случайных чисел, используя rdrand (только), Это реализовано в коде c следующим образом.
uint64_t _rdrand(void)
{
uint64_t r;
__asm__ volatile("rdrand %0\n\t" : "=r"(r));
return r;
}
Теперь мне нужно изменить так, чтобы он возвращался, только если установлен флаг переноса. (Согласно документации rdrand) Я думаю, что это можно сделать с помощью инструкции jc, но не знаю, как использовать внутри __asm__ volatile. Пожалуйста, помогите мне.
это рука или x86?
Почему бы просто не использовать встроенный от <immintrin.h>
? if (_rdrand64_step(&r) == 0) { /* Unable to generate random number */ }
(может потребоваться компиляция с -mrdrnd
или соответствующей настройкой -march=
).
@ThiruShetty: gcc6 и более поздние версии могут иметь выходные данные флагов из операторов asm (Использование флагов условий в качестве встроенных asm-выходов GNU C). Это позволит избежать выполнения setc
и последующего использования компилятором test al,al
для результата. что просто глупо. (Но в любом случае использование встроенных функций было бы лучше, чтобы полностью избежать проблемы.) И это также лучше, чем делать jc
внутри asm, даже если вы используете asm goto
или что-то еще для перехода на return 0
или return 1
, как это делает ядро Linux в некоторых случаях. места для разветвления внутри inline asm.
@PeterCordes согласен с вами .. позвольте мне удалить мой пост
в настоящее время нет разрешения на использование встроенного в нашем SDK @Shawn
Вы можете проверить это. Или просто попробуйте этот __asm__ volatile ( "1%=: \n\t" "rdrand %0\n\t" "jnc 1%=\n\t" : "=r"(r) : :);
в чем смысл этого шаблона ассемблера? Я сослался на документы gcc для расширенного asm, но это кажется сложным, я понял, что здесь вводится% 0. Но что делает 1%. что означает этот jnc 1% = \ n \ t? 1% =:?
С GCC 6 (или более поздней версии), как предложил Питер, вы могли бы написать его как uint64_t _rdrand(void) { uint64_t r; uint8_t carry; do { __asm__ volatile ("rdrand %1\n\t" : "=@ccc"(carry), "=r"(r)); } while (!carry); return r; }
. С оптимизацией (при условии 64-битного кода) он должен уменьшиться до функции, подобной looplabel: rdrand %rax
jnc looplabel
ret
, здесь RAX будет любым регистром, который выбирает компилятор.
Если вы пишете производственный код (и не можете использовать встроенные функции) и плохо знакомы с нюансами и сложностями встроенной сборки, я бы рекомендовал не использовать встроенную сборку и предлагал вам просто написать модуль сборки, который содержит код сборки, аналогичный следующему: _rdrand:
rdrand %rax
jnc _rdrand
ret
. Если вы ошиблись при встроенной сборке, поиск ошибок может стать настоящим кошмаром.
в setc% 1 что такое% 1 и возвращается ли он, только если установлен флаг переноса @ Thiru Shetty