NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: mark allyn on August 04, 2009, 02:39:20 AM
-
Hello everyone:
I'm new to this forum and I apologize if I am asking inappropriate question.
I am trying to use the CPUID instruction to determine the clock speed of a processor. I don't know which value to place in eax to get this info. I also don't know how to interpret the results. If someone could kindly give me some guidance, I would be most grateful.
Mark Allyn
-
Hi Mark,
I don't think we can get the actual clock speed with cpuid. Cpuid will return a "processor name string" (not the same as the "vendor string" returned by cpuid with eax=0), which includes the nominal "maximum supported speed" (I just now learned this - I often get educated trying to "help" you guys!).
Naturally, Intel has a document... in "painful document format" :(
http://www.intel.com/Assets/PDF/appnote/241618.pdf (http://www.intel.com/Assets/PDF/appnote/241618.pdf)
This includes example programs (for dos, and in Masm syntax) for both the "name string" and for calculating the actual current frequency.
The latter uses the "tick count" in the Bios Data Area to get an "interval" to count over, reading rdtsc before and after (and doing the division in an odd way...). On a less archaic OS, "interval" may actually be more of a problem. Linux, for example, has "sys_nanosleep" which should give us an interval - wait a full second to simplify the arithmetic? - but I think it'll give us a second... plus whenever the scheduler decides to give us the CPU back. Maybe "close enough"? You would use cpuid to make sure that rdtsc exists, after making sure that cpuid exists, if you're being paranoid. (better to be a little too paranoid than not quite paranoid enough!)
I'll append a quick-and-dirty example for "name string". The display is horrible, but it shows the useage of cpuid okay, I guess. Whether this will help you, and how accurate an interval you need if you're going to "count", depends on "why do you want to know?", probably...
Best,
Frank
; nasm -f elf cpuname.asm
; ld -o cpuname cpuname.o
;
; change the display and exit parts for 'doze
global _start
section .bss
namestring resb 48
section .text
_start:
mov eax, 80000000h
cpuid
cmp eax, 80000004h
jb exit ; not supported
mov edi, namestring ; need 48 bytes to store it
mov eax, 80000002h
cpuid
call savestring
mov eax, 80000003h
cpuid
call savestring
mov eax, 80000004h
cpuid
call savestring
; print it
mov ecx, namestring
mov edx, 48
mov ebx, 1 ; stdout
mov eax, 4 ; write
int 80h
exit:
mov eax, 1
int 80h
;----------------
;--------------------
savestring:
stosd
mov eax, ebx
stosd
mov eax, ecx
stosd
mov eax, edx
stosd
ret
;------------------
-
Thanks, Frank for the help on this. I had looked over Ch. 9 of the INTEL document and had two thoughts: 1. It can't be this complicated. 2. Why would they make it this complicated. Obviously, from what you have done, it is indeed just that complicated, but why? It is such an obvious piece of info that folks would want, why bury it.
Anyway, thank you for helping out on this. I appreciate the effort you put in.
Regards,
Mark Allyn
-
Hello Frank -
One more thought on the issue of clocks. I went back and looked again at the Intel CPUID doc. This time I went and looked at the code sample that shows up right at the end. What I'm not clear on is whether this code will or won't run on my Wintel box. I'm unclear because of what is written in Chapter 9 of the document. There is an early reference to Ring 0 access and the need for it. How do I determine Ring 0 access status and how do I change it, if it can be? Do I even care...the code sample doesn't make it obvious that it is required for it to assemble and run.
Thanks,
Mark Allyn