C Code Examples: In-line Assembly

This topic was published by and viewed 627 times since "". The last page revision was "".

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #3862
    DevynCJohnson
    DevynCJohnson
    Keymaster
    • Topics - 439
    • @devyncjohnson

    In-lining Assembly into C code allows developers to incorporate faster and/or low-level code into their C programs.

    The following in-line x86 Assembly code is supported by GNU-GCC and Clang. Other compilers may not support the given code.

    Get CPU Vendor ID

    const char *get_vendor_id(void) {
        // Return the vendor ID of the x86 CPU (Assumes little-endian)
        int ebx, edx, ecx;
        __asm__ (
            "movl $0,%%eax;"
            "cpuid;"
            "movl %%ecx,%0;"
            "movl %%edx,%1;"
            "movl %%ebx,%2;"
            : "=r" ( ebx ), "=r" ( edx ), "=r" ( ecx )  // Output C variable
            :  // No input variables
            : "ebx", "edx", "ecx"  // Clobbered Register
        );
        static char vendor[16];
        vendor[13] = '\0';
        vendor[12] = '\0';
        vendor[11] = (char)((ebx >> 24) & 0xFF);
        vendor[10] = (char)((ebx >> 16) & 0xFF);
        vendor[9] = (char)((ebx >> 8) & 0xFF);
        vendor[8] = (char)(ebx & 0xFF);
        vendor[7] = (char)((edx >> 24) & 0xFF);
        vendor[6] = (char)((edx >> 16) & 0xFF);
        vendor[5] = (char)((edx >> 8) & 0xFF);
        vendor[4] = (char)(edx & 0xFF);
        vendor[3] = (char)((ecx >> 24) & 0xFF);
        vendor[2] = (char)((ecx >> 16) & 0xFF);
        vendor[1] = (char)((ecx >> 8) & 0xFF);
        vendor[0] = (char)(ecx & 0xFF);
        return vendor;
    }

    Get CPU Stepping

    signed int get_cpu_stepping(void) {
        // Get the stepping value of the CPU
        register signed int stepping;
        __asm__ (
            "movl $0x01,%%eax;"
            "cpuid;"
            "andl $0b00000000000000000000000000001111,%%eax;"
            "movl %%eax,%0;"
            : "=r" ( stepping )  // Output C variable
        );
        return stepping;
    }

    Test if the x86 CPU has a FPU

    int is_fpu_aval(void) {
        // Test if the CPU supports `fpu`
        register int truth;
        __asm__ (
            "movl $0x01,%%eax;"
            "cpuid;"
            "andl $0b00000000000000000000000000000001,%%edx;"
            "movl %%edx,%0;"
            : "=r" ( truth )  // Output C variable
        );
        return truth;
    }

    Test if the CPU supports PSE

    int is_pse_aval(void) {
        // Test if the CPU supports `pse` (Page Size Extension)
        register int truth;
        __asm__ (
            "movl $0x01,%%eax;"
            "cpuid;"
            "andl $0b00000000000000000000000000001000,%%edx;"
            "sarl $3,%%edx;"
            "movl %%edx,%0;"
            : "=r" ( truth )  // Output C variable
        );
        return truth;
    }

    Test if the CPU Supports CMOV

    int is_cmov_aval(void) {
        // Test if the CPU supports `cmov` (Conditional move and FCMOV instructions)
        register int truth;
        __asm__ (
            "movl $0x01,%%eax;"
            "cpuid;"
            "andl $0b00000000000000001000000000000000,%%edx;"
            "sarl $15,%%edx;"
            "movl %%edx,%0;"
            : "=r" ( truth )  // Output C variable
        );
        return truth;
    }

    Test if the CPU Supports SSE3

    int is_sse3_aval(void) {
        // Test if the CPU supports `sse3` (Prescott New Instructions-SSE3 (PNI))
        register int truth;
        __asm__ (
            "movl $0x01,%%eax;"
            "cpuid;"
            "andl $0b00000000000000000000000000000001,%%edx;"
            "movl %%edx,%0;"
            : "=r" ( truth )  // Output C variable
        );
        return truth;
    }

    Get a Random Number from RDRAND

    #ifdef __BMI2__
    ulint rdrnd(void) {
        // Get a random number from the rdrand assembly instruction
        if ((is_rdrnd_aval()) == 0) return (ulint)0;
        register ulint rand_num;
        __asm__ volatile ( "rdrand %0;" : "=r" ( rand_num ) );
        return rand_num;
    }
    #endif

    Further Reading

Viewing 1 post (of 1 total)