News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

multiplying/dividing a positive decimal number by a positive number

Started by shankle, February 28, 2015, 01:57:08 PM

Previous topic - Next topic

shankle

        3-8-2015
Thanks Dave for helping.
This code gives the wrong value in GoAsm 64-bit
Value should be 0.006
Incorrect value is 1.#nf

hdc        dq  0
n1         dq  0
n2         dq  15  ;fixed value
n3         dq  0   ; result
buf        db '       ',0
;  keyed in value is 0.090 in HoldValue
HoldValue  db '     ',0 ; keyed in variable input ex: 0.090

    lea rcx,HoldValue   ; this includes the decimal point
    invoke atodw,rcx    ; decimal string to DWORD(now in Hex)
    push rax

    fild Q[rsp]  ; load HoldValue into the ST0 register on the fpu stack
    fdiv Q[n2]   ; divide it by n2 directly from memory
    fstp Q[n3]   ; pop the results off the stack to memory
    invoke msvcrt:sprintf_s,addr buf,sizeof buf,\
                   "%g",[n3]
    invoke user32:MessageBoxA,0,addr buf,"Result",0
    invoke TextOut, [hdc],200,345,addr buf,7
    pop rax


dedndave

in order for the assembler to assign floating point constants, you must use real format
n1         dq  0.0
n2         dq  15.0  ;fixed value
n3         dq  0.0   ; result


i am not familiar with GoAsm, but with Masm, we use REAL8 instead of DQ
that way, the code does not need to be told the size

but - my guess is that the integer 15 is not the same as the REAL8 15.0

also - you could make your keyboard input buffer a bit larger   :P

Yuri

Yes, dq 15 and dq 15.0 are two different formats and we should not substitute one for the other. 0 and 0.0 must be the same, though.


DATA SECTION

n1  DQ 0
n2  DQ 15.0
n3  DQ 0
buf DB 100 DUP ?
HoldValue   DB "0.090",0

CODE SECTION

Start:
    invoke msvcrt:_atodbl, addr n1, addr HoldValue  ; Convert string to double.
    fld Q[n1]   ; Load n1 into the ST0 register on the FPU stack.
    fdiv Q[n2]  ; Divide it by n2 directly from memory.
    fstp Q[n3]  ; Pop the result off the stack to memory.
    invoke msvcrt:sprintf_s, addr buf, sizeof buf, "%g / %g = %g", [n1], [n2], [n3]
    invoke user32:MessageBoxA, 0, addr buf, "Result", 0
    ret


Quote
---------------------------
Result
---------------------------
0.09 / 15 = 0.006
---------------------------
ОК   
---------------------------

dedndave

right, Yuri - as it happens, 0.0 = 0
but - he's not loading those   :P

if you want to specify a real initializer, use a decimal point

Yuri

Sorry, Dave, but I don't see how it would make any difference. As far as I know, integer and floating point zeroes are both a bunch of zero bits.

However, I agree with your recommendation. Specifying 0.0 would be more logically correct and would also remind about the format of the number.

shankle

Thanks guys for responding.
Had a bunch of "HoneyDos" today but am still working on it....
Changed the 15 to 15.0 as directed. Didn't realize it made a difference.

To Yuri:
Where can I read about "Msvcrt:_atodbl?


shankle

1. I don't understand why it is necessary to use instructions that are not
   part of GoAsm.  Ex: any Msvcrt: instruction.

   Does that mean that GoAsm can not process the things that Msvcrt: does?

2: want to delete values past 0.01234 - 5 decimal places.
    EX 0.01234567 - want to Delete "567". Not round up or down.

Yuri

1. They are not instructions but functions. You can write your own function that converts a string to a double or vice versa. But if there is already a library of such functions, like msvcrt.dll, you can use them. It's up to you to decide which way you go.

2. Do you mean preventing those digits from showing in the string representation of the number or removing that part of the number itself?

dedndave

MSVCRT stands for microsoft visual c runtime library
ms c compilers depend on these libraries for many common functions
they are present on all windows computers, so you don't have to worry about checking

the best part about these library functions is that they have been around a long while
and, they have worked out a lot of bugs and improved performance, over time
so - that really reduces your development time and effort

if you have a string, and you want to truncate it, just pick a spot and put the 0 terminator byte in there

example

buffer db '0.1234567',0

mov byte ptr buffer+6,0


now, the string is

buffer db '0.1234',0

shankle

Thanks guys for responding.
I think Dave has answered my 2nd ?

The 1st ?  I have so far seen 2 Msvcrt:  functions used.
Where can I find  complete list of these functions?
 


dedndave

https://msdn.microsoft.com/en-us/library/5948ysye.aspx

2 important things to notice about that page

first, near the top, there is a drop-down that allows you to view older versions ("Other Versions")

second, in the left pane, there is a clickable list of function names

shankle

Figures are a tad high.
Maybe I need to change the Control Word RC field to 0400h
How do I do that?
Is this a correct assumption?

FORTRANS

Hi,

   The rounding control bits in the FPU control word work as follows.

  00 = Round to nearest or even, default.
  01 = Round down towards minus infinity.
  10 = Round up towards plus infinity.
  11 = Chop, truncate towards zero.


Setting the bits with 0400H will round down.  From what you were
saying earlier, I think you would want 0C00H to truncate.  Of course
if all your numbers are positive, it shouldn't matter much.

HTH,

Steve N.