c++ – How to do correct assembly insertion

Question:

I want to practice with assembler inserts. I wanted to write a code to calculate the sum of numbers from 1 to n, implementing it in assembler. However, so far I have not been able to compile even a simple code that writes the value n to sum. Here is the code:

#include <stdio.h>
int sumN(int n)
{
    // calculate 1+2+...+n
    int sum;
    __asm__(
        "mov %1, %eax\n\t"
        "mov %eax, %0\n\t"
        :"=d"(sum)
        :"c"(n)
        :"%eax");
    return sum;
}
int main()
{
    for (int i = 1; i < 100; ++i)
    {
        printf("n: %d sum(n): %d\n",i,sumN(i) );
    }
    return 0;
}

However, the g ++ compiler throws an error

main.cpp: 11: 11: error: invalid 'asm': operand number missing after% -letter: "% eax");
^
main.cpp: 11: 11: error: invalid 'asm': operand number missing after% -letter.

I thought that the problem was that I did not specify all the registers that I use, so I rewrote the code a little:

#include <stdio.h>
int sumN(int n)
{
    // calculate 1+2+...+n
    int sum;
    __asm__(
        "mov %1, %eax\n\t"
        "mov %eax, %0\n\t"
        :"=d"(sum)
        :"c"(n)
        :"%eax","%edx","%ecx");
    return sum;
}
int main()
{
    for (int i = 1; i < 100; ++i)
    {
        printf("n: %d sum(n): %d\n",i,sumN(i) );
    }
    return 0;
}

However, this code does not compile either, gcc gives an error

main.cpp: 11: 25: error: 'asm' operand has impossible constraints
: "% eax", "% edx", "% ecx");

Tell me what is the error and how to fix it? PS was guided by this article

Answer:

In the assembly code itself, the % sign must be escaped, i.e. write %%eax , but in a clobber list, on the contrary, the % sign is optional.

int sumN(int n)
{
    // calculate 1+2+...+n
    int sum;
    __asm__(
        "mov %1, %%eax\n\t"
        "mov %%eax, %0\n\t"
        :"=d"(sum)
        :"c"(n)
        :"eax");
    return sum;
}

...

$ gcc test.c -m32 -o test
$ ./test

n: 1 sum(n): 1
...
n: 99 sum(n): 99

By the way, keep in mind that about compiling for x86-64, writing to eax clears the high-order bits of rax. This will need to be reflected in the clobber list.

Scroll to Top