inline ASM problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
stonedzealot

inline ASM problem

Post by stonedzealot »

In accordance with my last topic (RAM/CPU info) I started to try and implement CPU detection. I created this inline ASM function:

Code: Select all


void getcpufamily()
{

   char VendorSign[13];
   unsigned long MaxEAX;
   printmessage("START", 10, 10, 0x02);

   __asm__ __volatile__(  //<--LINE 52
      "movl 0,%%EAX\n"
      "cpuid\n"
      "movl %%EBX, %0\n"
      "movl %%EDX,4(%0)\n"
      "movl %%ECX,8(%0)\n"
      "movl %%EAX,%1"
      : "=g" (VendorSign)
      );
   VendorSign[12] = 0;
   printmessage("END", 10, 11, 0x02);
   printmessage(VendorSign, 0, 2, 0x02);
}

I don't think it's the code, but I thought I should give some background. Anway, GCC gives the error:

io.c:52: invalid `asm' : operand number out of range.

What is that?! I have no clue. I marked the line it says it's giving the error on in the code. Can someone help me out?
richie

Re:inline ASM problem

Post by richie »

I'm not very familiar with the AT&T syntax but I think the mistake is one line later. 0 is a constant value and I think in the AT&T syntax you have to use a Dollarsign before each constant. Try if this code works:

Code: Select all

void getcpufamily()
{

   char VendorSign[13];
   unsigned long MaxEAX;
   printmessage("START", 10, 10, 0x02);

   __asm__ __volatile__( 
      "movl $0,%%EAX\n"
      "cpuid\n"
      "movl %%EBX, %0\n"
      "movl %%EDX,4(%0)\n"
      "movl %%ECX,8(%0)\n"
      "movl %%EAX,%1"
      : "=g" (VendorSign)
      );
   VendorSign[12] = 0;
   printmessage("END", 10, 11, 0x02);
   printmessage(VendorSign, 0, 2, 0x02);
}
But as I already has said: I don't know very much about AT&T. But testing this is better than doing nothing.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:inline ASM problem

Post by Pype.Clicker »

the problem comes from your %1 command: you're asking gcc the second argument but you only provide one (%0)
stonedzealot

Re:inline ASM problem

Post by stonedzealot »

D'OH! OH man, I can't believe that. Agh, as I've mentioned before, sometimes I miss the obvious stuff.

btw, it should be 4%0 and 8%0 not 4(%0) and 8(%0)
I guess it's different from AT&T
Scalpel

Re:inline ASM problem

Post by Scalpel »

I tried your code here, with %1 changed to %0, and with the 4%0 and 8%0 corrections, but when I print the string I get just one ASCII character out. It was the white smileyface at position 0,1 in this chart

I tried it in both Bochs and on my Pentium III 1GHz, but the same output. Did you get it to work properly?
stonedzealot

Re:inline ASM problem

Post by stonedzealot »

Well, I got the inline ASM problem worked out as above, but the CPUID code I had I dropped because I needed to go back and gain a better understanding of what was being done earlier in my kernel. Therefore I sorta scrapped and am rebuliding the kernel. I can, however, give you a nice place for the CPUID function....

http://osdev.berlios.de/cpuid.html
Quite a nice place, I think.
surya4friends

Re:inline ASM problem

Post by surya4friends »

Well this should be code!

#include <stdio.h>

void DetectCPUFamily()
{
char strCompany[13];
unsigned long MaxEAX;
   __asm__ __volatile__(
    "cld\n\t"
    "cpuid\n\t"
    "movl %%EBX,%0\n\t"
    "movl %%EDX,4%0\n\t"
    "movl %%ECX,8%0\n\t"
    "movl %%EAX,%1\n\t"
    : "=g"(strCompany)
    : "a" (0)
    );
strCompany[12] = 0;
printf(strCompany);
}

int main(void)
{
printf("CPU Family detector v0.0.1\n\nCPU Type:\t");
DetectCPUFamily();
}

To compile:
gcc -c FILENAME.C

Link and make exe:
gcc -o EXENAME FILENAME.O

About putting 1 in %eax, or 2, as intial value, here is what intel maual 2 says,

Initial Information Provided about the Processor
EAX
Value
0    EAX-Maximum CPUID Input Value (2 for the P6
family processors and 1 for the Pentium ?
processor and the later versions of Intel486?
processor that support the CPUID instruction).
   EBX-"Genu"
   ECX-"ntel"
   EDX-"ineI"

1   EAX- Version Information (Type, Family, Model, and
Stepping ID)
   EBX- Reserved
   ECX- Reserved
   EDX- Feature Information

2   EAX- Cache and TLB Information
   EBX- Cache and TLB Information
   ECX- Cache and TLB Information
   EDX- Cache and TLB Information

See pg 3-111 ( as per Acrobat viewer - Page 151) of Intel Architecture Software Developer?s Manual Volume 2:Instruction Set Reference.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:inline ASM problem

Post by Pype.Clicker »

there's something that seems weird in the manner you give the access to VendorString, imho. i would rather try

Code: Select all

asm(..."mov %%ebx,$0; mov %%ecx,$1; mov %%edx,$2":   "=g"(VendorString),"=g"(VendorString+4),"=g"(VendorString+8)
BTW, use objdump -d or ndisasm to check the generated code is the one you wish.

another option would be

Code: Select all

asm("cpuid":"=a"(max_eax),"=b"(VendorString),
"=c"(VendorString+4),"=d"(VendorString+8):"0"(0))
Scalpel

Re:inline ASM problem

Post by Scalpel »

Code: Select all

void getcpufamily()
{
        char VendorString[13];
        unsigned long MaxEAX;
        sprintf("\ngetcpufamily start",0);

        __asm__ __volatile__ (
                "cld\n"
                "cpuid\n"
                "movl %%ebx, $1\n"
                "movl %%edx, $2\n"
                "movl %%ecx, $3\n"
                "movl %%eax,%0"
                : "=g" (VendorString), "=g"(VendorString+4),"=g"(VendorString+8)
                );
        VendorString[12]=0;
        sprintf("\ngetcpufamily end. String is: ",0);
        sprintf(VendorString,0);
}
I tried this code, but get the error 'invalid lvalue in assignment'.
surya4friends

Re:inline ASM problem

Post by surya4friends »

Hey Pype.Clicker,

Thanks for suggestion for using objdump / ndiasmw. Never came to my mind.

Well other than that my question is can I use NASM for Windows for OS developement? or should I use DJGPP ? I am using DJGPP GCC for OS. is there any clear and distinct advantage for choosing one over another? any links or pointers welcome!
Thanks!

BTW, code you mentioned give compile time error to me too!
Jonathan

Re:inline ASM problem

Post by Jonathan »

Hmm I didn't get the first code to compile either so I made som small changes to it. This works with gcc >3.x.

Code: Select all

#include <stdio.h>

void DetectCPUFamily()
{
   char strCompany[13];
   /*unsigned long MaxEAX;*/
   asm volatile(
     "cld\n\t"
     "cpuid\n\t"
     "movl %%EBX,%0\n\t"
     "movl %%EDX,4%0\n\t"
     "movl %%ECX,8%0\n\t"
     "movl %%EAX,%1\n\t"
     : "=g"(strCompany)
     : "a" (0)
     );
  strCompany[12] = 0;
  printf(strCompany);
}

int main(void)
{
   printf("CPU Family detector v0.0.1\n\nCPU Type:\t");
   DetectCPUFamily();
   
   return 0;
}
Post Reply