Det gøre den i asembler kode der stå imellem asm og end, men det er forlænge siden at jeg har lavet assembler programmering til at kommen med en pracis forklaring på koden
JEg må formode det er Assembler delen der volder problemer ?
i Delphi kan man lave inline assembler, hvilket betyder man kan lave en del af din Delphi kode i Assembler. Grunden til at man måtte ønske dette, kan være at man fx ønsker extrem performance, eller ønsker direkte adgang til hardwaren CPU'en fx.
I Pentium CPU'en og frem (Cyrix undtaget) efter er der et 64 bits register der indeholder antallet af clock cykler der er exekveret i CPU'en siden den blev tænt. Det bliver ganske hurtigt et voldsomt tal.
Inline assembler i Delphi kan kun håndtere 386 instruktioner. Det giver et lille problem fordi man skal bruge en instruktion fra Pentium Assembler til at tilgå dette register. In struktionen hedder RDTSC. FOr at kalde denne snyder man Delphis compiler ved oplat at kalde den fra sin opcode : $0F31. Derfor skriver man dw 0f31h. h for Hex.
RDTSC retunerer dig dette tal nede fra registere, hvor den ligger den høje del i edx, og resten i ecx. De værdier bliver så kopierte over i TimerLow og TimerHi (mov TimerLow, eax). mov for MOVE !
Resten er simpel matematik, omkring beregning af hastighed ud fra aftsand og tid. man holder en pause Sleep(TimeOfDelay);, og spørger efter tallet igen. så skal lotrdet blot trækkes fra hinanden :
sub eax, TimerLow og sub edx, TimerHigh
Så nu har du afstanden, målt i clock cykler, og du har tiden i ms : TimeOfDelay så er det blot at beregne .
Jeg vil gerne benytte lejligheden til at pointere en faktuel fej i koden :
sub edx, TimerHigh BURDE være sbb edx, TimerHigh, fordi sub i modsætning til sbb ikke tager højde for en eventuel mente, når man trækker fra ! Og den tester slet ikke om man overhoved kan kalde den funktion, hvliket ikke kan lade sig gøre på ældere CPU'er samt Cyris processorer !
Så brug den her i stedet for :
Function GetCpuSpeed : Extended;
Function IsCPUID_Available : Boolean;assembler;register; asm PUSHFD {direct access to flags no possible, only via stack} POP EAX {flags to EAX} MOV EDX,EAX {save current flags} XOR EAX,$200000 {not ID bit} PUSH EAX {onto stack} POPFD {from stack to flags, with not ID bit} PUSHFD {back to stack} POP EAX {get back to EAX} XOR EAX,EDX {check if ID bit affected} JZ @exit {no, CPUID not availavle} MOV AL,True {Result=True} @exit: end;
const Delay = 500;
var TimerHi, TimerLo: Integer; PriorityClass, Priority: Integer; begin Result:=0; if not IsCPUID_Available then Exit; PriorityClass := GetPriorityClass(GetCurrentProcess); Priority := GetThreadPriority(GetCurrentThread);
asm db $0F db $31 { $0F31 op-code for RDTSC pentiun instruction returns a 64 Bit Integer} mov TimerLo, eax mov TimerHi, edx end;
SleepEx(Delay , FALSE);
asm db $0F db $31 { $0F31 op-code for RDTSC pentiun instruction returns a 64 Bit Integer} sub eax, TimerLo sbb edx, TimerHi mov TimerLo, eax mov TimerHi, edx end;
function IsCPUID_Available: Boolean; assembler; register; asm PUSHFD {direct access to flags not possible, only via stack} POP EAX {flags to EAX} MOV EDX,EAX {save current flags} XOR EAX,$200000 {not ID bit} PUSH EAX {onto stack} POPFD {from stack to flags, with not ID bit} PUSHFD {back to stack} POP EAX {get back to EAX} XOR EAX,EDX {check if ID bit affected} JZ @exit {no, CPUID not availavle} MOV AL,True {Result=True} @exit: end;
const Delay = 500;
var TimerHi, TimerLo: Integer; PriorityClass, Priority: Integer; begin Result := 0; if not IsCPUID_Available then exit;
db $0F db $31 { $0F31 opcode for RDTSC pentiun instruction returns a 64 Bit Integer} sub eax, TimerLo sbb edx, TimerHi mov TimerLo, eax mov TimerHi, edx
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.