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

dedndave

not sure i see an advantage in that Michael
seems like more work   :redface:

shankle

This is my latest attempt.......        3-6-2015
Revision Number two.

I loaded this code into my 64-bit GoAsm Program.
The program compiled without errors.
I changed your code from msvcrt:printf to Textout.
dwtoa has been changed to handle 64-bit registers.

I gave up on the fixed point suggestion.
Got a lot of invalid results that made no sense.
So something hidden was altering the results.

    n1        dq  1.00416
    n2        dq  15.0
    n3        dq  0
    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 results off the stack to memory
   
;   test code begin
    testout  db '                       ',0
    BufAdd   dq  0
    hdc      dq  0
    mov rcx,[n3]
    lea rbx,testout
    mov [BufAdd],rbx
    invoke dwtoa,rcx,[BufAdd]      ; Hex DD to string
                               ; output is in testout
    invoke TextOut, [hdc],200,600,addr testout,20
; test code end

The result of this code should be 0.066944
This is what I got - 4571453861756211473

Thanks Yuri for the sample code.
Thanks Dave for the pointer to "fpu tutorial by Raymond Filiatreault"

MichaelW

Quote from: dedndave on March 07, 2015, 12:03:38 AM
seems like more work
Floating point operations in a HLL are much easier to understand and code. For a complex series of equations there would be a very large difference in coding effort.

Well Microsoft, here's another nice mess you've gotten us into.

GoneFishing

Quote from: MichaelW on March 06, 2015, 09:20:59 PM
I realize that the "Real Men" here are going to frown on this, but you can ease the task of using the FPU by creating a simple helper DLL in a HLL (I used Pelles C for this) that provides functions that make it relatively easy to do simple calculations.
...
Agree with Michael . Realising this fact was one another little step forward in my learning process.
I thought about implementing  this in ASM . As I don't have appropriate math background / floating point understanding I desided to make first draft in C++ and it took 100 lines of code to do that.
I borrowed Vec structure from famous on internet SMALLPT program :

struct Vec {       
  double x, y, z;               
  Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; }
  Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); }
  Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); }
  Vec operator*(double b) const { return Vec(x*b,y*b,z*b); }
  Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); }
  Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); }
  double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross:
  Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);}
};


How much lines of code will it take in ASM ?

P.S.: Moreover, it's a good way to learn from compiler - he(or she?) does know SSE better and I can tell him(or her?)  to optimize my code for , say, SSE2

Yuri

shankle
n3 is not an integer. It's in a floating point format, so you can't use dwtoa to convert it to a string. You need a function that does the same for floating point numbers. Or you can use one of the msvcrt.dll's functions.

DATA SECTION

n1  DQ 1.00416
n2  DQ 15.0
n3  DQ 0
buf DB 100 DUP ?

CODE SECTION

Start:
    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

dedndave

hi Jack

i wrote this little test program
of course, it's 32-bit MASM syntax, but it might help

all you need is a 64-bit equiv of the FloatToStr2 function, which is part of the Masm32 library
i used REAL8's, because that's what the FloatToStr2 function uses

        INCLUDE    \Masm32\Include\Masm32rt.inc

;###############################################################################################

        .DATA

n1  REAL8 1.00416
n2  REAL8 15.0
n3  REAL8 0.0

;***********************************************************************************************

        .DATA?

buf db 20 dup(?)

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

    fld     n1   ; Load n1 into the ST0 register on the FPU stack.
    fdiv    n2   ; Divide it by n2 directly from memory.
    fstp    n3   ; Pop the result off the stack to memory

    INVOKE  FloatToStr2,n3,offset buf
    print   offset buf

        print   chr$(13,10)
        inkey
        INVOKE  ExitProcess,0

main    ENDP

;###############################################################################################

        END     main


result:
0.06694399999999999
Press any key to continue ...

shankle

Thanks Dave and thanks for realizing I'm just a novice with FPU.
I tried your little proggie and the compiler complained that "Floattostr2
was not defined. I was unable to find any trace of it in GoAsm 64.
That does not mean it's not there.

In the mean time Yuris example does not work for me either.
I have no idea what goes in "Result". I would think it would be n3.
Anyway the example with "Result" in it gives errors.

rrr314159

shankle, this suggestion may be useless to you but, just to learn about FPU, u could drop back to 32-bit MASM and do it there. Nothing wrong with GoAsm or 64-bit but there are many more examples in good ol' MASM32 world. Figure it out with that tool, then it's easy to translate to other environments.

This is not to denigrate GoAsm, which looks like fine product, 64-bit, which I prefer, or Yuri's help; but he's only one person; dozens can help with MASM32.
I am NaN ;)

Yuri

Quote from: shankle on March 07, 2015, 07:33:15 AM
Anyway the example with "Result" in it gives errors.
What errors does it give? Did you compile it as a standalone exe or put it in your program? It compiles and runs without errors for me.

shankle

Thanks Yuri,
Your response made me take a closer look at the code I typed.
And yes, I made a typo. :redface:  Your code is now working.

shankle

        3-8-2015
This code gives the wrong value in GoAsm 64-bit
Value should be 0.006
Incorrect value is 280461;

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

    lea rcx,HoldValue   ; value is keyed input

    mov [n1],rcx ; (This is what I don't know how to do)
    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 results off the stack to memory
    invoke msvcrt:sprintf_s,addr buf,sizeof buf,\
                   "%g",[n3]
    invoke TextOut, [hdc],200,345,addr buf,7

dedndave

you want to use FILD (float integer load), instead of FLD (float load)
the value from RCX must be in memory
so, i sometimes just PUSH it on the stack and load it from there

    push    rcx
    fild qword ptr [rsp]   ;we have to tell the assembler the size of the integer
;
;
;
    pop     rcx


i guess, for GoAsm, it would be

    fild    Q[rsp]

dedndave

by the way, when you load an integer into the FPU,
it converts it, internally, to a REAL10 float
(all FPU operations are internally REAL10)

shankle

Just a tad of clarification Dave.
Is [rsp] a typo or the 32-bit esp register?

dedndave

RSP is the 64-bit wide stack pointer, counterpart to the 32-bit ESP

i'm assuming that you are writing 64-bit code