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.