0

I am using GCC in 32-bit mode on a Windows 7 machine under cygwin. I have the following function:

  unsigned f1(unsigned x, unsigned y)
  {
      return x*y;
  }

I want the code to do an unsigned multiply and as such I would expect it to generate the mul instruction, not the imul instruction. I compile the program with the following command:

 gcc -m32 -S t4.c

The generated assembly code is:

     .file   "t4.c"
     .text
     .globl  _f1
     .def    _f1;    .scl    2;  .type   32; .endef
_f1:
     pushl   %ebp
     movl    %esp, %ebp
     movl    8(%ebp), %eax
     imull   12(%ebp), %eax
     popl    %ebp
     ret
    .ident  "GCC: (GNU) 4.8.2"

I believe that the generated code has the wrong multiply instruction in it but I find it hard to believe that GCC has such a simple bug. Please comment.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Bob
  • 290
  • 3
  • 12
  • 1
    What is the problem with the code? Does it not work or generate a wrong result? – too honest for this site Mar 15 '16 at 00:29
  • 2
    Since you seem so concerned with the precise selection of assembly instructions, you must certainly have read `Intel® 64 and IA-32 Architectures Software Developer’s Manual`, specifically `IMUL—Signed Multiply: [...] The two- and three-operand forms may also be used with unsigned operands because the lower half of the product is the same regardless if the operands are signed or unsigned. The CF and OF flags, however, cannot be used to determine if the upper half of the result is non-zero.`? – EOF Mar 15 '16 at 01:04
  • 1
    [the lower half result is the same regardless of signed or unsigned multiplication](http://stackoverflow.com/q/14063599/995714). That's one of the advantages of 2's complement – phuclv Mar 15 '16 at 11:55
  • Possible duplicate of [x86 MUL Instruction from VS 2008/2010](http://stackoverflow.com/questions/4039378/x86-mul-instruction-from-vs-2008-2010) – phuclv Mar 15 '16 at 11:57
  • I could not find a problem with the generated code. All the test cases went as planned. – Bob Mar 16 '16 at 16:29

1 Answers1

6

The compiler relies on the "as-if" rule: No standard conforming program can detect a difference between what this program does and what the program should do, since the lowest 32 bits of the result are the same for both instructions.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • That's the reason why Intel didn't also make 2 and 3 operand versions of `mul`. If there was a use for it, it would exist. – Peter Cordes Mar 16 '16 at 04:41
  • @PeterCordes: I wonder if there's any reason they didn't define such "instructions" as having the same machine instructions as the "imul" forms, in much the way they did with some of the conditional branches which are named for the relationship between a compared destination and source, but in reality just check the carry flag. – supercat Jul 11 '16 at 17:39
  • @supercat: A more recent question finally shed light on why `mul` with multiple explicit operands isn't just a synonym for `imul`: [imul r,r still has signed semantics for setting CF and OF](http://stackoverflow.com/questions/38253541/c-unsigned-long-long-and-imulq/38254324#38254324). Also, its imm8 form uses sign-extension, not zero-extension. – Peter Cordes Jul 11 '16 at 17:49