Why can’t local variable be used in GNU C basic inline asm statements?

You can use local variables in extended assembly, but you need to tell the extended assembly construct about them. Consider:

#include <stdio.h>


int main (void)
{
    int data1 = 10;
    int data2 = 20;
    int result;

    __asm__(
        "   movl    %[mydata1], %[myresult]\n"
        "   imull   %[mydata2], %[myresult]\n"
        : [myresult] "=&r" (result)
        : [mydata1] "r" (data1), [mydata2] "r" (data2));

    printf("The result is %d\n",result);

    return 0;
}

In this [myresult] "=&r" (result) says to select a register (r) that will be used as an output (=) value for the lvalue result, and that register will be referred to in the assembly as %[myresult] and must be different from the input registers (&). (You can use the same text in both places, result instead of myresult; I just made it different for illustration.)

Similarly [mydata1] "r" (data1) says to put the value of expression data1 into a register, and it will be referred to in the assembly as %[mydata1].

I modified the code in the assembly so that it only modifies the output register. Your original code modifies %ecx but does not tell the compiler it is doing that. You could have told the compiler that by putting "ecx" after a third :, which is where the list of “clobbered” registers goes. However, since my code lets the compiler assign a register, I would not have a specific register to list in the clobbered register. There may be a way to tell the compiler that one of the input registers will be modified but is not needed for output, but I do not know. (Documentation is here.) For this task, a better solution is to tell the compiler to use the same register for one of the inputs as the output:

    __asm__(
        "   imull   %[mydata1], %[myresult]\n"
        : [myresult] "=r" (result)
        : [mydata1] "r" (data1), [mydata2] "0" (data2));

In this, the 0 with data2 says to make it the same as operand 0. The operands are numbered in the order they appear, starting with 0 for the first output operand and continuing into the input operands. So, when the assembly code starts, %[myresult] will refer to some register that the value of data2 has been placed in, and the compiler will expect the new value of result to be in that register when the assembly is done.

When doing this, you have to match the constraint with how a thing will be used in assembly. For the r constraint, the compiler supplies some text that can be used in assembly language where a general processor register is accepted. Others include m for a memory reference, and i for an immediate operand.

Leave a Comment