-2

Trying to multiply 400 by 2 with inline assembly, using the fact imul implicity multiplies by eax. However, i'm getting "undefined reference" compile errors to $1 and $2

 int c;
 int a = 400;
 int b = 2;

 __asm__(
  ".intel_syntax;"
  "mov eax, $1;"
  "mov ebx, $2;"
  "imul %0, ebx;"
  ".att_syntax;"
  : "=r"(c)
  : "r" (a), "r" (b)
  : "eax");

std::cout << c << std::endl;
Jester
  • 52,795
  • 4
  • 67
  • 108
mezamorphic
  • 13,455
  • 46
  • 103
  • 168
  • 1
    That's not `masm` so don't tag it with `masm`. Do not use `eax` or `ebx` unless you have written the constraints properly. Do not switch syntax in inline asm, use `-masm=intel` if you want to write intel syntax. (The actual error is of course you'd need `.intel_syntax noprefix` but do not fix that. Instead fix everything else.) – Jester Feb 16 '20 at 18:56
  • 2
    In Intel-syntax, `$1` is a symbol name. Intel syntax doesn't use decorations on immediates, `mov $1, %eax` is only for AT&T. Once you fix that, you'll notice that everything else is broken; see Jester's comment. Also, you don't need `mov` instructions, just tell the compiler where to put your inputs, or use the `%0` / `%1` or named operands everywhere to let it choose. See [segmentation fault(core dumped) error while using inline assembly](//stackoverflow.com/q/60237447). If your first or last instruction in an asm template is `mov`, you're usually doing it wrong. – Peter Cordes Feb 16 '20 at 18:58
  • Oh yeah, that should be `%1` there for the operand substitution. – Jester Feb 16 '20 at 18:59
  • @Jester I assume you're saying the clobber list is incorrect? – mezamorphic Feb 16 '20 at 23:05
  • @Jester I tagged it with MASM because the Stackoverflow description for the MASM tag mentioned Intel syntax. – mezamorphic Feb 16 '20 at 23:18

1 Answers1

3

Do not use fixed registers in inline asm, especially if you have not listed them as clobbers and have not made sure inputs or outputs don't overlap them. (This part is basically a duplicate of segmentation fault(core dumped) error while using inline assembly)

Do not switch syntax in inline assembly as the compiler will substitute wrong syntax. Use -masm=intel if you want intel syntax.

To reference arguments in an asm template string use % not $ prefix. There's nothing special about $1; it gets treated as a symbol name just like if you'd used my_extern_int_var. When linking, the linker doesn't find a definition for a $1 symbol.

Do not mov stuff around unnecessarily. Also remember that just because something seems to work in a certain environment, that doesn't guarantee it's correct and will work everywhere every time. Doubly so for inline asm. You have to be careful. Anyway, a fixed version could look like:

__asm__(
  "imul %0, %1"
  : "=r"(c)
  : "r" (a), "0" (b)
  : );

Has to be compiled using -masm=intel. Notice b has been put into the same register as c.


using the fact imul implicity multiplies by eax

That's not true for the normal 2-operand form of imul. It works the same as other instructions, doing dst *= src so you can use any register, and not waste uops writing the high half anywhere if you don't even want it.

Peter Cordes
  • 245,674
  • 35
  • 423
  • 606
Jester
  • 52,795
  • 4
  • 67
  • 108
  • Is there ever a need to use fixed registers within inline assembly? Is there a trade-off/decision to be made, or literally just always use the placeholders? – mezamorphic Feb 17 '20 at 00:10
  • Some instructions expect particular registers. Otherwise just leave the register allocation to the compiler. Even then. you'd use the appropriate constraint and not `mov` stuff around. – Jester Feb 17 '20 at 00:11