0

I would like to learn some inline assembly programming, but my first cod snippet does not work. I have a string and I would like to assign the value of the string to the rsi register.

Here is my code:

    string s = "Hello world";
    const char *ystr = s.c_str();
    asm("mov %1,%%rsi"
    :"S"(ystr)
    :"%rsi" //clobbered register
);

    return 0;

It gives me the error :Expected ')' before token. Any help is appreciated.

  • 3
    Did you actually write `;clobbered register` in your code? – MikeCAT Jun 14 '21 at 16:27
  • Yes, but I wrote that as a comment. – Andras M Szilagyi Jun 14 '21 at 16:29
  • Comments in C++ are begun with `//`, not `;`. – Nate Eldredge Jun 14 '21 at 16:29
  • 2
    You have several other problems: (1) extended asm operands are numbered starting with 0, not 1 (2) specifying the `S` constraint will already cause the compiler to load the value into `rsi`, so the `mov` is unnecessary (3) you cannot clobber the same register that operand is constrained to be loaded into. – Nate Eldredge Jun 14 '21 at 16:30
  • (4) The operands after the first colon should be outputs, not inputs; you would need two colons between `"mov %0, %%rsi"` and `"S"`. – Nate Eldredge Jun 14 '21 at 16:33
  • You left out a `:` to delimit the empty outputs section. So `"S"(ystr)` is an input operand in the outputs section, and `"%rsi"` in the inputs section. But it's missing a `(var_name)` so that's a syntax error, as well as a semantic error. That's the immediate source of the error `:9:5: error: expected '(' before ')' token`. https://godbolt.org/z/97aTdjE8K – Peter Cordes Jun 14 '21 at 16:33
  • Opposite problem of [g++ inline assembly mismatch in brackets](https://stackoverflow.com/q/64762476), not quite a duplicate. – Peter Cordes Jun 14 '21 at 16:39
  • Elaborate on the erorr, please – JohnkaS Jun 14 '21 at 16:51

3 Answers3

1

You left out a : to delimit the empty outputs section. So "S"(ystr) is an input operand in the outputs section, and "%rsi" is in the inputs section, not clobbers.

But as an input it's missing the (var_name) part of the "constraint"(var_name) syntax. So that's a syntax error, as well as a semantic error. That's the immediate source of the error <source>:9:5: error: expected '(' before ')' token. https://godbolt.org/z/97aTdjE8K


As Nate pointed out, you have several other errors, like trying to force the input to pick RSI with "S".

   char *output;   // could be a dummy var if you don't actually need it.
   asm("mov %1, %0"
     : "=r" (output)     /// compiler picks a reg for you to write to.
    :"S"(ystr)           // force RSI input
    :   // no clobbers
   );

Note that this does not tell the compiler that you read or write the pointed-to memory, so it's only safe for something like this, which copies the address around but doesn't expect to read or write the pointed-to data.

Also related:

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
1

In general, when using gcc inline asm on x86, you want to avoid ever using mov instructions, and want to avoid explicit registers in the asm code -- just use the register constraints to get things in the appropriate registers. So for your example, getting a string pointer into the rsi register, you want just:

asm volatile("; ystr wil be in %rsi here"
            :  // no output contraints
            : "S"(ystr)  // input constraint
            :  // no clobber needed
            );

Note that there's no actual asm code output here -- just a comment. The input constraint is sufficient to get the operand into the needed register prior to the point where this appears. Yes, rsi might well be used for something else afterwards, but that is as expected -- the register constraints just cover the inputs and outputs of the asm text.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

In my case, C++ code was compiled with -std=c++17 and the compiler also reported expected ')' before ':' token

I changed the keyword asm to __asm__ and in my case, this helped.

This modification was inspired by "When writing code that can be compiled with -ansi and the various -std options, use __asm__ instead of asm" from https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html, however as commented below, this may not be completely precise.

  • 1
    Only if you tell the compiler not to recognize the `asm` keyword by using `g++ -std=c++20` instead of `-std=gnu++20`. In that case yes, you need to use the `__foo__` versions of some names that GNU C++ would otherwise define. That wasn't the problem in this question; does `g++ -std=c++20` give the same error message? – Peter Cordes May 02 '22 at 14:52
  • I checked (https://godbolt.org/z/rqG59rqrv) - `gcc -std=c11` includes the error message `expected ')' before ':' token` when compiling as C, but `g++ -std=c++11` still allows the `asm` keyword, even with `-Wall -Wextra -Wpedantic`. (clang vs. clang++ is the same). Maybe ISO C++ reserves that keyword while ISO C doesn't. So this isn't a very good answer to a C++ question without some explanation. – Peter Cordes May 03 '22 at 04:35
  • Thank you @PeterCordes, I added some context to my answer. – Adam Husár May 08 '22 at 17:36