News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Suggestion with MSVCRT code.

Started by hutch--, June 06, 2005, 04:59:13 AM

Previous topic - Next topic

hutch--

Greg,

These look good and should be a great improvement in the handling of such a wide range of data types. If you are happy enough that they are reliable, I would like to add them to the macros.asm file for MASM32 as I have been doing a lot of work on it recently myself.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

You bet. But I haven't done any testing of them besides the program I posted. I made a few corrections a few minutes after I first posted it, cleanup stuff, so get the latest version. Maybe some other folks will try them out.

Any idea why I was having problems using fn and invoke in the macros?


hutch--

Greg,

I am not sure but I notice that you are zero extending the byte values to DWORD so the invoke syntax may not be handling this correctly. The "fn" macro uses invoke.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

Yeah, that's where the problem was, invoke was not handling it correctly. Same thing with some of the other types.

I did it this way so that you would get an assembly error if you passed anything other than the correct type:


    mov   al, bytevalue
    movzx eax, al
    push  eax


instead of


    movzx eax, bytevalue




hutch--

Yes,

I got the same results. I played with the first two and you can use invoke with them if you extend the data size to DWORD. Here are the two tested versions. There is no reason to change the manual layout as invoke does not do it any better but I have one suggestion, the format strings only need to be defined once so I put them in an IFNDEF block and reduced the buffer data sizes to the next aligned size after the maximum size that can be written to the data in characters.


ubyte$ MACRO bytevalue:req
  LOCAL buffer
  .data?
    buffer db 4 dup (?)
    IFNDEF ubfmt
    .data
      ubfmt db "%u",0
    ENDIF
  .code
  mov al, bytevalue
  movzx eax, al
  invoke crt_sprintf,OFFSET buffer,OFFSET ubfmt,eax
  EXITM <OFFSET buffer>
ENDM

sbyte$ MACRO bytevalue:req
  LOCAL buffer
  .data?
    buffer db 4 dup (?)
    IFNDEF sbfmt
    .data
      sbfmt db "%d",0
    ENDIF
  .code
  mov al, bytevalue
  movsx eax, al
  invoke crt_sprintf,OFFSET buffer,OFFSET sbfmt,eax
  EXITM <OFFSET buffer>
ENDM
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

Quote
IFNDEF
good idea

For sbyte$ max bytes is 5 ("-128",0) :bg

tomorrow ...


hutch--

Yep,

You are right actually, problem is with counting with your fingers is you don't get signed values all that well.  :red
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

#52
I updated the 'number to string' macros in my earlier post as there were some problems I discovered. The qwords were being pushed incorrectly. I also added the IFNDEF for the format strings, changed the buffer lengths and added some more testing.

I deleted a question that was here because the light just went on, doh! I need to take a break.  ::)

hutch--

Greg,

These are testing up fine at this end, they look like they are ready to rock 'n roll.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL


GregL

#55
String input using C Run-Time Library fgets function.


.586
.MODEL FLAT, stdcall
option casemap:none

include windows.inc

include kernel32.inc
include user32.inc
;include masm32.inc
include msvcrt.inc

include c:\masm32\macros\macros.asm

includelib kernel32.lib
includelib user32.lib
;includelib masm32.lib
includelib msvcrt.lib

;-----------------------------------------------------
linein MACRO
    LOCAL buffer
    .data?
        buffer BYTE 96 dup(?)
    IFNDEF strFmt   
    .data
        strFmt BYTE "%s", 0
    ENDIF
    IFNDEF Cr
    .data
        dwNewLine DWORD 10
    ENDIF   
    .code   
    invoke crt_fgets, ADDR buffer, SIZEOF buffer, crt__iob
    push eax
    invoke crt_strchr, ADDR buffer, dwNewLine
    .if eax
        mov BYTE PTR [eax], 0   ; remove the newline from buffer
    .endif   
    pop eax
    EXITM <eax>
ENDM   
;-----------------------------------------------------
WaitKey MACRO
    LOCAL crlf, pak
    .data
        szCrLf BYTE 13, 10, 0
        szPAK  BYTE 13, 10, "Press any key to continue...", 0
    .code   
        invoke crt_printf, ADDR szPAK         
        call crt__getch
        .if (eax == 0) || (eax == 0E0h)
            call crt__getch
        .endif
        invoke crt_printf, ADDR szCrLf
ENDM
;-----------------------------------------------------

.DATA

    lpInput DWORD 0
    msg1    BYTE "Enter some text: ", 0
    msg2    BYTE "You entered:     %s", 13, 10, 0

.CODE

start:
   
    invoke crt_printf, ADDR msg1
    mov lpInput, linein()
    invoke crt_printf, ADDR msg2, lpInput
   
    WaitKey
    invoke ExitProcess, 0

end start


GregL

#56
'String to number' procedures using the C Run-Time function sscanf.


; 'String to number' procedures that use
; the C Run-Time Library function sscanf.
; Greg Lyon - 2005
;
.586
.MODEL FLAT, stdcall
option casemap:none

include windows.inc

include kernel32.inc
include user32.inc
include masm32.inc
include msvcrt.inc

include c:\masm32\macros\macros.asm ; uses the file dated July 10, 2005

includelib kernel32.lib
includelib user32.lib
includelib masm32.lib
includelib msvcrt.lib

atoubyte     PROTO pStr:PTR BYTE, pUb :PTR BYTE
atosbyte     PROTO pStr:PTR BYTE, pSb :PTR SBYTE
ahextoubyte  PROTO pStr:PTR BYTE, pUb :PTR BYTE
atouword     PROTO pStr:PTR BYTE, pUw :PTR WORD
atosword     PROTO pStr:PTR BYTE, pSw :PTR SWORD
ahextouword  PROTO pStr:PTR BYTE, pUw :PTR WORD
atoudword    PROTO pStr:PTR BYTE, pUdw:PTR DWORD
atosdword    PROTO pStr:PTR BYTE, pSdw:PTR SDWORD
ahextoudword PROTO pStr:PTR BYTE, pUdw:PTR DWORD
atouqword    PROTO pStr:PTR BYTE, pUqw:PTR QWORD
atosqword    PROTO pStr:PTR BYTE, pSqw:PTR QWORD
ahextouqword PROTO pStr:PTR BYTE, pUqw:PTR QWORD
atoreal4     PROTO pStr:PTR BYTE, pR4 :PTR REAL4
atoreal8     PROTO pStr:PTR BYTE, pR8 :PTR REAL8
atoreal10    PROTO pStr:PTR BYTE, pR10:PTR REAL10

.DATA

szUbyMin BYTE   "0",0
szUbyMax BYTE   "255",0
szSbyMin BYTE  "-128",0
szSbyMax BYTE   "127",0
szUwdMin BYTE   "0",0
szUwdMax BYTE   "65535",0
szSwdMin BYTE  "-32768",0
szSwdMax BYTE   "32767",0
szUdwMin BYTE   "0",0
szUdwMax BYTE   "4294967295",0
szSdwMin BYTE  "-2147483648",0
szSdwMax BYTE   "2147483647",0
szUqwMin BYTE   "0",0
szUqwMax BYTE   "18446744073709551615",0
szSqwMin BYTE  "-9223372036854775808",0
szSqwMax BYTE   "9223372036854775807",0
szR4Min  BYTE  "-1.175494351E-38",0
szR4Max  BYTE   "3.402823466E+38",0
szR8Min  BYTE  "-2.2250738585072014E-308",0
szR8Max  BYTE   "1.7976931348623158E+308",0
szR10Min BYTE  "-2.2250738585072014E-308",0
szR10Max BYTE   "1.7976931348623158E+308",0
szHexBy  BYTE  "FF", 0
szHexWd  BYTE  "FFFF", 0
szHexDw  BYTE  "FFFFFFFF", 0
szHexQw  BYTE  "FFFFFFFFFFFFFFFF", 0
   
align 16
r10Max   REAL10 0.0
r10Min   REAL10 0.0
r8Max    REAL8  0.0
r8Min    REAL8  0.0
r4Max    REAL4  0.0
r4Min    REAL4  0.0
uqwMax   QWORD  0
uqwMin   QWORD  0
sqwMax   QWORD  0
sqwMin   QWORD  0
udwMax   DWORD  0
udwMin   DWORD  0
sdwMax   SDWORD 0
sdwMin   SDWORD 0
uwdMax   WORD   0
uwdMin   WORD   0
swdMax   SWORD  0
swdMin   SWORD  0
ubyMax   BYTE   0
ubyMin   BYTE   0
sbyMax   SBYTE  0
sbyMin   SBYTE  0

.CODE

start:

    ; decimal string to unsigned byte
    invoke atoubyte, ADDR szUbyMax, ADDR ubyMax
    print ubyte$(ubyMax)
    print SADD(13,10)
    invoke atoubyte, ADDR szUbyMin, ADDR ubyMin
    print ubyte$(ubyMin)
    print SADD(13,10,13,10)

    ; decimal string to signed byte
    invoke atosbyte, ADDR szSbyMax, ADDR sbyMax
    print sbyte$(sbyMax)
    print SADD(13,10)
    invoke atosbyte, ADDR szSbyMin, ADDR sbyMin
    print sbyte$(sbyMin)
    print SADD(13,10,13,10)
   
    ; hex string to unsigned byte
    invoke ahextoubyte, ADDR szHexBy, ADDR ubyMax
    print xbyte$(ubyMax)
    print SADD(13,10)
    invoke ahextoubyte, ADDR szUbyMin, ADDR ubyMin
    print xbyte$(ubyMin)
    print SADD(13,10,13,10)
   

    ; decimal string to unsigned word
    invoke atouword, ADDR szUwdMax, ADDR uwdMax
    print uword$(uwdMax)
    print SADD(13,10)   
    invoke atouword, ADDR szUwdMin, ADDR uwdMin
    print uword$(uwdMin)
    print SADD(13,10,13,10)   
   
    ; decimal string to signed word
    invoke atosword, ADDR szSwdMax, ADDR swdMax
    print sword$(swdMax)
    print SADD(13,10)   
    invoke atosword, ADDR szSwdMin, ADDR swdMin
    print sword$(swdMin)
    print SADD(13,10,13,10)
   
    ; hex string to unsigned word
    invoke ahextouword, ADDR szHexWd, ADDR uwdMax
    print xword$(uwdMax)
    print SADD(13,10)   
    invoke ahextouword, ADDR szUwdMin, ADDR uwdMin
    print xword$(uwdMin)
    print SADD(13,10,13,10)   
       
   
    ; decimal string to unsigned dword
    invoke atoudword, ADDR szUdwMax, ADDR udwMax
    print udword$(udwMax)
    print SADD(13,10)
    invoke atoudword, ADDR szUdwMin, ADDR udwMin
    print udword$(udwMin)
    print SADD(13,10,13,10)   
   
    ; decimal string to signed dword
    invoke atosdword, ADDR szSdwMax, ADDR sdwMax
    print sdword$(sdwMax)
    print SADD(13,10)
    invoke atosdword, ADDR szSdwMin, ADDR sdwMin
    print sdword$(sdwMin)
    print SADD(13,10,13,10)
   
    ; hex string to unsigned dword
    invoke ahextoudword, ADDR szHexDw, ADDR udwMax
    print xdword$(udwMax)
    print SADD(13,10)
    invoke ahextoudword, ADDR szUdwMin, ADDR udwMin
    print xdword$(udwMin)
    print SADD(13,10,13,10)
   
   
    ; decimal string to unsigned qword
    invoke atouqword, ADDR szUqwMax, ADDR uqwMax
    print uqword$(uqwMax)
    print SADD(13,10)
    invoke atouqword, ADDR szUqwMin, ADDR uqwMin
    print uqword$(uqwMin)
    print SADD(13,10,13,10)
   
    ; decimal string to signed qword
    invoke atosqword, ADDR szSqwMax, ADDR sqwMax
    print sqword$(sqwMax)
    print SADD(13,10)
    invoke atosqword, ADDR szSqwMin, ADDR sqwMin
    print sqword$(sqwMin)
    print SADD(13,10,13,10)
   
    ; hex string to unsigned qword
    invoke ahextouqword, ADDR szHexQw, ADDR uqwMax
    print xqword$(uqwMax)
    print SADD(13,10)
    invoke ahextouqword, ADDR szUqwMin, ADDR uqwMin
    print xqword$(uqwMin)
    print SADD(13,10,13,10)
   
   
    ; real4
    invoke atoreal4, ADDR szR4Max, ADDR  r4Max
    print real4$(r4Max)
    print SADD(13,10)
    invoke atoreal4, ADDR szR4Min, ADDR r4Min
    print real4$(r4Min)
    print SADD(13,10,13,10)
   
    ; real8
    invoke atoreal8, ADDR szR8Max, ADDR  r8Max
    print real8$(r8Max)
    print SADD(13,10)
    invoke atoreal8, ADDR szR8Min, ADDR r8Min
    print real8$(r8Min)
    print SADD(13,10,13,10)
   
    ; real10
    invoke atoreal10, ADDR szR10Max, ADDR  r10Max
    print real10$(r10Max)
    print SADD(13,10)
    invoke atoreal10, ADDR szR10Min, ADDR r10Min
    print real10$(r10Min)
    print SADD(13,10,13,10)
   
    invoke ExitProcess, 0

;---------------------------------------
atoubyte PROC pStr:PTR BYTE, pUb:PTR BYTE
    .data
       align 4
       ub DWORD 0   
    IFNDEF ubfmt   
    .data
        ubfmt BYTE "%hhu",0
    ENDIF 
    .code
    invoke crt_sscanf, pStr, ADDR ubfmt, ADDR ub
    mov eax, ub
    mov edx, pUb
    mov BYTE PTR [edx], al 
    ret
atoubyte ENDP 
;---------------------------------------
atosbyte PROC pStr:PTR BYTE, pSb:PTR SBYTE
    IFNDEF sb
    .data
       align 4
       sb SDWORD 0   
    ENDIF   
    IFNDEF sbfmt   
    .data
        sbfmt BYTE "%hhd",0
    ENDIF 
    .code
    invoke crt_sscanf, pStr, ADDR sbfmt, ADDR sb
    mov eax, sb
    mov edx, pSb
    mov SBYTE PTR [edx], al
    ret
atosbyte ENDP 
;---------------------------------------
ahextoubyte PROC pStr:PTR BYTE, pUb:PTR BYTE
    IFNDEF ub
    .data
       align 4
       ub DWORD 0   
    ENDIF   
    IFNDEF xbfmt   
    .data
        xbfmt BYTE "%hhX",0
    ENDIF 
    .code
    invoke crt_sscanf, pStr, ADDR xbfmt, ADDR ub
    mov eax, ub
    mov edx, pUb
    mov BYTE PTR [edx], al 
    ret
ahextoubyte ENDP 
;---------------------------------------
atouword PROC pStr:PTR BYTE, pUw:PTR WORD
    IFNDEF uw
    .data
       align 4
       uw DWORD 0   
    ENDIF   
    IFNDEF uwfmt   
    .data
        uwfmt BYTE "%hu",0
    ENDIF
    .code
    invoke crt_sscanf, pStr, ADDR uwfmt, ADDR uw
    mov eax, uw
    mov edx, pUw
    mov WORD PTR [edx], ax   
    ret
atouword ENDP   
;---------------------------------------
atosword PROC pStr:PTR BYTE, pSw:PTR SWORD
    IFNDEF sw
    .data
       align 4
       sw SDWORD 0   
    ENDIF   
    IFNDEF swfmt   
    .data
        swfmt BYTE "%hd",0
    ENDIF 
    .code
    invoke crt_sscanf, pStr, ADDR swfmt, ADDR sw
    mov eax, sw
    mov edx, pSw
    mov SWORD PTR [edx], ax     
    ret
atosword ENDP   
;---------------------------------------
ahextouword PROC pStr:PTR BYTE, pUw:PTR WORD
    IFNDEF uw
    .data
       align 4
       uw DWORD 0   
    ENDIF   
    IFNDEF xwfmt   
    .data
        xwfmt BYTE "%hX",0
    ENDIF
    .code
    invoke crt_sscanf, pStr, ADDR xwfmt, ADDR uw
    mov eax, uw
    mov edx, pUw
    mov WORD PTR [edx], ax   
    ret
ahextouword ENDP   
;---------------------------------------
atoudword PROC pStr:PTR BYTE, pUdw:PTR DWORD
    IFNDEF udw
    .data
        align 4
        udw DWORD 0   
    ENDIF   
    IFNDEF udwfmt   
    .data
        udwfmt BYTE "%u",0
    ENDIF
    .code
    invoke crt_sscanf, pStr, ADDR udwfmt, ADDR udw
    mov eax, udw
    mov edx, pUdw
    mov DWORD PTR [edx], eax
    ret
atoudword ENDP   
;---------------------------------------
atosdword PROC pStr:PTR BYTE, pSdw:PTR SDWORD
    IFNDEF sdw
    .data
       align 4
       sdw SDWORD 0   
    ENDIF   
    IFNDEF sdwfmt   
    .data
        sdwfmt BYTE "%d",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR sdwfmt, ADDR sdw
    mov eax, sdw
    mov edx, pSdw
    mov SDWORD PTR [edx], eax   
    ret
atosdword ENDP   
;---------------------------------------
ahextoudword PROC pStr:PTR BYTE, pUdw:PTR DWORD
    IFNDEF udw
    .data
        align 4
        udw DWORD 0   
    ENDIF   
    IFNDEF xdwfmt   
    .data
        xdwfmt BYTE "%X",0
    ENDIF
    .code
    invoke crt_sscanf, pStr, ADDR xdwfmt, ADDR udw
    mov eax, udw
    mov edx, pUdw
    mov DWORD PTR [edx], eax
    ret
ahextoudword ENDP   
;---------------------------------------
atouqword PROC pStr:PTR BYTE, pUqw:PTR QWORD
    IFNDEF uqw
    .data
       align 8
       uqw QWORD 0   
    ENDIF   
    IFNDEF uqwfmt   
    .data
        uqwfmt BYTE "%I64u",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR uqwfmt, ADDR uqw
    mov edx, pUqw
    mov eax, DWORD PTR [uqw+4]
    mov DWORD PTR [edx+4], eax
    mov eax, DWORD PTR [uqw+0]
    mov DWORD PTR [edx+0], eax
    ret
atouqword ENDP   
;---------------------------------------
atosqword PROC pStr:PTR BYTE, pSqw:PTR QWORD
    IFNDEF sqw
    .data
       align 8
       sqw QWORD 0   
    ENDIF   
    IFNDEF sqwfmt   
    .data
        sqwfmt BYTE "%I64d",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR sqwfmt, ADDR sqw
    mov edx, pSqw
    mov eax, DWORD PTR [sqw+4]
    mov DWORD PTR [edx+4], eax
    mov eax, DWORD PTR [sqw+0]
    mov DWORD PTR [edx+0], eax
    ret
atosqword ENDP   
;-------------------------------------------
ahextouqword PROC pStr:PTR BYTE, pUqw:PTR QWORD
    IFNDEF uqw
    .data
       align 8
       uqw QWORD 0   
    ENDIF   
    IFNDEF xqwfmt   
    .data
        xqwfmt BYTE "%I64X",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR xqwfmt, ADDR uqw
    mov edx, pUqw
    mov eax, DWORD PTR [uqw+4]
    mov DWORD PTR [edx+4], eax
    mov eax, DWORD PTR [uqw+0]
    mov DWORD PTR [edx+0], eax
    ret
ahextouqword ENDP   
;---------------------------------------
atoreal4 PROC pStr:PTR BYTE, pR4:PTR REAL4
    IFNDEF r4fmt   
    .data
        r4fmt BYTE "%f",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR r4fmt, pR4
    ret
atoreal4 ENDP   
;-------------------------------------------
atoreal8 PROC pStr:PTR BYTE, pR8:PTR REAL8
    IFNDEF r8fmt   
    .data
        r8fmt BYTE "%lf",0
    ENDIF
    .code
    invoke crt_sscanf, pStr, ADDR r8fmt, pR8
    ret
atoreal8 ENDP   
;--------------------------------------------
atoreal10 PROC pStr:PTR BYTE, pR10:PTR REAL10
    IFNDEF r8
    .data
       align 8
       r8 REAL8 0.0
    ENDIF   
    IFNDEF r8fmt   
    .data
        r8fmt BYTE "%lf",0
    ENDIF   
    .code
    invoke crt_sscanf, pStr, ADDR r8fmt, ADDR r8
    mov eax, pR10
    finit
    fld r8
    fstp REAL10 PTR [eax]
    ret
atoreal10 ENDP
;--------------------------------------------

end start







[attachment deleted by admin]

GregL

#57
Updated above, changed data in procedures to LOCAL.

Updated again, eliminated unnecessary code.

I'm done for tonight.  :bg

Updated again, added hex string support.

 

hutch--

Thanks Greg,

Another masterpiece.  :U
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

This is an unrelated question. Whenever I have tried to use the internal notation within a quoted string of \t or \n I only ever get those characters as literals in the displayed string and not the TAB or CRLF. Am I missing something in how I format the strings.


fn crt_printf,"%s","This \t is a test\n"


I have checked the macros 1st pass and the normal string content is written to the .DATA section so it is passed as a normal zero terminated string.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php