Valhalla Legends Forums Archive | Assembly Language (any cpu) | mul/imul

AuthorMessageTime
Eibro
mul -- unsigned multiply.
I want to convert the following into C++
[code]mov    eax, bufdata
mul    factor
add    eax, tableval
adc    edx, 0x0
mov    bufdata, eax
mov    tableval, edx[/code]

Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)
[code]
unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;[/code]I don't understand why it is doing this.
November 18, 2004, 4:19 AM
Kp
Maybe 'unsigned __int64' is confusing cl (since int64 is an MSVC extension).  Try using unsigned long long (under gcc).  The following code produces a 64bit mull for me:

[code]extern unsigned pbuf[];
unsigned tableval, factor;
typedef unsigned long long uint64_t;
int m(int a, char **b) {
(void)(a&&b);
unsigned bufdata = pbuf[0];
unsigned long long result = ((uint64_t)bufdata) * ((uint64_t)factor) + ((uint64_t)tableval);
tableval = ( result >> 32 );
pbuf[1] = result & 0xffffffff;
return 0;
}
[/code]
Produces:[code]_m:
movl _factor, %ecx
movl _pbuf, %eax
pushl %ebx
mull %ecx
movl %eax, %ecx
movl %edx, %ebx
movl _tableval, %eax
xorl %edx, %edx
addl %eax, %ecx
adcl %edx, %ebx
movl %ecx, _pbuf+4
xorl %eax, %eax
movl %ebx, _tableval
popl %ebx
ret[/code]
November 18, 2004, 5:02 AM
Skywing
[quote author=Eibro[yL] link=topic=9594.msg89212#msg89212 date=1100751583]
mul -- unsigned multiply.
I want to convert the following into C++
[code]mov     eax, bufdata
mul     factor
add     eax, tableval
adc     edx, 0x0
mov     bufdata, eax
mov     tableval, edx[/code]

Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)
[code]
unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;[/code]I don't understand why it is doing this.
[/quote]
Try casting the * operands to 64-bit numbers.
November 18, 2004, 5:55 AM
Eibro
[quote author=Skywing link=topic=9594.msg89225#msg89225 date=1100757314]
[quote author=Eibro[yL] link=topic=9594.msg89212#msg89212 date=1100751583]
mul -- unsigned multiply.
I want to convert the following into C++
[code]mov    eax, bufdata
mul    factor
add    eax, tableval
adc    edx, 0x0
mov    bufdata, eax
mov    tableval, edx[/code]

Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)
[code]
unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;[/code]I don't understand why it is doing this.
[/quote]
Try casting the * operands to 64-bit numbers.
[/quote]Yep. That did it.
Thanks Skywing & Kp.
November 18, 2004, 12:13 PM
Eibro
[quote author=Kp link=topic=9594.msg89221#msg89221 date=1100754158]
Maybe 'unsigned __int64' is confusing cl (since int64 is an MSVC extension).  Try using unsigned long long (under gcc).  The following code produces a 64bit mull for me:

[code]extern unsigned pbuf[];
unsigned tableval, factor;
typedef unsigned long long uint64_t;
int m(int a, char **b) {
(void)(a&&b);
unsigned bufdata = pbuf[0];
unsigned long long result = ((uint64_t)bufdata) * ((uint64_t)factor) + ((uint64_t)tableval);
tableval = ( result >> 32 );
pbuf[1] = result & 0xffffffff;
return 0;
}
[/code]
Produces:[code]_m:
movl _factor, %ecx
movl _pbuf, %eax
pushl %ebx
mull %ecx
movl %eax, %ecx
movl %edx, %ebx
movl _tableval, %eax
xorl %edx, %edx
addl %eax, %ecx
adcl %edx, %ebx
movl %ecx, _pbuf+4
xorl %eax, %eax
movl %ebx, _tableval
popl %ebx
ret[/code]
[/quote]Hmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.
November 18, 2004, 12:37 PM
Skywing
For future reference, you might want to compare the code generated by the compiler there and the UInt32x32To64 macro.
November 18, 2004, 7:00 PM
Kp
[quote author=Eibro[yL] link=topic=9594.msg89235#msg89235 date=1100781421]Hmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.[/quote]

What C code did you feed to gcc?  Your MSVC code won't work verbatim due to the difference over what to name a 64bit number.
November 20, 2004, 12:26 AM
Eibro
[quote author=Kp link=topic=9594.msg89426#msg89426 date=1100910373]
[quote author=Eibro[yL] link=topic=9594.msg89235#msg89235 date=1100781421]Hmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.[/quote]

What C code did you feed to gcc?  Your MSVC code won't work verbatim due to the difference over what to name a 64bit number.
[/quote]The code you posted, less the casting.
November 20, 2004, 4:27 AM

Search