2013-02-09 16 views
10

Zastrzeżenie: Słowa nie mogą opisać, jak bardzo nienawidzę AT & T składniKtóry wbudowany kod zespołu jest poprawny dla rdtscp?

Mam problem, który mam nadzieję jest spowodowane rejestru przebijania. Jeśli nie, mam znacznie większy problem.

Pierwsza wersja Kiedyś był

static unsigned long long rdtscp(void) 
{ 
    unsigned int hi, lo; 
    __asm__ __volatile__("rdtscp" : "=a"(lo), "=d"(hi)); 
    return (unsigned long long)lo | ((unsigned long long)hi << 32); 
} 

zauważam, nie ma „gdyż temu” rzeczy w tej wersji. Niezależnie od tego, czy jest to problem, którego nie znam ... Przypuszczam, że zależy to od tego, czy kompilator włącza funkcję, czy nie. Używanie tej wersji powoduje problemy z odtwarzaniem , które nie zawsze są odtwarzalne..

Kolejna wersja znalazłem jest

static unsigned long long rdtscp(void) 
{ 
    unsigned long long tsc; 
    __asm__ __volatile__(
     "rdtscp;" 
     "shl $32, %%rdx;" 
     "or %%rdx, %%rax" 
     : "=a"(tsc) 
     : 
     : "%rcx", "%rdx"); 

    return tsc; 
} 

to uspokajająco nieczytelny i oficjalny wygląd, ale jak mówiłem mój problem nie zawsze jest powtarzalna, więc jestem po prostu próbuje wykluczyć jedną możliwą przyczynę mojego problem.

Powodem, dla którego I wierzę w pierwszą wersją jest problem polegający na nadpisaniu rejestru, który poprzednio posiadał parametr funkcji.

Co jest poprawne ... wersja 1 lub wersja 2, lub obie?

+7

Podziel się nienawiścią składni. Kiedy dojdę do tego punktu, szukam wewnętrznych funkcji kompilatora lub po prostu umieszczam funkcje w pliku .s i sam je montuję ... –

+0

@MichaelDorgan VC++ oferuje piękne wewnętrzne, niestety nie. – James

+8

+1 tylko dla "nie lubię składni stylu AT & T" –

Odpowiedz

18

Oto kod C++, który zwróci TSC i przechowywania pomocnicze 32-bitów do parametru odniesienia

static inline uint64_t rdtscp(uint32_t & aux) 
{ 
    uint64_t rax,rdx; 
    asm volatile ("rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : :); 
    return (rdx << 32) + rax; 
} 

Lepiej jest zrobić shift i add scalić obie połowy 32-bitowych w rachunku C++ raczej niż inline, pozwala to kompilatorowi zaplanować te instrukcje według własnego uznania.

+0

Czy to nie jest również clobber ECX? Jeśli nie, po prostu usunę swoją odpowiedź i zadzwonię do twojego dobra. –

+2

Tak, specyfikacja "= c" mówi kompilatorowi, że ECX będzie przechowywać dane wyjściowe, co oznacza, że ​​jest on clobbered – amdn

+0

Dziękuję.Pierwsza wersja nie oznaczyła 'ecx' jako clobbered. Ten rejestr początkowo posiadał wartość parametru, która została użyta w warunku, który, jeśli się nie powiodł, nazywa się 'std :: terminate()'. Kiedy to zostało zepsuło, oczywistym warunkiem było sprawdzenie niewłaściwej rzeczy! – James

1

Zgodnie z this, operacja ta zrywa EDX i ECX. Musisz zaznaczyć te rejestry jako clobbered, co jest tym, co robi drugi. BTW, czy to jest link, w którym dostałeś powyższy kod, czy znalazłeś go gdzie indziej? Pokazuje również kilka innych wariacji dla taktowania, co jest całkiem zadbane.

+0

Zła instrukcja. Jest to 'rdtscp', a nie' rdtsc', a wszelkie dane wyjściowe są znane jako clobbered, więc nie trzeba ich wymieniać. Problem polega na tym, że 'rdtscp' * również * niszczy ekx, którego wersja 2 zaznacza jako clobbered, ale wersja 1 nie. – ughoavgfhw

+0

Niech tak będzie i mamy dla niego odpowiedź. Sprzątnę to ... –

+0

Pozostawiając to tutaj dla innych linków SO, które mogą być przydatne - choć powyższa odpowiedź jest lepsza. –

2

myślę, że można bardzo bezpiecznie patrz this document, nie tylko do sprawdzania poprawności, ale także poznawanie trochę bardziej dogłębną analizę o dokładności RDTSC i RDTSCP.

Mam nadzieję, że to pomoże.

Powiązane problemy