signed vs. unsigned multiplication

Discussion in 'C Programming' started by wrschlanger@gmail.com, Jun 17, 2012.

  1. Guest

    Does anyone care to comment on the below program I wrote?
    The question I was wondering is: why do compilers still use IMUL or MUL forsigned or unsigned multiplication respectively when there is no differencein the numeric value of the result provided the product size is the same as the size of the two factors that are being multiplied together?

    This program prints PASS on my screen when I run it. Am I missing something?

    Here is what I think is going on. The Intel manual lists IMUL for signed imultiplication and MUL for unsigned. It does this because originally those instructions always doubled capacity, i.e. the product had twice the size ofthe factors.

    But then a variant of IMUL was introduced that discards the upper half of the result, i.e. it works like the C * operator. This is still listed as being for "signed" multiplication but it works equally well for unsigned multiplication and might be more efficient because it can take more operands.

    Do any compiler writers know about this?? Or do they blindly trust the Intel manuals?

    (By the way--interestingly I can't get (unsigned char)(0xff) to equal (signed char)(0xff) in GCC).
    ---
    #include <cstdio>

    int main()
    {
    for(int a = 0; a < 256; ++a)
    {
    for(int b = 0; b < 256; ++b)
    {
    signed char sa = a;
    signed char sb = b;
    unsigned char ua = a;
    unsigned char ub = b;
    signed char sc = sa * sb;
    unsigned char uc = ua * ub;
    unsigned char usc = sc;
    if(uc != usc)
    {
    std::printf("FAIL %02x * %02x = %02x vs. %02x\n", ua, ub, (unsigned int)(unsigned char)(sc), uc);
    break;
    }
    }
    }
    std::printf("PASS\n");
    return 0;
    }
    , Jun 17, 2012
    #1
    1. Advertising

  2. Xavier Roche Guest

    Le 17/06/2012 16:31, a écrit :
    > Does anyone care to comment on the below program I wrote?


    There is no difference between signed/unsigned muls if you restrict them
    to the source size AFAIK.

    > The question I was wondering is: why do compilers still use IMUL or MUL for signed or unsigned multiplication respectively when there is no difference in the numeric value of the result provided the product size is the same as the size of the two factors that are being multiplied together?


    extern unsigned char mulu(unsigned char a, unsigned char b) {
    return a*b;
    }

    extern signed char muls(signed char a, signed char b) {
    return a*b;
    }

    $ gcc -O -S -std=c99 sample.c -o sample.S

    mulu:
    movl %esi, %eax
    imull %edi, %eax
    ret

    muls:
    movl %esi, %eax
    imull %edi, %eax
    ret
    Xavier Roche, Jun 17, 2012
    #2
    1. Advertising

  3. Eric Sosman Guest

    On 6/17/2012 10:31 AM, wrote:
    > Does anyone care to comment on the below program I wrote?


    Comment: It's written in C++, not C. The two languages are
    related but not identical, and differ in details large and small.
    Try comp.lang.c++ for your C++ questions.

    > (By the way--interestingly I can't get (unsigned char)(0xff) to equal (signed char)(0xff) in GCC).


    This would be easy to explain in C, although I don't know whether
    the C++ explanation would be similar. In C on a machine with eight-bit
    characters, `signed char' cannot represent the value 0xFF=255 so the
    conversion of 255 to `signed char' so "the result is implementation-
    defined or an implementation-defined signal is raised." The usual
    implementation-defined result is just to store as many bits as will fit,
    which on a two's complement machine would produce -1. Meanwhile,
    `unsigned char' *is* able to hold 255, so your interesting observation
    is that 255 != -1; most people find this unsurprising.

    --
    Eric Sosman
    d
    Eric Sosman, Jun 17, 2012
    #3
  4. writes:

    > Does anyone care to comment on the below program I wrote?


    First off, it's a C++ program and not a C one. I don't think there is a
    significant area of difference in this program, but if you want answers
    about C++ then comp.lang.c++ is a better place. It's possible that
    follow-ups might stray into and area where the is an important
    difference between the two languages.

    > The question I was wondering is: why do compilers still use IMUL or
    > MUL for signed or unsigned multiplication respectively when there is
    > no difference in the numeric value of the result provided the product
    > size is the same as the size of the two factors that are being
    > multiplied together?


    This is not really a C (or C++) question. You give a reasonable
    explanation below, but from a C point of view I wonder why you care. Do
    you think the compiler is getting something wrong as a result of the
    choice being made?

    > This program prints PASS on my screen when I run it. Am I missing
    > something?


    Since you ask, the answer must be yes. Presumably you expected
    something else, but I can't be sure what. People here could offer more
    help if you say why you think you might be missing something.

    > Here is what I think is going on. The Intel manual lists IMUL for
    > signed imultiplication and MUL for unsigned. It does this because
    > originally those instructions always doubled capacity, i.e. the
    > product had twice the size of the factors.
    >
    > But then a variant of IMUL was introduced that discards the upper half
    > of the result, i.e. it works like the C * operator. This is still
    > listed as being for "signed" multiplication but it works equally well
    > for unsigned multiplication and might be more efficient because it can
    > take more operands.
    >
    > Do any compiler writers know about this?? Or do they blindly trust the
    > Intel manuals?


    I would image that they trust the hardware documentation, but not
    "blindly". I feel I'm not really getting at what is bothering you.

    > (By the way--interestingly I can't get (unsigned char)(0xff) to equal
    > (signed char)(0xff) in GCC).


    Well, there's something wrong with your expectation here. Whilst
    it's possible for these to be equal on some systems, it is not "normal"
    for the systems that have gcc ported to them.

    > #include <cstdio>


    Change to stdio.h to make this a standard C header.

    > int main()


    In C, int main(void) is (marginally) better.

    > {
    > for(int a = 0; a < 256; ++a)
    > {
    > for(int b = 0; b < 256; ++b)
    > {
    > signed char sa = a;
    > signed char sb = b;
    > unsigned char ua = a;
    > unsigned char ub = b;
    > signed char sc = sa * sb;
    > unsigned char uc = ua * ub;
    > unsigned char usc = sc;
    > if(uc != usc)
    > {
    > std::printf("FAIL %02x * %02x = %02x vs. %02x\n", ua, ub, (unsigned int)(unsigned char)(sc), uc);
    > break;
    > }
    > }
    > }
    > std::printf("PASS\n");
    > return 0;
    > }


    Turn std::printf to plain printf to make this C.

    --
    Ben.
    Ben Bacarisse, Jun 17, 2012
    #4
  5. Guest

    Hi Ben,

    I do a lot of low level stuff and regularly look at the output from my C compiler. (My apologies for posting C++ code to a C newsgroup).

    I was basically wondering about Visual C++ whose code seemed (at least for the old version I checked) to always use MUL for 32-bit unsigned multiplication, and I was wondering whether or not my observation that IMUL would work just as well, was accurate.

    This was answered by an earlier post, though I don't have a proof, I guess I don't need one as long as there's a general consensus -- and the fact that GCC generates identical code (using IMUL) is enough proof for me.

    The reason I made the post was because I was unaware that GCC did this.

    On Sunday, June 17, 2012 8:37:37 AM UTC-7, Ben Bacarisse wrote:
    [snip]
    > Turn std::printf to plain printf to make this C.
    >
    > --
    > Ben.


    Thanks for the tips on converting to C. If I have any other questions I will use a C++ newsgroup, or make sure everything works with plain C. Actuallythis question would have been better suited for an assembly group since it's specific to x86, but then they might complain I used C and not assembly :)


    Willow
    , Jun 17, 2012
    #5
  6. BartC Guest

    <> wrote in message
    news:...

    > I was basically wondering about Visual C++ whose code seemed (at least for
    > the old version I checked) to always use MUL for 32-bit unsigned
    > multiplication, and I was wondering whether or not my observation that
    > IMUL would work just as well, was accurate.
    >
    > This was answered by an earlier post, though I don't have a proof, I guess
    > I don't need one as long as there's a general consensus -- and the fact
    > that GCC generates identical code (using IMUL) is enough proof for me.


    I'm doing some code generation at the moment and using MUL and IMUL. If the
    latter works just as well, and could be faster because of the 32-bit, rather
    than 64-bit, result, then I will use it.

    Although the brief test I've just done shows no difference (not on my
    processor anyway).

    As for proof, testing that I get the same results on a selected range of
    values will do me. It's not necessary to test all 2**64 possible pairs of
    operands (and which would anyway take too long). And I wouldn't rely on the
    output of GCC; there could be many reasons why the generated code is what it
    is.

    --
    Bartc
    BartC, Jun 17, 2012
    #6
  7. On 2012-06-17, BartC <> wrote:
    ><> wrote in message
    > news:...
    >
    >> I was basically wondering about Visual C++ whose code seemed (at least for
    >> the old version I checked) to always use MUL for 32-bit unsigned
    >> multiplication, and I was wondering whether or not my observation that
    >> IMUL would work just as well, was accurate.
    >>
    >> This was answered by an earlier post, though I don't have a proof, I guess
    >> I don't need one as long as there's a general consensus -- and the fact
    >> that GCC generates identical code (using IMUL) is enough proof for me.

    >

    ....
    > operands (and which would anyway take too long). And I wouldn't rely on the
    > output of GCC; there could be many reasons why the generated code is what it
    > is.


    The (maligned) Intel manual[1] is actually reasonably clear about this,
    if you don't mind trusting it "blindly" for this occasion:

    "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."

    (When using the "correct" version of MUL/IMUL, the CF or OF flag -- they
    have the same value -- can be tested to see if any significant bits will
    be lost when truncating the result back to 32 bits, in case this is of
    interest.)


    [1] Intel(R) 64 and IA-32 Architectures Software Developer's Manual,
    Volume 2 (2A, 2B & 2C): Instruction Set Reference, A-Z: "IMUL--Signed
    Multiply", Vol. 2A, pp. 3-495.


    --
    Heikki Kallasjoki
    Heikki Kallasjoki, Jun 17, 2012
    #7
  8. Joe. Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > writes:
    >
    >> Does anyone care to comment on the below program I wrote?

    >
    > First off, it's a C++ program and not a C one.


    But you experience has no value.?

    It's not about programming anymore, it's about who you programmed for. ?

    I ask the hard questions. I should just shut up and capitalize on them?

    Did Jesus die for anyone's sins?
    Joe., Jun 25, 2012
    #8
  9. Joe. Guest

    <> wrote in message
    news:...
    Hi Ben,

    "I do a lot of low level stuff and regularly look at the output from my C
    compiler. (My apologies for posting C++ code to a C newsgroup)."

    But you don't want one of "dem jobs" either, huh? Did "your country" fail
    you?
    Joe., Jun 25, 2012
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Weng Tianxiang
    Replies:
    4
    Views:
    3,023
    Weng Tianxiang
    Apr 7, 2005
  2. Christopher Dyken

    32x32 and 64x64 signed integer multiplication

    Christopher Dyken, Feb 17, 2004, in forum: C Programming
    Replies:
    18
    Views:
    1,417
    glen herrmannsfeldt
    Feb 24, 2004
  3. priya

    signed multiplication

    priya, Nov 16, 2006, in forum: VHDL
    Replies:
    2
    Views:
    1,658
    priya
    Nov 17, 2006
  4. William Hughes
    Replies:
    13
    Views:
    1,200
    Ben Bacarisse
    Mar 15, 2010
  5. pozz
    Replies:
    12
    Views:
    712
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page