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-25-2015

    n1     dq  0
    buf7  db  9 DUP (0h)
    Value db  '010000.00'

    invoke msvcrt:_atodbl, addr n1,addr Value ;convert string to double
    invoke msvcrt:sprintf_s, addr buf,sizeof buf,\
                   "%g",[n1]
    invoke TextOut, [hdc],200,425,addr buf7,9

   The above drops the ".00"
   If I change Value to '010000.11' it still loses the ".11"
   Not sure if I am asking the question correctly.
   
   Thanks again for all the help.

dedndave

try this line, as a test
invoke TextOut, [hdc],200,425,addr Value,9
verify that the area is large enough to support the string length without clipping

oh - and terminate the Value string with a 0
(not needed for TextOut, but might be for the other functions)

MichaelW

I can't see how it can matter, but the floating-point value is supposed to be wrapped in a structure, see the MSDN documentation. In the time I spent looking I could not find _atodbl in any import library for MSVCRT.DLL, so I used run-time dynamic linking and call instead of invoke. And since the import library that I used did not include sprintf_s, I just used a routine that calls printf.

;==============================================================================
option casemap:none
include \jwasm\inc\windows.inc
include \jwasm\inc\stdio.inc
include \jwasm\inc\stdlib.inc
includelib \jwasm\lib64\kernel32.lib
includelib \jwasm\lib64\msvcrt.lib
include support.asm
;==============================================================================

_getch PROTO

_CRT_DOUBLE struct
    x REAL8 ?
_CRT_DOUBLE ends   

;==============================================================================
.data
    dblval     _CRT_DOUBLE <0.0>     
    sz_msvcrt   db  "msvcrt.dll",0
    sz_atodbl   db  "_atodbl",0
    s0   db "010000.00",0 
    s1   db "010000.11",0 
    s2   db "12345.12345",0 
.code
;============================================================================== 
main proc
    invoke LoadLibrary, ADDR sz_msvcrt
    invoke GetProcAddress, rax, ADDR sz_atodbl   
    mov   rbx, rax   
    sub   rsp, 28h
   
    mov   rcx, OFFSET dblval
    mov   rdx, OFFSET s0   
    call  rbx
    print("%f\n",dblval.x)   

    mov   rcx, OFFSET dblval
    mov   rdx, OFFSET s1   
    call  rbx
    print("%f\n",dblval.x)   
   
    mov   rcx, OFFSET dblval
    mov   rdx, OFFSET s2   
    call  rbx
    print("%f\n",dblval.x)       
   
    invoke _getch
    invoke ExitProcess, 0
main endp
;==============================================================================
end main


Support.asm:

;===================================================================================
; Minimal support components, including several MASM32 macros and one procedure,
; modified and/or renamed as necessary.
;===================================================================================

;include \jwasm\inc\stdio.inc

acfm$ MACRO txt:VARARG

  LOCAL ch1,char,nu$,tmp,flag,lbuf,rbuf,cpos,sln
  ch1 equ <>
  nu$ equ <>
  flag = 0

  ch1 SUBSTR <txt>,1,1              ;; check if 1st character is a quote
  IFDIF ch1,<">
    EXITM <txt>                     ;; exit with original "txt" if it is not
  ENDIF

  FORC char,<txt>                   ;; scan through characters in "txt"

    IFIDN <char>,<\>                ;; increment the flag if "\" escape character
      flag = flag + 1
    ENDIF

  ; -----------------------------------------------

    IF flag EQ 0                    ;; <<< if flag = 0 then normal APPEND character
      nu$ CATSTR nu$,<char>
    ENDIF

    IF flag EQ 1                    ;; <<< if flag = 1 then perform replacement
      IFIDN <char>,<n>
        nu$ CATSTR nu$,<",13,10,">  ;; \n = CRLF
        flag = 0
      ENDIF
      IFIDN <char>,<t>
        nu$ CATSTR nu$,<",9,">      ;; \t = TAB
        flag = 0
      ENDIF
      IFIDN <char>,<q>
        nu$ CATSTR nu$,<",34,">     ;; \q = quote
        flag = 0
      ENDIF
      IFIDN <char>,<0>
        nu$ CATSTR nu$,<",0,">      ;; \0 = embedded zero
        flag = 0
      ENDIF

   ;; ---------------------
   ;; masm specific escapes
   ;; ---------------------
      IFIDN <char>,<l>
        nu$ CATSTR nu$,<",60,">     ;; \l = <
        flag = 0
      ENDIF
      IFIDN <char>,<r>
        nu$ CATSTR nu$,<",62,">     ;; \r = >
        flag = 0
      ENDIF
      IFIDN <char>,<x>
        nu$ CATSTR nu$,<",33,">     ;; \x = !
        flag = 0
      ENDIF
      IFIDN <char>,<a>
        nu$ CATSTR nu$,<",40,">     ;; \a = (
        flag = 0
      ENDIF
      IFIDN <char>,<b>
        nu$ CATSTR nu$,<",41,">     ;; \b = )
        flag = 0
      ENDIF
    ENDIF

    IF flag EQ 2                    ;; <<< if flag = 2 APPEND the "\" character
      IFIDN <char>,<\>
        nu$ CATSTR nu$,<",92,">     ;; \\ = \
        flag = 0
      ENDIF
    ENDIF

  ; -----------------------------------------------

  ENDM

;; ---------------------------------------------
;; strip any embedded <"",> characters sequences
;; ---------------------------------------------
    nu$ CATSTR nu$,<,0,0,0>                 ;; append trailing zeros

    cpos INSTR nu$,<"",>                    ;; test for leading junk
    IF cpos EQ 1
      nu$ SUBSTR nu$,4                      ;; chomp off any leading junk
    ENDIF

    cpos INSTR nu$,<"",>

    WHILE cpos
      lbuf SUBSTR nu$,1,cpos-1              ;; read text before junk
      rbuf SUBSTR nu$,cpos+3                ;; read text after junk
      nu$ equ <>                            ;; clear nu$
      nu$ CATSTR lbuf,rbuf                  ;; concantenate the two
      cpos INSTR nu$,<"",>                  ;; reload cpos for next iteration
    ENDM

    sln SIZESTR nu$
    nu$ SUBSTR nu$,1,sln-6                  ;; trim off tail padding

    .data
      tmp db nu$,0
      align 4
    .code
    EXITM <OFFSET tmp>                      ;; return the DATA section OFFSET
   
ENDM

print MACRO format:REQ, args:VARARG
    IFNB <args>
      invoke printf, acfm$(format), args
    ELSE
      invoke printf, acfm$(format)
    ENDIF
    EXITM <>
ENDM

wait_key proto
_kbhit proto

waitkey MACRO
    invoke wait_key
ENDM

.code
wait_key proc
    ;--------------------------------------------------------------------------
    ; Unlike the MASM32 lib procedure it was derived from, this procedure does
    ; not return the pressed key because it needs to avoid the (not Windows8
    ; compatible) _getch function, and because I simply need to wait for a
    ; keystroke.
    ;--------------------------------------------------------------------------   
    invoke GetStdHandle, STD_INPUT_HANDLE
    invoke FlushConsoleInputBuffer, rax
  @@:
    invoke Sleep, 10
    invoke _kbhit
    test  rax, rax
    jz    @B
    ret
wait_key endp   


And the results:

10000.000000
10000.110000
12345.123450

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

dedndave

it's crt__atodbl in msvcrt.inc   :biggrin:
Jack uses GoAsm, which handles imports differently i guess

MichaelW

I should have specified that I was only looking at the 64-bit components.
Well Microsoft, here's another nice mess you've gotten us into.

shankle

        3-26-2015

    n1          dq  0
    looper     dd  0
    saveesi   dd  0
    buf7       db  '         ',0
    Value      db  '         ',0  ; number keyed in
   
    const
    codecode     STRUCT
    cc1          db     ?
    cc2          db     ?
    cc3          db     ?
    cc4          db     ?
    codecode     ENDS

; program re-enters here 9 times to build the
; keyed input into Value
: keyed in test values: 010000.00 or 010000.11   
.ValueLoop
    mov ecx,[wParam]    ; wParam contains 1 keyed digit of Value
    mov D[cc],ecx
    mov cl,B[cc.cc1]
    mov esi,[saveesi]
    mov B[Value+esi],cl
    inc esi
    mov [saveesi],esi
    inc D[looper]
    cmp D[looper],9
     jne >>.goon     ; goes out and comes back to ValueLoop 9 times

    invoke msvcrt:_atodbl, addr n1,addr Value ;convert string to double
    invoke msvcrt:sprintf_s, addr buf,sizeof buf,\
                   "%g",[n1]
    invoke TextOut, [hdc],200,425,addr buf7,9     ; prints 010000
    invoke TextOut, [hdc],200,425,addr Value,9   ;  prints 010000.00/010000.11

    The above drops the ".00"
    If I change the keyed Value to '010000.11',0 it still loses the ".11"
    msvcrt:_atodbl can be found on the Microsoft site by keying in _atodbl.
    Hope I did a better job this time.