2013-02-09 3 views
10

Haftungsausschluss: Worte können nicht beschreiben, wie sehr ich verabscheue AT & T Stil SyntaxWelcher Inline-Assemblercode ist für rdtscp korrekt?

Ich habe ein Problem, das ich hoffe, wird durch Register Clobbering verursacht. Wenn nicht, habe ich ein viel größeres Problem.

Die erste Version war ich verwendet

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); 
} 

ich es bemerkt, ist kein Material in dieser Version 'Verfälschungs'. Ob dies ein Problem ist oder nicht, weiß ich nicht ... Ich nehme an, es kommt darauf an, ob der Compiler die Funktion einreiht oder nicht. Die Verwendung dieser Version verursacht Probleme , die nicht immer reproduzierbar sind.

Die nächste Version, die ich gefunden ist

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; 
} 

Dieses beschwichtigend unlesbar ist und offiziell aussehende, aber wie ich schon sagte, mein Problem ist nicht immer reproduzierbar, so bin ich nur versucht, auf eine mögliche Ursache auszuschließen meine Problem.

Der Grund, warum ich glaube die erste Version ist ein Problem ist, dass es ein Register überschreibt, das zuvor einen Funktionsparameter enthielt.

Was ist korrekt ... Version 1 oder Version 2 oder beides?

+7

Teilen Sie Ihren Hass der Syntax. Wenn ich an diesen Punkt komme, suche ich nach intrinsischen Funktionen des Compilers oder platziere einfach die Funktionen in einer .s-Datei und stelle sie selbst zusammen ... –

+0

@MichaelDorgan VC++ bietet eine schöne intrinsische, gcc leider nicht. – James

+8

+1 nur für 'AT & T-Stil-Syntax zu verachten' –

Antwort

18

Hier ist C++ Code, der die TSC und speichern die Hilfs 32-Bits in den Referenzparameter

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; 
} 

Es ist besser zu tun, um die shift und add zu verschmelzen sowohl 32-Bit-Hälften in C++ eher Aussage zurückkehren als Inline erlaubt dies dem Compiler, diese Anweisungen nach eigenem Ermessen zu planen.

+0

Macht das nicht auch ECX Clobber? Wenn nicht, lösche ich einfach meine Antwort und rufe dich an. –

+2

Ja, die "= c" Spezifikation teilt dem Compiler mit, dass ECX die Ausgabe halten wird, was bedeutet, dass es plump ist – amdn

+0

Vielen Dank.In der ersten Version wurde "ecx" nicht als verfälscht markiert. Dieses Register enthielt initial einen Parameterwert, der in einer Bedingung verwendet wurde, die, falls fehlgeschlagen, 'std :: terminate()' genannt wurde. Als das geplättet wurde, war der Zustand offensichtlich das falsche Ding! – James

1

Nach this, diese Operation Clobbers EDX und ECX. Sie müssen diese Register als geblockt markieren, was der zweite tut. BTW, ist das der Link, wo Sie den obigen Code bekommen haben oder haben Sie ihn woanders gefunden? Es zeigt auch ein paar andere Variationen für Timings als auch, die ziemlich ordentlich ist.

+0

Falsche Anweisung. Es ist 'rdtscp', nicht' rdtsc', und jede Ausgabe ist bekannt dafür, dass sie verfälscht ist, so dass sie nicht aufgelistet werden muss. Das Problem ist, dass 'rdtscp' * auch * ecx zerstört, was Version 2 als verfälscht markiert, aber Version 1 nicht. – ughoavgfhw

+0

Also sei es und wir haben eine Antwort für ihn. Ich werde es aufräumen ... –

+0

Das hier für die andere SO-Link verlassen, die nützlich sein kann - obwohl die obige Antwort besser ist. –

2

Ich glaube, Sie sehr sicher this document beziehen, nicht nur zu bestätigen, sondern auch ein wenig mehr in die Tiefe gehende Analyse über die Genauigkeit der RDTSC und RDTSCP kennen zu lernen.

Ich hoffe, das hilft.