Thread: Get CPU info

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    6
    Hello , I have read your post on forum and it was helpful
    however i cant understand some lines of volatile asm.
    I googled and read http://www.ibm.com/developerworks/library/l-ia.html
    However still no bulb in my head =)

    Code:
    mov %5, %%eax 
    mov %6, %%ecx 
    " mov %7, %%ebx"
    What are %5 , %6, %7 ? Cant resolve it.
    But i can sense that

    Code:
                            " mov %%eax, %1;"
                            " mov %%ebx, %2;"
                            " mov %%ecx, %3;"
                            " mov %%edx, %4;"
    %1 is *a , %2 is *b and so on so forth.

    Plus ,
    Why did u define a "keeper" named variable and used it in output operands if youre not gonna send it out of the "void cpuid" function ?

  2. #2
    Registered User
    Join Date
    Mar 2008
    Posts
    15
    Quote Originally Posted by lastsurvivor View Post
    But i can sense that

    Code:
                            " mov %%eax, %1;"
                            " mov %%ebx, %2;"
                            " mov %%ecx, %3;"
                            " mov %%edx, %4;"
    %1 is *a , %2 is *b and so on so forth.
    The inline assembly for the GCC can't work with variables directly, so you have to use %0 for the first variable you will be using, %1 for the second and so on.
    I guess that's what you already found out.
    If you have Registers you're writing the value of a value to, those are input operations. Writing the register value to a variable is a output operation.
    Since you're going to name the output variables first and the input ones after, input variable numbering will start at %0. Output variable numbering starts at the max input variable +1, so if we've got 5 input variables (max %4 since 0 counts), input variables will be named %5 and up.
    If you've got no output variables at all, input variables will start at %0 of course

    Quote Originally Posted by lastsurvivor View Post
    Plus ,
    Why did u define a "keeper" named variable and used it in output operands if youre not gonna send it out of the "void cpuid" function ?
    That "keeper" variable keeps the value of register EBX before executing the CPUID instruction and is used to write that value back after the EAX, EBX, ECX and EDX register values have been saved to *a,*b,*c and *d.
    If you modify the EBX register (or "clobber" it as it's called in assembly) and compile code with the -fpic option of GCC you'll get an error, because the EBX register is supposed to hold some pretty important data. (I think it's about memory adresses)
    Details on PIC (Position Independent Code) can be found at http://en.wikipedia.org/wiki/Position_independent_code .
    It's particularly interesting for shared libraries or making code invulnerable against some exploits because the code's memory adresses are "hidden".
    So I added this in case some guys running hardened gentoo (which uses -fpic AFAIK) try to compile this with their default CFLAGS. Dunno if it's the perfect workaround, but at least I know it works.


    If you're interested in the CPUID instruction, I can send you a small tool for Linux I'm developing that detects the CPU, the microarchitecture, codename, core stepping and has more sophisticated cache recognition than /proc/cpuinfo for multicore CPUs.

    Peter

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by pgzh View Post
    That "keeper" variable keeps the value of register EBX before executing the CPUID instruction and is used to write that value back after the EAX, EBX, ECX and EDX register values have been saved to *a,*b,*c and *d.
    If you modify the EBX register (or "clobber" it as it's called in assembly) and compile code with the -fpic option of GCC you'll get an error, because the EBX register is supposed to hold some pretty important data. (I think it's about memory adresses)
    This is all unnecessary. GCC will automatically save and restore any registers it needs to. Just make sure that EBX is listed in the clobber list or the output list.

  4. #4
    Registered User
    Join Date
    Mar 2008
    Posts
    15
    Quote Originally Posted by brewbuck View Post
    This is all unnecessary. GCC will automatically save and restore any registers it needs to. Just make sure that EBX is listed in the clobber list or the output list.
    That's strange, because I did this after a tester of my tool reported the following error compiling my program:
    Code:
    error: can't find a register in class ‘BREG’ while reloading ‘asm’
    With Google I found the following: http://sam.zoy.org/blog/2007-04-13-s...d-pic-mix-well

    So I decided to save the EBX register in my "keeper" variable and AFAIK it worked for that guy...

    My original code looks like this, maybe you can tell me if there's another culprit that could lead to the reported problem:
    Code:
    void cpuid(int *a, int *b, int *c, int *d)
    {
      __asm__ __volatile__ (" mov %4, %%eax;"
                            " mov %5, %%ecx;"
                            " cpuid;"
                            " mov %%eax, %0;"
                            " mov %%ebx, %1;"
                            " mov %%ecx, %2;"
                            " mov %%edx, %3;"
             /* Output */ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
             /* Input  */ : "a" (*a), "c" (*c) );
    }
    Peter
    Last edited by pgzh; 03-27-2008 at 12:50 PM.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by pgzh View Post
    That's strange, because I did this after a tester of my tool reported the following error compiling my program:
    Code:
    error: can't find a register in class ‘BREG’ while reloading ‘asm’
    That's the code generator in GCC puking out. Try fiddling with the optimization settings. It's a bug in GCC. If you're hitting it, then you should probably save and restore EBX manually, like you're doing now. I hope they fix it -- it happens with other register classes sometimes, too.

    The cheap solution, though, is to just "pusha" at the beginning and "popa" at the end. I doubt efficiency really matters in this function.

    EDIT: I'd actually rewrite that asm to look like this:

    Code:
    __asm__ __volatile__ ("cpuid"
      : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
      : "a" (*a), "c" (*c)
      : "ebx" );
    That might work better, no guarantee..
    Last edited by brewbuck; 03-27-2008 at 01:01 PM.

  6. #6
    Nub SWE
    Join Date
    Mar 2008
    Location
    Dallas, TX
    Posts
    133
    Code:
             /* Output */ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
             /* Input  */ : "a" (*a), "c" (*c) );
    I'm not -too- familiar with assembly code or what you're doing here, but it looks like you use r for the first time here, instead of b. All of the other variables seem to correspond to the pointer of the same name. I highlighted it in red above.

    In case I wasn't clear, I'm fully aware I'm possibly being an idiot here. Just wanted to make sure you knew this was there and that it was supposed to be that way.

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by JDGATX View Post
    Code:
             /* Output */ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
             /* Input  */ : "a" (*a), "c" (*c) );
    I'm not -too- familiar with assembly code or what you're doing here, but it looks like you use r for the first time here, instead of b. All of the other variables seem to correspond to the pointer of the same name. I highlighted it in red above.

    In case I wasn't clear, I'm fully aware I'm possibly being an idiot here. Just wanted to make sure you knew this was there and that it was supposed to be that way.
    It's basically telling the compiler, "use the register indicated by asm param %1", in this case, the param of line " mov %%ebx, %1;" In other words, load %ebx into any available register.

  8. #8
    Nub SWE
    Join Date
    Mar 2008
    Location
    Dallas, TX
    Posts
    133
    Ah, alright! Makes sense.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. questions on multiple thread programming
    By lehe in forum C Programming
    Replies: 11
    Last Post: 03-27-2009, 07:44 AM
  2. Upgrading my old CPU (for another old one!)
    By foxman in forum Tech Board
    Replies: 16
    Last Post: 01-11-2008, 05:41 PM
  3. Can you still view the bios screen with a bad CPU?
    By HyperCreep in forum Tech Board
    Replies: 4
    Last Post: 12-31-2006, 06:57 PM
  4. Question about getting an info class from another Form
    By Joelito in forum C# Programming
    Replies: 0
    Last Post: 10-16-2006, 01:02 PM
  5. Help doing an e-mail program in c...
    By Tyler_Durden in forum C Programming
    Replies: 88
    Last Post: 01-02-2005, 03:12 PM