-5

I'm using an MCU that doesn't support long long type. I can't cast to long long.

I need a function to get the high 32 bits of a 32-bit/32-bit multiplication.

x86 ASM is like this:

__asm {
    mov     eax, a
    mov     ecx, b
    mul     ecx
    mov     eax, edx
}

Is there a C code that would do the same function? I tried

UINT32 umulm(UINT32 a, UINT32 b)
{
    UINT32 i, r;

    r = 0;
    for (i = 1; i < 32; i++)
        if (a & (1 << i))
            r += b >> (32 - i);
    return r;
}

, but something is wrong with function; how could I fix it?

Joseph Qu
  • 11
  • 5
  • 1
    Many 32 bit CPUs don't support 64 bit types. But any compliant C compiler shall. And as yourt code is x86, you should use a compliant compiler. Actrually finding a non-compliant compiler is harder than a compliant one. – too honest for this site Aug 15 '16 at 19:44
  • 1
    Are you wanting to do this on x86 or an architecture other than x86. It isn't quite clear from your question. – rjp Aug 15 '16 at 19:44
  • 1
    Unless you clarify what exact machine you want this for, the only answer is to write a multi-precision multiply function yourself. – EOF Aug 15 '16 at 19:46
  • 2
    What compiler are you using, for what target system? – Keith Thompson Aug 15 '16 at 19:46
  • 1
    Related question that would help: http://stackoverflow.com/questions/1355461/multiplying-two-32-bit-numbers-without-using-64-bit-int – rjp Aug 15 '16 at 19:50
  • UINT32 umulm(UINT32 a, UINT32 b) { UINT32 i, r; r = 0; for (i = 1; i < 32; i++) if (a & (1 << i)) r += b >> (32 - i); return r; } this function is something wrong, how could I fix it? – Joseph Qu Aug 15 '16 at 20:10
  • 1
    @JosephQu:; What is `UINT32`? Why use some homebrew types and not the C standard types? Bad practice! – too honest for this site Aug 15 '16 at 21:36
  • 2
    [This answer](https://stackoverflow.com/questions/26852435/reasonably-portable-way-to-get-top-64-bits-from-64x64-bit-multiply/26855440#26855440) explains how to get the high 64-bits of a 64x64 bit multiply. It's easy to adapt to 32x32. – user3386109 Aug 15 '16 at 21:42
  • @Olaf: An implementation that doesn't support `long long` might not support `uint32_t` either. JosephQu: Again, what compiler are you using, and for what target system? – Keith Thompson Aug 15 '16 at 22:22
  • @KeithThompson: You are right about `uint32_t`, but that is not related to `long long`. DId I miss that `long long` has been made optional? (And that is apparently some x86 code and `UINT32` sounds pretty much a sane compiler would support `uint32_t` on that platform). I suspect some rubbish compiler, which should be trashed asap. – too honest for this site Aug 15 '16 at 23:23
  • @Olaf: The OP is using an implementation that does not support `long long`. No, it's not a fully conforming ISO C 2011 implementation. Do you think that pointing that out is helpful to the OP? – Keith Thompson Aug 15 '16 at 23:25
  • @KeithThompson: There is a point changing the compiler is the easier way than working around its quirks. This becomes even more important if maintenance is an issue, as such compilers are likely already beyond EOL support. – too honest for this site Aug 15 '16 at 23:26
  • @Olaf: What makes you think that's a possibility? We don't know what system the OP is using (which is why the question has been closed). – Keith Thompson Aug 15 '16 at 23:28
  • @KeithThompson: There is a rason I commented and did not answer ... – too honest for this site Aug 15 '16 at 23:29

1 Answers1

2

You can do this if you use the standard sized types:

#include <stdint.h>

...

uint32_t a = 0x1234; b = 0x5678;
uint64_t result = (uint64_t)a * b;
uint32_t high = (result >> 32) && 0xffffffff;
uint32_t low = result && 0xffffffff;

<stdint.h> was introduced with C99, so if your compiler isn't too ancient, you will most likely have this feature available.

Morten Jensen
  • 5,818
  • 3
  • 43
  • 55
dbush
  • 205,898
  • 23
  • 218
  • 273