[asm] inline assembly na rejestrach xmm

0

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.

0

Napisz sobie to po prostu w assemblerze MASM / FASM i spróbuj zdebuggować pod x64dbg.

2
Bartosz Wójcik napisał(a):

Napisz sobie to po prostu w assemblerze MASM / FASM i spróbuj zdebuggować pod x64dbg.

Popieram, zamiast tego koszmarka z __asm__ volatile polecam kod assemblera trzymać w osobnym pliku .asm, skompilować do .o i zlinkować z resztą kodu w C/C++ za pomocą gcc czy tam clanga.

0

Popieram, zamiast tego koszmarka z asm volatile polecam kod assemblera trzymać w osobnym pliku .asm

Jak będę miał w pracy coś do napisania w asm, to oczywiście tak pewnie zrobię, ale w tej chwili chcę nabyć umiejętność posługiwania się inline asm i tym syntaxem constraintów, bo skompilować osobny plik asma już umiem.

Napisz sobie to po prostu w assemblerze MASM / FASM i spróbuj zdebuggować pod x64dbg.

Tak, z tym że problem nie leży w tym, że piszę złe instrukcje (to już sprawdziłem), tylko problem jest na poziomie posługiwania się składnią inline asm, a konkretnie w przekazaniu wartości float z rejestru do zmiennej.

Swoją drogą, już sobie poradziłem

#include <stdio.h>

int main(void)
{
    float foo = 0.0;
    __asm__ volatile (
        "movl $2, %%eax \n"
        "cvtsi2ss %%eax, %%xmm0 \n"
        "movss %%xmm0, %[foo]"

        : [foo] "=Yz" (foo)
    );

    printf("%0.2f\n", foo);
}

Niestety działa to tylko pod gcc, clang rzuca błędami.

1 użytkowników online, w tym zalogowanych: 0, gości: 1