Page 1 of 1

Need some ASM/C advice

Posted: Thu Feb 07, 2008 11:09 pm
by babernat
For some reason I decided it would be neat to write a little library on my own that would simplify access to CPUID provided by Intel. I started looking at the Intel documentation which included both assembly and C code.

In the document Intel provides some assembly examples on how to do this. Long story short, after some frustration I gave up on the hopes of assembling the code. Plus it's copyrighted by Intel so call me paranoid, but...

Which brought me to my question. I have some options here. The first is to write the helper functions in assembly, write a C header file that prototypes the functions and then just assemble the files then link them together with C code. If I was smart, I could do most of the tedious processing in C and only use the assembly portions where required. Which lead me to my second option, why not use inline assembly in my C code to begin with. Is this simply a question of style?

What are you all's thoughts. Am I completely wasting my time?

Posted: Thu Feb 07, 2008 11:50 pm
by 01000101
hi, I've written a CPUID library in C with inline asm. I didn't run into many issues at all, and (because I'm more familiar with C) found it to not be all that hard either.

I made an array of known CPU properties (sse, mmx, etc..) and enumerated them that way.

It's completely up to you and what you feel comfortable doing though, if you are better at ASM, Id suggest doing it in ASM, if you're better in C, do it in C, just make sure you know the proper __asm(""); format and to clobber what needs to be destroyed in the end.

Posted: Fri Feb 08, 2008 1:17 am
by Solar
Mostly a matter of style, yes. Inline assembly makes your code compiler-specific, as there is no standard way to do it. So splitting it up into a C file and a ASM file seems "cleaner" to some (me included). But since ASM code is assembler-specific anyhow, it's in the eye of the beholder.

Posted: Fri Feb 08, 2008 7:03 am
by babernat
@01000101: That sounds exactly like what I want to do. Thanks for the advice. Can you recommend a good resource for explaining inline assembly in gcc?

Posted: Fri Feb 08, 2008 7:04 am
by JamesM
The GCC manual is pretty good.

Hope this upload helps ...

Posted: Fri Feb 08, 2008 11:53 am
by DeletedAccount

Posted: Fri Feb 08, 2008 10:42 pm
by babernat
Thanks for the input everyone. I played around with the approach of using inline assembly. Here's what I wrote.

Code: Select all

#include <stdio.h>

int main(void)
{
        int foo = 0;

        __asm__ __volatile__(
                        "movl $0x00,%%eax\n\t"                  /* load 00h into eas */ \
                        "cpuid\n\t"                             /* execute cpuid */ \
                        :"=a"(foo)                              /* output to foo */
                        :                                       /* no input registers */

                        );

        printf("result: %d\n",foo);
        return 0;
}
The code compiles, but when executing I get a segmentation fault (wonderful). I started up gdb and found it was coming from __vfprintf. So I commented out printf and it ran fine. Well, I assume it ran fine because obviously I got no output to the screen. My current path of thinking leads me to believe that printf is using eax. So then I tried to add eax to the clobber list thinking that would do the trick. When I do that, I can't get the dang thing to compile! Here's what I had:

Code: Select all

#include <stdio.h>

int main(void)
{
        int foo = 0;

        __asm__ __volatile__(
                        "movl $0x00,%%eax\n\t"                  /* load 00h into eas */ \
                        "cpuid\n\t"                             /* execute cpuid */ \
                        :"=a"(foo)                              /* output to foo */
                        :                                       /* no input registers */
                        :"%%eax"                                /* clobber the stinker */
                        );

        printf("result: %d\n",foo);
        return 0;
}
My gcc error says:
2.c: In function ‘main’:
2.c:7: error: unknown register name ‘%%eax’ in ‘asm’
Any help/comments would be appreciated.
Thanks.

Posted: Fri Feb 08, 2008 11:34 pm
by babernat
After some more exploring, I think I got it.

Code: Select all

#include <stdio.h>

int main(void)
{
        int a,b,c,d;

        asm(
                        "pushl %%ebx\n\t"                       /* need to store off ebx */\
                        "movl $0x00,%%eax\n\t"                  /* load 00h into eas */ \
                        "cpuid\n\t"                             /* execute cpuid */ \
                        "movl %%ebx, %%esi\n\t"                 /* move ebx value to another register */\
                        "popl %%ebx\n"                          /* restore the ebx value */
                        :"=a"(a),"=S"(b),"=c"(c),"=d"(d)        /* output */
                        :                                       /* no input registers */
                        );

        printf("a: %d, b: %d, c: %d, d: %d\n",a,b,c,d);
        return 0;
}
After a brief moment of clarity, I remembered CPUID outputs to eax, ebx, ecx, and edx. So I named those as outputs. Then I had the problem of ebx can't be jacked with. Something about PIC or whatever. So I added some code to push the value of ebx onto the stack and then call CPUID, save the resulting ebx to a different register then restore the original ebx value from the stack.

There are finally some values in my variables. Need to make sure they're what I expected, though.

Posted: Fri Feb 08, 2008 11:55 pm
by piranha
Plus it's copyrighted by Intel so call me paranoid, but...
Heh heh.......Paranoid!

-JL
P.S. I'm bored.