rdtsc funktion mit gcc
-
hola leute
hab mir ne rdtsc funktion fuer den gcc gebastelt. leider kommen zwischen durch bei der messung negative zahlen vor. bei ner dauer von < 0.5 sek
hier der code
long long int rdtsc(void) { unsigned long value1=0,value2=0; __asm__ __volatile__("rdtsc":"=a"(value1),"=d"(value2)); long long int result = value1 + (value2 << 16); return result; }
hab ich mehr oder weniger von kingruedi aus nem cpu-frequenzmessungsthread entwendet. sieht jemand den fehler ? und kann mir jemand sagen wofuer das =a und =d ist?
cermy
Meep Meep
-
<< 16 ? sicher nicht
die kanonische form geht so
unsigned long long rdtsc() { unsigned long long result; asm volatile("rdtsc":"=A"(result)); return result; }
die =a,d,A sagen dem compiler, in welchem register die entsprechenden variablen zu finden sind.
-
Das <<16 allein erklärt aber noch nicht die negativen Werte. Die werden erst klar, wenn man sieht, dass zuerst der Shift und die Addition mit longs passiert und erst nachher auf long long aufgeblasen wird.
-
Ringding schrieb:
Das <<16 allein erklärt aber noch nicht die negativen Werte. Die werden erst klar, wenn man sieht, dass zuerst der Shift und die Addition mit longs passiert und erst nachher auf long long aufgeblasen wird.
beides kann für negative werte verantworlich sein. wenn von zwei messpunkten einer unmittelbar vor einem übertrag in die oberen 32bit und einer unmittelbar danach erfolgt, dann is die differenz negativ:
zeitpunkt eins: 0x00000000:0xffffffff ---> mit << 16 ergibt 0x00000000ffffffff
zeitpunkt zwei: 0x00000001:0x00000000 ---> ergibt 0x0000000000010000
-
Da das Argument des Shift-Operators, "16", vorzeichenbehaftet ist (Alternative: "16U"), wird eine Konvertierung zuerst nach "long int" (no-op, da meist "int" == "long int" auf 32-Bit-Maschinen) durchgefuehrt. Da "long int" und "unsigned long int" den gleichen Rang haben, darf der Compiler entscheiden, ob er das Ergebnis des Shifts nach "long int" oder "unsigned long int" aufloest. Offensichtlich wurde daraus "long int". Bei der Addition mit "unsigned long int" geschieht dasselbe: Ergebnis "long int". Bloss weil "16" statt "16U" geschrieben wurde. Korrekt haette es sogar "16UL" lauten muessen, im Hinblick auf das gewuenschte Ergebnis "32ULL", da ja sicher keine negativen Ergebnisse gewuenscht waren.
unsigned long long int result = value1 | ( value2 << 32ULL );
(Ich habe hier auch "+" durch "|" ersetzt, da eine OR-Verknuepfung wohl passender als eine Addition ist)