flat assembler
Message board for the users of flat assembler.

Index > Main > multiplying signed and unsigned integer

Author
Thread Post new topic Reply to topic
vivik



Joined: 29 Oct 2016
Posts: 671
vivik 21 Apr 2017, 19:24
When you need to multiply two unsigned integers, you use mul.

When you need to multiply two signed integers, you use imul.

But to multiply a signed and an unsigned integer, which should you use?



Also, which kind of integer you use more often, signed or unsigned? Where do you use each?
Post 21 Apr 2017, 19:24
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4072
Location: vpcmpistri
bitRAKE 21 Apr 2017, 22:05
vivik wrote:
But to multiply a signed and an unsigned integer, which should you use?
Do some range checking on the unsigned number and then use IMUL?
Quote:
Also, which kind of integer you use more often, signed or unsigned? Where do you use each?
I mostly use unsigned because I only use signed if required. Even when working with small ranges of numbers, I like to leave open the option of using negative numbers for something else in the future. Usually, some form of simple range checking. On rarer occasions I will also not use zero for the same reason. Really depends on the problem.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 21 Apr 2017, 22:05
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 21 Apr 2017, 23:46
vivik wrote:
But to multiply a signed and an unsigned integer, which should you use?
Convert the unsigned value to signed of the next size and use signed IMUL.
vivik wrote:
Also, which kind of integer you use more often, signed or unsigned?
Asking about the popularity is not the right question here. Use what makes sense in the application you are working on.
Post 21 Apr 2017, 23:46
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2561
Furs 22 Apr 2017, 11:16
BTW you can use imul for unsigned multiplications unless you need the upper half.

The lower half (i.e. 32-bit x 32-bit -> 32-bit lower half result) are the same whether you use mul or imul. There's a difference only if you are interested in the upper half.
Post 22 Apr 2017, 11:16
View user's profile Send private message Reply with quote
vivik



Joined: 29 Oct 2016
Posts: 671
vivik 22 Apr 2017, 12:59
I'm confused by the result of division. Any idea what happened here?

MOV EAX,-5
XOR EDX,EDX
MOV ECX,-2
; eax fffffffb
; ecx fffffffe

IDIV ECX
; eax 80000003 ;why?
; edx 1



MOV EAX,-5
XOR EDX,EDX
MOV ECX,-2
; eax fffffffb
; ecx fffffffe

DIV ECX
; eax 0 ;why?
; edx fffffffb
Post 22 Apr 2017, 12:59
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 22 Apr 2017, 13:10
IDIV:
EDX:EAX = 0x00000000fffffffb = +4294967291
ECX = 0xfffffffe = -2

Result = 0x80000003 = -2147483645

CPU is Correct

DIV:
EDX:EAX = 0x00000000fffffffb = +4294967291
ECX = 0xfffffffe = +4294967294

Result = 0x00000000 = 0

CPU is Correct

Explanation: I suspect you want to use cdq instead of xor edx,edx.
Post 22 Apr 2017, 13:10
View user's profile Send private message Visit poster's website Reply with quote
vivik



Joined: 29 Oct 2016
Posts: 671
vivik 22 Apr 2017, 13:44
Thanks!

Hope I don't annoy you too much.
Post 22 Apr 2017, 13:44
View user's profile Send private message Reply with quote
vivik



Joined: 29 Oct 2016
Posts: 671
vivik 22 Apr 2017, 14:13
Never seen an integer overflow before, didn't knew this exception existed.
Post 22 Apr 2017, 14:13
View user's profile Send private message Reply with quote
vivik



Joined: 29 Oct 2016
Posts: 671
vivik 23 Apr 2017, 10:12
Question about big numbers.

I know it's possible to add or substract 64- 96- or 128-bit numbers on 32-bit processor with the use of flags. But is it possible to multiply or divide them? This is probably a math question.

After I learned that div can cause exception if you put something weird in edx, I probably never going to divide a 64-bit number(, unless I know that it's safe).

There was this link in the sticky http://www.x86asm.net/articles/working-with-big-numbers-using-x86-instructions/ , but it limits itself at 64-bit numbers.
Post 23 Apr 2017, 10:12
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 23 Apr 2017, 10:21
vivik wrote:
I know it's possible to add or substract 64- 96- or 128-bit numbers on 32-bit processor with the use of flags. But is it possible to multiply or divide them?
You can't directly divide them. There are methods available that use DIV as the first approximation. Barrett and Montgomery are to most commonly used methods IME, but a bit of searching will reveal many other methods.

You also can't directly multiply them. But a basic long multiply (like you learned in school) can be used. And for larger numbers things like Karatsuba and FFT can be a win.
Post 23 Apr 2017, 10:21
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2561
Furs 25 Apr 2017, 18:21
For multiplying/division of large 64-bit numbers on 32-bit mode (or for dynamic range) you should try and use the x87 FPU with the 80-bit precision if you can (unless you require even higher results). You can store any 64-bit integer exactly in one 80-bit FPU register and all operations can be done exact (in terms of 64-bit integer results) as long as you require only 64-bits of integer precision, and multiplying them is a matter of multiplying their significands (normal 64-bit x 64-bit multiply) and adding their exponents.

Make sure the FPU control word is set appropriately to use all 80-bits of precision because some stupid OS like Windows sets it to 64-bit only. (you can easily change it with asm)

Obviously I don't think it will work without precision loss if you need a number larger than 64 bits in the result (unless they have a certain multiple of a power-of-2 each, then you get extra precision bits due to increased dynamic range), but since it's floating point its dynamic range will be huge.
Post 25 Apr 2017, 18:21
View user's profile Send private message Reply with quote
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 25 Apr 2017, 21:20
Furs wrote:
For multiplying/division of large 64-bit numbers on 32-bit mode (or for dynamic range) you should try and use the x87 FPU with the 80-bit precision if you can (unless you require even higher results). You can store any 64-bit integer exactly in one 80-bit FPU register and all operations can be done exact (in terms of 64-bit integer results) as long as you require only 64-bits of integer precision, and multiplying them is a matter of multiplying their significands (normal 64-bit x 64-bit multiply) and adding their exponents.


No. F80 is good only for 18 significant digits. So representing max 0xffffffffffffffff (20 digits) with F80, will give you inexact result due to exponentiation.

Secondly, FPU and the general registers use different kind of overflow exceptions and flags. What may seem to be overflow in integers, may look fine in SFLAG register of the FPU.

Thirdly, signmess in FPU and general registers are interpreted quite differently. 0 and -0.0 may give you trouble.

Next, FPU involves other kind of exceptions such as NaN (QNaN and SNaN) which is not relevant to integer operations but do affect the results and the entire operations.

Finally, 80-bit precision is only good as far as 63 mantissa bits. In contrast to integers (2^64 - 1).

So either in 32-bit or 64-bit CPU, using FPU 80-bit precisions to represent a 64 integer is not smart in any way.
Post 25 Apr 2017, 21:20
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2561
Furs 25 Apr 2017, 22:34
fasmnewbie wrote:
No. F80 is good only for 18 significant digits. So representing max 0xffffffffffffffff (20 digits) with F80, will give you inexact result due to exponentiation.
Sorry but that's bullshit, you speak in decimal which is an approximation and has nothing to do whatsoever with binary representation.

fasmnewbie wrote:
Secondly, FPU and the general registers use different kind of overflow exceptions and flags. What may seem to be overflow in integers, may look fine in SFLAG register of the FPU.
Yeah, this is valid, but I never spoke about overflow flags though; I mean, it's same as not using upper half of a wide integer multiplication, which is the more common case. If he needs proper overflow detection then you are right, of course.

fasmnewbie wrote:
Thirdly, signmess in FPU and general registers are interpreted quite differently. 0 and -0.0 may give you trouble.
Huh?

-0.0 converted back to integer is 0, no issue at all. What trouble are you even speaking of. Multiplication by -0 is also 0 result (or -0, but again, when you convert it back when done, it's not an issue).

fasmnewbie wrote:
Next, FPU involves other kind of exceptions such as NaN (QNaN and SNaN) which is not relevant to integer operations but do affect the results and the entire operations.
How are you going to get those things if you perform integer operations...? Other than dividing by 0, which is an exception in integer division anyway, and needs special care.

Obviously you can do weird floating point math and prove me wrong, but that's beside the point. You cannot do those with integer operations, so why even think about them? In these cases it's "wrong result" vs "impossible code" (with integers) so it's still better.

fasmnewbie wrote:
Finally, 80-bit precision is only good as far as 63 mantissa bits. In contrast to integers (2^64 - 1).
Wrong. There is an implied 1 bit (I think?) or full 64 bits at least. See https://en.wikipedia.org/wiki/Extended_precision

Think about it like this, people used to copy data with the FPU (using integer loads and stores, because otherwise NaNs would give you trouble if the data happened to have that pattern) 8 bytes at a time before SSE was mainstream. You understand this right? A data copy operation is not allowed to change even 1 bit and must preserve all 8 bytes perfectly.

Again, with integer loads and stores, because otherwise the FPU could mess the number up in certain cases (NaNs) but with integers no issue at all, since the significand itself is 64 bits wide. That's why they weren't copying 10 bytes at a time.

Most people think floating point math is unpredictable and random but that's nonsense.

You can do all operations with integer precision at least as wide as the significand is with absolutely no precision loss whatsoever (obviously, if you are looking for an integer result and truncate the fraction)
Post 25 Apr 2017, 22:34
View user's profile Send private message Reply with quote
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 25 Apr 2017, 23:47
Furs wrote:
fasmnewbie wrote:
No. F80 is good only for 18 significant digits. So representing max 0xffffffffffffffff (20 digits) with F80, will give you inexact result due to exponentiation.
Sorry but that's bullshit, you speak in decimal which is an approximation and has nothing to do whatsoever with binary representation.

fasmnewbie wrote:
Secondly, FPU and the general registers use different kind of overflow exceptions and flags. What may seem to be overflow in integers, may look fine in SFLAG register of the FPU.
Yeah, this is valid, but I never spoke about overflow flags though; I mean, it's same as not using upper half of a wide integer multiplication, which is the more common case. If he needs proper overflow detection then you are right, of course.

fasmnewbie wrote:
Thirdly, signmess in FPU and general registers are interpreted quite differently. 0 and -0.0 may give you trouble.
Huh?

-0.0 converted back to integer is 0, no issue at all. What trouble are you even speaking of. Multiplication by -0 is also 0 result (or -0, but again, when you convert it back when done, it's not an issue).

fasmnewbie wrote:
Next, FPU involves other kind of exceptions such as NaN (QNaN and SNaN) which is not relevant to integer operations but do affect the results and the entire operations.
How are you going to get those things if you perform integer operations...? Other than dividing by 0, which is an exception in integer division anyway, and needs special care.

Obviously you can do weird floating point math and prove me wrong, but that's beside the point. You cannot do those with integer operations, so why even think about them? In these cases it's "wrong result" vs "impossible code" (with integers) so it's still better.

fasmnewbie wrote:
Finally, 80-bit precision is only good as far as 63 mantissa bits. In contrast to integers (2^64 - 1).
Wrong. There is an implied 1 bit (I think?) or full 64 bits at least. See https://en.wikipedia.org/wiki/Extended_precision

Think about it like this, people used to copy data with the FPU (using integer loads and stores, because otherwise NaNs would give you trouble if the data happened to have that pattern) 8 bytes at a time before SSE was mainstream. You understand this right? A data copy operation is not allowed to change even 1 bit and must preserve all 8 bytes perfectly.

Again, with integer loads and stores, because otherwise the FPU could mess the number up in certain cases (NaNs) but with integers no issue at all, since the significand itself is 64 bits wide. That's why they weren't copying 10 bytes at a time.

Most people think floating point math is unpredictable and random but that's nonsense.

You can do all operations with integer precision at least as wide as the significand is with absolutely no precision loss whatsoever (obviously, if you are looking for an integer result and truncate the fraction)


Yeah genius.

f dt 18446744073709551615.0 ;(max 64-bit integer unsigned)
fld [f]

How do you think this may look like in the FPU register?

1.84467440737095516E+19

I wonder where the other 2 digits go...
Post 25 Apr 2017, 23:47
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 26 Apr 2017, 03:13
fasmnewbie wrote:
f dt 18446744073709551615.0 ;(max 64-bit integer unsigned)
fld [f]

How do you think this may look like in the FPU register?

1.84467440737095516E+19

I wonder where the other 2 digits go...
Actually it stores inside the FPU just fine. There is no loss of precision. The FPU is binary in nature not decimal. But you can't store that as a normal qword with fistp due to integer overflow. Numbers in the normal 64-bit integer range (-2^63 to +2^63-1) can be manipulated with the FPU in extended precision mode just fine.
Post 26 Apr 2017, 03:13
View user's profile Send private message Visit poster's website Reply with quote
fasmnewbie



Joined: 01 Mar 2011
Posts: 555
fasmnewbie 26 Apr 2017, 09:19
revolution wrote:
fasmnewbie wrote:
f dt 18446744073709551615.0 ;(max 64-bit integer unsigned)
fld [f]

How do you think this may look like in the FPU register?

1.84467440737095516E+19

I wonder where the other 2 digits go...
Actually it stores inside the FPU just fine. There is no loss of precision. The FPU is binary in nature not decimal. But you can't store that as a normal qword with fistp due to integer overflow. Numbers in the normal 64-bit integer range (-2^63 to +2^63-1) can be manipulated with the FPU in extended precision mode just fine.


oh, ok then. I misread Furr's earlier comment. I thought he meant to use 80 bit precisions (DT) to represent an integer.
Post 26 Apr 2017, 09:19
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.