Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error in my first assembly program (GCC Inline Assembly)

After a lot of internet research I implemented a small assembler routine in my C++ program to get the CPU's L1 cache size using cpuid.

int CPUID_getL1CacheSize() {

    int l1CacheSize = -1;

    asm ( "mov $5, %%eax\n\t"   // EAX=80000005h: L1 Cache and TLB Identifiers
          "cpuid\n\t"
          "mov %%eax, %0"       // eax into l1CacheSize 
          : "=r"(l1CacheSize)   // output 
          :                     // no input
          : "%eax"              // clobbered register
         );

    return l1CacheSize;
}

It works perfectly on Windows 7 64 bit with MinGW (GCC, G++). Next I tried this on my Mac computer using GCC 4.0 and there must be an error somewhere because my program shows strange strings in the ComboBoxes and some signals cannot be connected (Qt GUI).

This is my first assembler program, I hope someone can give me a hint, Thanks!

like image 301
Linoliumz Avatar asked Jun 24 '10 20:06

Linoliumz


People also ask

Does GCC support inline assembly?

GCC provides two forms of inline asm statements. A basic asm statement is one with no operands (see Basic Asm), while an extended asm statement (see Extended Asm) includes one or more operands.

What is inline assembly code?

In computer programming, an inline assembler is a feature of some compilers that allows low-level code written in assembly language to be embedded within a program, among code that otherwise has been compiled from a higher-level language such as C or Ada.

What is inline assembly in C++?

Inline assembly (typically introduced by the asm keyword) gives the ability to embed assembly language source code within a C program.

Is inline assembly useful?

Inline assembly code can use any C variable or function name that is in scope, so it is easy to integrate it with your program's C code. Because the assembly code can be mixed inline with C or C++ statements, it can do tasks that are cumbersome or impossible in C or C++.


1 Answers

I think that CPUID actually clobbers EAX, EBX, ECX, EDX, so it's probably just a register trashing problem. The following code appears to work OK with gcc 4.0.1 and 4.2.1 on Mac OS X:

#include <stdio.h>

int CPUID_getL1CacheSize()
{
    int l1CacheSize = -1;

    asm ( "mov $5, %%eax\n\t"   // EAX=80000005h: L1 Cache and TLB Identifiers
          "cpuid\n\t"
          "mov %%eax, %0"       // eax into l1CacheSize 
          : "=r"(l1CacheSize)   // output 
          :                     // no input
          : "%eax", "%ebx", "%ecx", "%edx"  // clobbered registers
         );

    return l1CacheSize;
}

int main(void)
{
    printf("CPUID_getL1CacheSize = %d\n", CPUID_getL1CacheSize());
    return 0;
}

Note that you need to compile with -fno-pic as EBX is reserved when PIC is enabled. (Either that or you need to take steps to save and restore EBX).

$ gcc-4.0 -Wall -fno-pic cpuid2.c -o cpuid2
$ ./cpuid2 
CPUID_getL1CacheSize = 64
$ gcc-4.2 -Wall -fno-pic cpuid2.c -o cpuid2
$ ./cpuid2 
CPUID_getL1CacheSize = 64
$ 
like image 158
Paul R Avatar answered Sep 25 '22 15:09

Paul R