Does anybody know how to work with numbers in fixed point? I want to try this format instead of float point, but it was hard to find good information about that. Thanks

there is nothing difficult to know, you just use some of the bits as precision, e.g. 16:16 or 24:8 bits. For any mathematical operation you can use the normal integer commands, like add, mul, div .. (take care that you dont get any overflow).

Before using the result value, just shift the number right for the fraction bits, e.g.16 or 8.

If you have decided for 24:8, you have for instance:

00000080h means 0.5

00000100h means 1.0

000008C0h means 8.75

12345678h means 1193046.46875

if you want to add 1.2 + 3.9:

mov eax, 00000133h

add eax, 000003E6h

sar eax, 8

result: eax = 5

note, that this will round always to the next lower number, if you will be more accurat, just add 0.5 before shifting, like this:

add eax, 080h

sar eax, 8

Take care about mul and div operations, cause there you will have twice as much bits after the operation, cause you also multiply the "shift-factor".

mov eax, 00000133h

imul eax, 000003E6h

sar eax, 16

or

mov edx, 0

mov eax, 00000133h

shl eax, 8

mov ecx, 000003E6h

idiv ecx

add eax, 080h

sar eax, 8

(note that this code does not use the 64 bit capabilities of mul / div, doing this would enlarge the range of possible values, just shift the resulting value from edx to eax about 8 bits)

The signs are handled just like normal integers, you can use signed or unsigned values, the most significant bit is still the first, so you dont need to care about it.

(hope this will help you, and further hope, that my mathematical english is good enough to explain something...)

Before using the result value, just shift the number right for the fraction bits, e.g.16 or 8.

If you have decided for 24:8, you have for instance:

00000080h means 0.5

00000100h means 1.0

000008C0h means 8.75

12345678h means 1193046.46875

if you want to add 1.2 + 3.9:

mov eax, 00000133h

add eax, 000003E6h

sar eax, 8

result: eax = 5

note, that this will round always to the next lower number, if you will be more accurat, just add 0.5 before shifting, like this:

add eax, 080h

sar eax, 8

Take care about mul and div operations, cause there you will have twice as much bits after the operation, cause you also multiply the "shift-factor".

mov eax, 00000133h

imul eax, 000003E6h

sar eax, 16

or

mov edx, 0

mov eax, 00000133h

shl eax, 8

mov ecx, 000003E6h

idiv ecx

add eax, 080h

sar eax, 8

(note that this code does not use the 64 bit capabilities of mul / div, doing this would enlarge the range of possible values, just shift the resulting value from edx to eax about 8 bits)

The signs are handled just like normal integers, you can use signed or unsigned values, the most significant bit is still the first, so you dont need to care about it.

(hope this will help you, and further hope, that my mathematical english is good enough to explain something...)

You may get a lot of info in the mixlib09.zip available at the bottom of the following page:

http://www.movsd.com/source.htm

A fixed point math library is provided complete with source code and examples. Simply ask if you need more explanations.

Raymond

http://www.movsd.com/source.htm

A fixed point math library is provided complete with source code and examples. Simply ask if you need more explanations.

Raymond

Let's suppose that I have the integer part in DX and the fracional part in AX, like 2.6: DX = 2 and AX = 6. Is there a way to divide this number by another decimal number in this format: DX:AX / DX:AX for example? Thanks

The simple answer is NO. The fractional part must be in binary fractional format.

One way of getting it in that format could be:

xor ax,ax

mov dx,6

mov cx,10

div cx

AX would then have the "0.6" in binary fractional format with 16 bits of precision. Loading DX with the integer portion, you could then divide it by some other integer word (which would need to be greater than the integer portion in DX, otherwise the program will crash). The binary fractional result would then be in AX.

The suggested mixlib library uses 32-bit registers allowing for much greater flexibility than with 16-bit registers.

Raymond

One way of getting it in that format could be:

xor ax,ax

mov dx,6

mov cx,10

div cx

AX would then have the "0.6" in binary fractional format with 16 bits of precision. Loading DX with the integer portion, you could then divide it by some other integer word (which would need to be greater than the integer portion in DX, otherwise the program will crash). The binary fractional result would then be in AX.

The suggested mixlib library uses 32-bit registers allowing for much greater flexibility than with 16-bit registers.

Raymond