Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: bitmaster am 24. July 2006, 16:51
-
Hi,
ich versuche gerade pusha unter 64 Bit auszuführen. Das funktioniert leider nicht. Pushaq geht leider auch nicht. Das AMD64 Manual sagt das pusha eine Exception6 (ungültiger Opcode) unterm 64 Bit ausführt. Aber wieso das denn? Gibt es da einen ganz neuen Befehl für, oder wie soll ich das machen?
bitmaster
-
Ne, pusha wurde abgeschafft, weil es afaik zu viele Bytes pushen muss. (Mehr und größere Register afaik).
-
Wie stellen die sich dann das Taskswitchen vor?
-
push rax
push rbx
push rcx
...
-
Das haben die ja blöd geregeld. Soll ein push rax, push rbx, push rcx usw. schneller sein als ein pusha?
bitmaster
-
Also das wäre dann ein pusha unter 64 Bit, oder wie:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
Schwachsinnig!!!
bitmaster
-
Das ist alles genau gleich schnell.....
War glaub ich auch schon früher so?? Oder nicht???
Der einzige Vorteil war die Grösse in der Datei.
Nooooooooooooooooos
-
Ein pusha ist langsamer ist als 8 pushs. Auf einem Pentium 1 habe ich sogar Zahlen dazu: Ein pusha braucht 5 Taktzyklen, ein push einen Taktzyklus. Allerdings kann push eax etc. gepipelined werden, sodass zwei pushs in einem Takt ausgeführt werden, womit 8 pushs nur 4 Taktzyklen brauchen. (Quelle: ASM86FAQ)
(Auf einem 386er dauert ein pusha übrigens 18 Taktzyklen und ein push eax nur 2, falls da jetzt was kommt von wegen Möhmöhmöhmeinecpuistkeinpentium. Selbe Quelle.)
-
ok, ich hab mal einen Vergleich zwischen pusha/popa und push/pop gemacht.
unsigned int start;
unsigned int end;
__asm__ __volatile__("rdtsc":"=a" (start));
__asm__ __volatile__("pusha\n\tpopa");
__asm__ __volatile__("rdtsc":"=a" (end));
cout << "pusha, popa: " << dec << (end - start) << endl;
__asm__ __volatile__("rdtsc":"=a" (start));
__asm__ __volatile__( "push %eax\n\t"
"push %ecx\n\t"
"push %edx\n\t"
"push %ebx\n\t"
"push %esp\n\t"
"push %ebp\n\t"
"push %esi\n\t"
"push %edi\n\t"
"pop %edi\n\t"
"pop %esi\n\t"
"pop %ebp\n\t"
"add $4, %esp\n\t"
"pop %ebx\n\t"
"pop %edx\n\t"
"pop %ecx\n\t"
"pop %eax\n\r");
__asm__ __volatile__("rdtsc":"=a" (end));
cout << "push/pop: " << dec << (end - start) << endl;
Das Ergebnis war: 50 und 47 auf einem Pentium 3. Also hat Pork Chicken recht (hätte ich ehrlich gesagt nicht gedacht). Hab den von g++ generierten Code auch angesehen: Es werden keine unnötigen instructions (außer natürlich einem mov [...], eax, aber des is ja bei beiden so) zwischengeschoben! Zu beachten ist auch, dass bei dem normalen push/pop's eigentlich kein push/pop esp nötig ist, d.h. sie nochmal schneller sind.
btw. wieso können zwei pushs gepipelined werden? Ich mein die verändern ja beide das gleiche Register (esp)... :?:
-
wie wärs mir macros ? mach doch en macro push_reg und gut :)