The MASM Forum

General => The Workshop => Topic started by: clamicun on November 05, 2015, 07:23:30 AM

Title: Help on simple mathematics
Post by: clamicun on November 05, 2015, 07:23:30 AM
include \masm32\MasmBasic\MasmBasic.inc   
include ..\cmctools\cmc_macros.inc

include \masm32\include\Shlwapi.inc
includelib \masm32\lib\Shlwapi.lib

include \masm32\include\msvcrt.inc
   
value   dd ?
result  dd ?

;result2 dq ?  ;??? for atof

;The inputs are from a dialogbox in my programm, which takes care to exclusively accept - . and 0 to 9.
;After processing they will be uploaded to mysql.

test1_input1  db "200",0
test1_input2  db "470",0
test1_input3  db "100",0

test2_input1  db "200.55",0

result_buffer db 30 dup(?),0
show_result   db "%s + %s  - %s = %s",0
showeax       db "%li",0

output        db 30 dup(?),0

;=====================
.code
start:

INVOKE crt_atoi,offset test1_input1
push eax

INVOKE crt_atoi,offset test1_input2
mov value,eax

pop eax
add eax,value
mov result,eax

INVOKE crt_atoi,offset test1_input3
sub result,eax

INVOKE crt__itoa,result,offset result_buffer,10

INVOKE wsprintf,offset output,offset show_result,offset test1_input1,offset test1_input2,offset test1_input3,offset result_buffer
INVOKE MessageBox,0,offset output,0,0

;ok that is easy, but I nedd to do this with inputs like (for example) 200.55 

;----------------------------
;After hours in the net I guess it might be atof. Hundreds of entries and not one asm example. 
;atof converts a string to double.... returns a double value.
;But where is the result ?
;The return of itoa is in a given buffer, so the atof result should be in eax. 
;I obviously do not understand this function.
;The value in eax is different every time. That does not make sense or the syntax is wrong.
;Please - can someone explain it to me or give me a link, which explains it understandably.

xor eax,eax
INVOKE crt_atof,offset test2_input1

INVOKE wsprintf,offset output,offset showeax,eax
INVOKE MessageBox,0,offset output,0,0

INVOKE ExitProcess,0
end start


;=====================
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 07:34:34 AM
use crt__atodbl

    INVOKE  crt__atodbl,offset real8value,offset inpstring
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 07:35:58 AM
if you have a fixed or limited number of decimal digits, you could also use fixed-point math

i.e., 200.55 might be stored as 20055 or 200550
Title: Re: Help on simple mathematics
Post by: jj2007 on November 05, 2015, 07:59:00 AM
  INVOKE crt_atof,offset test2_input1
  deb 1, "There it is:", ST(0)
;)
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 08:17:42 AM
 :t

took me a minute to figure that out - it's in the top register of the FPU   :P
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 08:27:20 AM
by the way....

it depends on the range and precision required
you may be able to use single-precision values (REAL4)

single precision: ~ -3.438 to +3.438, precision = 24 bits
double precision: ~ -1.79308 to +1.79308, precision = 53 bits
Title: Re: Help on simple mathematics
Post by: jj2007 on November 05, 2015, 08:36:11 AM
Quote from: dedndave on November 05, 2015, 08:27:20 AMit depends on the range and precision required

crt is by default real8=double, assembler allows real10:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
.data
test2_input1  db "200.55", 0
test4      REAL4 ?
  Init
  INVOKE crt_atof, offset test2_input1      ; real8 precision
  MovVal ST(0), offset test2_input1      ; real10 precision
  fst test4
  deb 4, "There they are:", ST(0), ST(1), test4
  Inkey Str$("test4\t\t%Jf", test4)
EndOfCode


Output:
There they are:
ST(0)           200.5500000000000000
ST(1)           200.5500000000000114
test4           200.5500
test4           200.5500030517578125
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 08:39:36 AM
right - i normally use REAL10 - just because that's the FPU "native language", so to speak

well - for intermediate calculations, i do
for user I/O, 7 digits is enough for most real-world stuff
except when talking about times or frequencies - lol

example.....
a mile is 5280 feet
if we use 7 digits, that might be 5280.000 feet

0.001 feet is 0.012 inches
that's like measuring a mile with dial calipers
Title: Re: Help on simple mathematics
Post by: clamicun on November 05, 2015, 10:46:39 AM
dedndave, jj ,good evening and many thanks.

Lots of info to think about.
FPU is quite new to me.

The examples of jj work well, like always, but I do not know what to do with the results.
Like I wrote above - I will add one input to the other or others, convert that result back into a string and upload it to mysql.

I guess the result in the messagebox  or in the console  is ST(0).
How do I process it ?

--------------------
INVOKE  crt__atodbl,offset real8value,offset inpstring

Sounds good. ascii to double. That is what I want.
Could you be a bit more explicit on the two parameters, please.
atof has only one.

Ok. - ate ja

INVOKE  crt__atodbl,offset real8value,offset inpstring
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 12:05:27 PM
the first argument points to a REAL8 (the address of the location, offset)

    .DATA?

r8SomeName REAL8 ?


the second argument points to the string buffer
it should contain an ascii string in the general form
-1.123E-3
1.0
will also work - and, the string should be terminated with a NUL

if you want to add a series of real's, you will want to use the FPU
adding a few numbers together is not that hard
you should look at Ray's tutorial
FLD, FST, FSTP, FADD, FADDP, FFREE are the instructions of interest

http://www.ray.masmcode.com/tutorial/index.html (http://www.ray.masmcode.com/tutorial/index.html)
Title: Re: Help on simple mathematics
Post by: dedndave on November 05, 2015, 03:33:33 PM
result:
8.888

Press any key to continue ...


code:
;###############################################################################################

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .686p
        .MMX
        .XMM
        .List

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

        .DATA
        ALIGN   8

r8Val1   REAL8 1.225
r8Val2   REAL8 2.122
r8Val3   REAL8 5.541

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

        .DATA?
        ALIGN   8

r8Result REAL8 ?
szBuffer db    20 dup(?)

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

        .CODE

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

main    PROC

    fld     r8Val1          ;float load          - r8Val1 is in ST(0)
    fadd    r8Val2          ;float add           - r8Val2 is added to ST(0)
    fadd    r8Val3          ;float add           - r8Val3 is added to ST(0)
    fstp    r8Result        ;float store and pop - ST(0) is stored in r8Result, and ST(0) is emptied

    INVOKE  FloatToStr,r8Result,offset szBuffer
    print   offset szBuffer,13,10

    print   chr$(13,10)
    inkey
    exit

main    ENDP

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

        END     main
Title: Re: Help on simple mathematics
Post by: jj2007 on November 05, 2015, 07:14:03 PM
Quote from: clamicun on November 05, 2015, 10:46:39 AMLike I wrote above - I will add one input to the other or others, convert that result back into a string and upload it to mysql.

Why don't you simply use Str$()?

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
.data
Some8      REAL8 11111.11111
Some4      REAL4 22222.22222
SomeDw      dd 33333

  Init
  Let esi=Str$(Some4/Some8*SomeDw/1000)      ; ca. 22/11*33.333 = 66
;   SendData "MyClient", esi      ; whatever works
;   FileWrite "Result.txt", esi      ; for sending to MySQL
  Inkey esi
EndOfCode


Output: 66.66600

Attention, there is no operator precedence: 20+50*3 = 210 (wrong), so use 50*3+20 instead.

BTW it would be nice to see a simple MySql example application here. Can you cook up something?
Title: Re: Help on simple mathematics
Post by: clamicun on November 06, 2015, 06:57:19 AM
jj, dedndave thank you guys very much.

ok - I know how it will work. (various possibilities).

Because the input is always like  '12345.67'  or  '-12345.67'

dedndave's idea to  simply delete the  '.' , treat it as signed integer
and finally write   '.'   two bytes before the end of the string. 

is probably the easiest method, but I'll have to check it out.

I'll send an example of how to work with mysql.
Must write a simple demoversion.
Looks like php.

Good night, clamicun
Title: Re: Help on simple mathematics
Post by: raymond on November 07, 2015, 03:38:55 AM
If you intend to go with fixed point, you may get some more info from the "Fixed point math" section which you can access from the main page at:
http://www.ray.masmcode.com/

You can also access the FPU tutorial and the Fpulib from that site. The Fpulib comes with the source code of each function where you can learn how various operations are performed.
Title: Re: Help on simple mathematics
Post by: jj2007 on November 07, 2015, 04:59:38 AM
Quote from: clamicun on November 06, 2015, 06:57:19 AM
Because the input is always like  '12345.67'  or  '-12345.67'

Str$() is perhaps the easiest option, but if you want a solution with plain Masm32, here it is:

include \masm32\include\masm32rt.inc

.data
a$ db "123.456", 0
b$ db "321.432", 0
Result REAL8 ?

.code
start:
  invoke crt_atof, offset a$ ; load 1st result to ST(0)
  invoke crt_atof, offset b$ ; load 2nd result to ST(0), move 1st to ST(1)
  fadd ; add ST(0)+ST(1)
  fstp Result ; pop result from FPU to REAL8 variable
  printf("The result is %f", Result)
  inkey " - ok?"
  exit

end start
Title: Re: Help on simple mathematics
Post by: MichaelW on January 12, 2016, 07:53:40 PM
Why use _atodbl?

Per this page (https://msdn.microsoft.com/en-us/library/5948ysye.aspx) the special feature is that the function does not generate floating-point code.

And the double is packed in a _CRT_DOUBLE structure:


  typedef struct {
    double x;
  } _CRT_DOUBLE;


Sorry about the C code, but it's the only way I have to test this ATM:


#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main(void)
{
_CRT_DOUBLE value;

printf("%d\n", _atodbl( &value, "3.14159265358979323846264"));
printf("%.20f\n", value.x);

_getch();
}



0
3.14159265358979310000

Title: Re: Help on simple mathematics
Post by: jj2007 on January 12, 2016, 09:13:12 PM
Quote from: MichaelW on January 12, 2016, 07:53:40 PMSorry about the C code

POLINK: error: Unresolved external symbol '__atodbl' ::)
Title: Re: Help on simple mathematics
Post by: MichaelW on January 12, 2016, 11:34:30 PM
Quote from: jj2007 on January 12, 2016, 09:13:12 PM
POLINK: error: Unresolved external symbol '__atodbl' ::)

I used a recent 64-bit MinGW, selected originally because it supports 64-bit code in inline assembly. The function I could not make work was  _atoldbl, no error but the _LDOUBLE value returned doesn't make sense.
Title: Re: Help on simple mathematics
Post by: TWell on January 13, 2016, 07:41:05 AM
Difference
C90FDAA22168C235
C90FDAA22168C233

.386
.model flat, stdcall
option casemap:none

printf proto cdecl :vararg
exit proto cdecl :dword
_atoldbl proto cdecl :dword, :dword
includelib msvcr100.lib


.data
sPI db "3.14159265358979323846264", 0
nPI dt 3.14159265358979323846264;338327
fmt db "%llX", 13, 10, 0
re10 real10 0

.code
start proc
invoke _atoldbl, addr re10, addr sPI
invoke printf, addr fmt, re10
invoke printf, addr fmt, nPI
invoke exit, 0
start endp
end start