Need some ASM/C advice

Programming, for all ages and all languages.
Post Reply
User avatar
babernat
Member
Member
Posts: 42
Joined: Tue Jul 03, 2007 6:53 am
Location: Colorado USA

Need some ASM/C advice

Post 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?
Thanks for all the fish.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post 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.
Every good solution is obvious once you've found it.
User avatar
babernat
Member
Member
Posts: 42
Joined: Tue Jul 03, 2007 6:53 am
Location: Colorado USA

Post 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?
Thanks for all the fish.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

The GCC manual is pretty good.
DeletedAccount
Member
Member
Posts: 566
Joined: Tue Jun 20, 2006 9:17 am

Hope this upload helps ...

Post by DeletedAccount »

User avatar
babernat
Member
Member
Posts: 42
Joined: Tue Jul 03, 2007 6:53 am
Location: Colorado USA

Post 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.
Thanks for all the fish.
User avatar
babernat
Member
Member
Posts: 42
Joined: Tue Jul 03, 2007 6:53 am
Location: Colorado USA

Post 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.
Thanks for all the fish.
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Post by piranha »

Plus it's copyrighted by Intel so call me paranoid, but...
Heh heh.......Paranoid!

-JL
P.S. I'm bored.
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
Post Reply