Bawiłem się dziś troszkę asemblerem i o ile przykładowo
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint64_t rnd = 0;
__asm__ volatile (
"rdrandq %%rax \n"
"shrq $50, %%rax \n"
"movq $20, %%rcx \n"
"xorq %%rdx, %%rdx \n"
"divq %%rcx \n"
: "=d" (rnd)
);
printf("%llu\n", rnd);
return 0;
}
daje oczekiwany wynik, tj. robi jakieś tam rzeczy (losuje liczbę z przedziału 0-20) i zapisuje wynik do rdx, po czym ta wartość jest przechwytywana do zmiennej rnd, to już z liczbami zmiennoprzecinkowymi nie mogę sobie poradzić.
Z tego, co wyczytałem (ze średnim zrozumieniem), to żeby dobrać się do rejestrów xmm, muszę podać output constraint =m.
#include <stdint.h>
#include <stdio.h>
int main(void)
{
float foo = 0.0;
__asm__ volatile (
"mov %%eax, 3\n"
/* z tego, co rozumiem, to jest konwersja liczby z rejestru całkowitego
na liczbę zmiennoprzecinkową pojedynczej precyzji
zresztą godbolt.org pokazuje taką instrukcję dla analogicznej funkcji w C */
"cvtsi2ss %%eax, %%xmm0"
: "=m" (foo)
);
printf("%0.4f\n", foo);
return 0;
}
Ale niestety program rzuca segfaultem (zarówno kompilując clangiem jak i gcc 9). Wrzuciłem to na godbolt.org i tam nie ma segfaulta, ale też nie działa to, jakbym oczekiwał. Printuje się wartość, na jaką zainicjalizuję foo. Coś robię źle, ale nie wiem, co. Ofc, wertowałem stackoverflow, ale bez efektów.
Edit: doczytałem o constraintach i powinienem chyba użyć "=Yz" zamiast "=m", ale nadal nie działa.