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

Howard,

Sad to say I tried that one but it just displays the \\n in the text. I think Greg is right that the compiler expands the text before its sent to the procedure.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

hutch--

Greg,

Here is some macro code that may be useful as well.


    % echo num2str(TYPE(reg))

      IF TYPE(reg) NE 4
        echo ------------------------
        echo 32 bit register required
        echo ------------------------
        .err
      ENDIF


I can get TYPE to recognise 2, 4 and 10 byte registers. It fails on 1 byte regs and does not appear to work correctly on mm or xmm registers.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

Just using TYPE would be simpler. It seems to be the same as using just SIZE. What's eluding me is how to determine if a 32-bit variable is a REAL4 or not. I have been reading the MASM manuals and I don't see a way to do it. MASM doesn't seem to differentiate between DWORD and REAL4 or QWORD and REAL8. They seem to be just aliases. I like to use them though for clarity. You could use FXAM but that would only tell you whether a number is a valid floating-point or not, which the bit pattern of many integers would be considered as.

One thing I don't like about the current macro is you can't pass a REAL4 in a 32-bit register, as FLD won't load a CPU register.

What do you think of this, it does the size checking and allows passing a REAL4 in a 32-bit register too.

;; ----------------------------------------------
real4$ MACRO r4value:req
    LOCAL buffer, r8value, r4tmp
    .data?
        r4tmp   REAL4 ?
        r8value REAL8 ?
        buffer  BYTE  48 dup(?)
    IFNDEF r8fmt   
    .data
        r8fmt   BYTE "%lf", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        push   r4value
        pop    r4tmp
        finit
        fld    r4tmp
        fstp   r8value
        fwait
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------



GregL

#78
I think I have it now. The macros accept both memory and register variables.

sprintf macros


.586
.MODEL FLAT, stdcall
option casemap:none

include c:\masm32\include\windows.inc

include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\masm32.inc
include c:\masm32\include\msvcrt.inc

include c:\masm32\macros\macros.asm

includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\lib\msvcrt.lib

;; ----------------------------------------------
isregister MACRO tst
    IF op_type(tst) EQ 4
        EXITM <1>
    ELSE
        EXITM <0>
    ENDIF
ENDM   
;; ----------------------------------------------
ubyte$ MACRO ubytevalue:req
    ; unsigned byte
    LOCAL buffer, ubtmp
    .data?
        ubtmp  BYTE ?
        buffer BYTE 4 dup(?)
    IFNDEF ubfmt   
    .data   
        ubfmt  BYTE "%hhu", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(ubytevalue)
            mov   ubtmp, ubytevalue
            movzx eax, ubtmp
        ELSE
            mov   al, ubytevalue
            movzx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR ubfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
sbyte$ MACRO sbytevalue:req
    ; signed byte
    LOCAL buffer, sbtmp
    .data?
        sbtmp  SBYTE ?
        buffer BYTE  8 dup(?)
    IFNDEF sbfmt     
    .data   
        sbfmt  BYTE "%hhd", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(sbytevalue)
            mov   sbtmp, sbytevalue
            movsx eax, sbtmp
        ELSE     
            mov   al, sbytevalue
            movsx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR sbfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
xbyte$ MACRO xbytevalue:req
    ; unsigned hex byte
    LOCAL buffer, xbtmp
    .data?
        xbtmp  BYTE ?
        buffer BYTE 4 dup(?)
    IFNDEF xbfmt   
    .data   
        xbfmt  BYTE "%hhX", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(xbytevalue)
            mov   xbtmp, xbytevalue
            movzx eax, xbtmp
        ELSE
            mov   al, xbytevalue
            movzx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR xbfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
uword$ MACRO uwordvalue:req
    ; unsigned word
    LOCAL buffer, uwtmp
    .data?
        uwtmp  WORD ?
        buffer BYTE 8 dup(?)
    IFNDEF uwfmt   
    .data   
        uwfmt  BYTE "%hu", 0
    ENDIF   
    .code
        mov   buffer[0], 0
        IF isregister(uwordvalue)
            mov   uwtmp, uwordvalue
            movzx eax, uwtmp
        ELSE       
            mov   ax, uwordvalue
            movzx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR uwfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
sword$ MACRO swordvalue:req
    ; signed word
    LOCAL buffer, swtmp
    .data?
        swtmp  SWORD ?
        buffer BYTE  8 dup(?)
    IFNDEF swfmt   
    .data   
        swfmt  BYTE "%hd", 0
    ENDIF   
    .code
        mov   buffer[0], 0
        IF isregister(swordvalue)
            mov   swtmp, swordvalue
            movsx eax, swtmp
        ELSE   
            mov   ax, swordvalue
            movsx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR swfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
xword$ MACRO xwordvalue:req
    ; unsigned hex word
    LOCAL buffer, xwtmp
    .data?
        xwtmp  WORD ?
        buffer BYTE 8 dup(?)
    IFNDEF xwfmt   
    .data   
        xwfmt  BYTE "%hX", 0
    ENDIF   
    .code
        mov   buffer[0], 0
        IF isregister(xwordvalue)
            mov   xwtmp, xwordvalue
            movzx eax, xwtmp
        ELSE               
            mov   ax, xwordvalue
            movzx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR xwfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
udword$ MACRO udwordvalue:req
    ; unsigned dword
    LOCAL buffer, udtmp
    .data?
        udtmp  DWORD ?
        buffer BYTE  12 dup(?)
    IFNDEF udfmt   
    .data   
        udfmt  BYTE "%lu", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(udwordvalue)
            mov udtmp, udwordvalue
            mov eax, udtmp
        ELSE   
            mov eax, udwordvalue
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR udfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
sdword$ MACRO sdwordvalue:req
    ; signed dword
    LOCAL buffer, sdtmp
    .data?
        sdtmp  SDWORD ?
        buffer BYTE   12 dup(?)
    IFNDEF sdfmt   
    .data   
        sdfmt BYTE "%ld", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(sdwordvalue)
            mov sdtmp, sdwordvalue
            mov eax, sdtmp
        ELSE           
            mov eax, sdwordvalue
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR sdfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
xdword$ MACRO xdwordvalue:req
    ; unsigned hex dword
    LOCAL buffer, xdtmp
    .data?
        xdtmp  DWORD ?
        buffer BYTE  12 dup(?)
    IFNDEF xdfmt   
    .data   
        xdfmt BYTE "%lX", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        IF isregister(xdwordvalue)
            mov xdtmp, xdwordvalue
            mov eax, xdtmp
        ELSE           
            mov eax, xdwordvalue
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR xdfmt, eax
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
uqword$ MACRO uqwordvalue:req
    ; unsigned qword
    LOCAL buffer
    .data?
        buffer BYTE 24 dup(?)
    IFNDEF uqwfmt   
    .data   
        uqwfmt BYTE "%I64u", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR uqwfmt, uqwordvalue
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
sqword$ MACRO sqwordvalue:req
    ; signed qword
    LOCAL buffer
    .data?
        buffer BYTE 24 dup(?)
    IFNDEF sqwfmt   
    .data   
        sqwfmt BYTE "%I64d", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR sqwfmt, sqwordvalue
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
xqword$ MACRO xqwordvalue:req
    ; unsigned hex qword
    LOCAL buffer
    .data?
        buffer BYTE 20 dup(?)
    IFNDEF xqwfmt   
    .data   
        xqwfmt BYTE "%I64X", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR xqwfmt, xqwordvalue
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
real4$ MACRO r4value:req
    LOCAL buffer, r8value, r4tmp
    .data?
        r4tmp   REAL4 ?
        r8value REAL8 ?
        buffer  BYTE  48 dup(?)
    IFNDEF r8fmt   
    .data
        r8fmt   BYTE "%lf", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        push   r4value
        pop    r4tmp
        finit
        fld    r4tmp
        fstp   r8value
        fwait
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
real8$ MACRO r8value:req
    LOCAL buffer
    .data?
        buffer BYTE 320 dup(?)
    IFNDEF r8fmt   
    .data   
        r8fmt  BYTE "%lf", 0
    ENDIF   
    .code
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
real10$ MACRO r10value:req
    LOCAL buffer, r8value
    .data?
        r8value REAL8 ?
        buffer  BYTE  320 dup(?)
    IFNDEF r8fmt   
    .data   
        r8fmt   BYTE "%lf", 0
    ENDIF   
    .code
        IF isregister(r10value)
            fld    r10value
        ELSE 
            finit
            fld    r10value
        ENDIF           
        fstp   r8value
        fwait
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
;; ----------------------------------------------
;; ----------------------------------------------
printf MACRO pszFmt, args:VARARG
    IFB <args>
        IFB <pszFmt>
            invoke crt_printf, chr$(13,10)
        ELSE   
            invoke crt_printf, pszFmt
        ENDIF
    ELSE
        invoke crt_printf, pszFmt, args
    ENDIF   
ENDM   
;------------------------------------------------------------
WaitKey MACRO
    printf chr$(13, 10, "Press any key to continue...")
    call wait_key
    printf
ENDM
;------------------------------------------------------------

.DATA
       
    ubyMax BYTE   255                        ; UCHAR_MAX
    ubyMin BYTE     0                        ; UCHAR_MIN
   
    sbyMax SBYTE  127                        ; CHAR_MAX
    sbyMin SBYTE -128                        ; CHAR_MIN
   
    uwdMax WORD   65535                      ; USHRT_MAX
    uwdMin WORD       0                      ; USHRT_MIN
   
    swdMax SWORD  32767                      ; SHRT_MAX
    swdMin SWORD -32768                      ; SHRT_MIN
   
    udwMax DWORD   4294967295                ; ULONG MAX
    udwMin DWORD            0                ; ULONG_MIN
   
    sdwMax SDWORD  2147483647                ; LONG_MAX
    sdwMin SDWORD -2147483648                ; LONG_MIN
   
    uqwMax QWORD 18446744073709551615        ; _UI64_MAX
    uqwMin QWORD                    0        ; _UI64_MIN
   
    sqwMax QWORD  9223372036854775807        ; _I64_MAX
    sqwMin QWORD -9223372036854775808        ; _I64_MIN
   
    r4Max  REAL4   3.402823466E+38           ; FLT_MAX
    r4Min  REAL4  -1.175494351E-38           ; FLT_MIN
   
    r8Max  REAL8   1.7976931348623158E+308   ; DBL_MAX
    r8Min  REAL8  -2.2250738585072014E-308   ; DBL_MIN
   
    r10Max REAL10  1.7976931348623158E+308   ; LDBL_MAX ( = DBL_MAX)
    r10Min REAL10 -2.2250738585072014E-308   ; LDBL_MIN ( = DBL_MIN)
       
.CODE

start:
   
    printf SADD("Memory variables",10)
    printf SADD("================",10,10)
   
    printf SADD("ubyte$(UCHAR_MAX)  = %s",10), ubyte$(ubyMax)
    printf SADD("ubyte$(UCHAR_MIN)  = %s",10), ubyte$(ubyMin)
    printf
    printf SADD("sbyte$(CHAR_MAX)   = %s",10), sbyte$(sbyMax)
    printf SADD("sbyte$(CHAR_MIN)   = %s",10), sbyte$(sbyMin)
    printf
    printf SADD("xbyte$(UCHAR_MAX)  = %s",10), xbyte$(ubyMax)
    printf SADD("xbyte$(UCHAR_MIN)  = %s",10), xbyte$(ubyMin)
    printf
    printf SADD("uword$(USHRT_MAX)  = %s",10), uword$(uwdMax)
    printf SADD("uword$(USHRT_MIN)  = %s",10), uword$(uwdMin)
    printf
    printf SADD("sword$(SHRT_MAX)   = %s",10), sword$(swdMax)
    printf SADD("sword$(SHRT_MIN)   = %s",10), sword$(swdMin)
    printf
    printf SADD("xword$(USHRT_MAX)  = %s",10), xword$(uwdMax)
    printf SADD("xword$(USHRT_MIN)  = %s",10), xword$(uwdMin)
    printf
    printf SADD("udword$(ULONG_MAX) = %s",10), udword$(udwMax)
    printf SADD("udword$(ULONG_MIN) = %s",10), udword$(udwMin)
    printf
    printf SADD("sdword$(LONG_MAX)  = %s",10), sdword$(sdwMax)
    printf SADD("sdword$(LONG_MIN)  = %s",10), sdword$(sdwMin)
    printf 
    printf SADD("xdword$(ULONG_MAX) = %s",10), xdword$(udwMax)
    printf SADD("xdword$(ULONG_MIN) = %s",10), xdword$(udwMin)
    printf
    printf SADD("uqword$(_UI64_MAX) = %s",10), uqword$(uqwMax)
    printf SADD("uqword$(_UI64_MIN) = %s",10), uqword$(uqwMin)
    printf
    printf SADD("sqword$(_I64_MAX)  = %s",10), sqword$(sqwMax)
    printf SADD("sqword$(_I64_MIN)  = %s",10), sqword$(sqwMin)
    printf
    printf SADD("xqword$(_UI64_MAX) = %s",10), xqword$(uqwMax)
    printf SADD("xqword$(_UI64_MIN) = %s",10), xqword$(uqwMin)
    printf
    printf SADD("real4$(FLT_MAX)    = %s",10), real4$(r4Max)
    printf SADD("real4$(FLT_MIN)    = %s",10), real4$(r4Min)
    printf
    printf SADD("real8$(DBL_MAX)    = %s",10), real8$(r8Max)
    printf SADD("real8$(DBL_MIN)    = %s",10), real8$(r8Min)
    printf
    printf SADD("real10$(LDBL_MAX) = %s",10), real10$(r10Max)
    printf SADD("real10$(LDBL_MIN) = %s",10), real10$(r10Min)
    printf
   
    printf SADD("Register variables",10)
    printf SADD("==================",10,10)
   
    mov al, ubyMax
    printf SADD("ubyte$(UCHAR_MAX)  = %s",10), ubyte$(al)
    mov al, ubyMin
    printf SADD("ubyte$(UCHAR_MIN)  = %s",10), ubyte$(al)
    printf
    mov al, sbyMax
    printf SADD("sbyte$(CHAR_MAX)   = %s",10), sbyte$(al)
    mov al, sbyMin
    printf SADD("sbyte$(CHAR_MIN)   = %s",10), sbyte$(al)
    printf
    mov al, ubyMax
    printf SADD("xbyte$(UCHAR_MAX)  = %s",10), xbyte$(al)
    mov al, ubyMin
    printf SADD("xbyte$(UCHAR_MIN)  = %s",10), xbyte$(al)
    printf

    mov ax, uwdMax
    printf SADD("uword$(USHRT_MAX)  = %s",10), uword$(ax)
    mov ax, uwdMin
    printf SADD("uword$(USHRT_MIN)  = %s",10), uword$(ax)
    printf
    mov ax, swdMax
    printf SADD("sword$(SHRT_MAX)   = %s",10), sword$(ax)
    mov ax, swdMin
    printf SADD("sword$(SHRT_MIN)   = %s",10), sword$(ax)
    printf
    mov ax, uwdMax
    printf SADD("xword$(USHRT_MAX)  = %s",10), xword$(ax)
    mov ax, uwdMin
    printf SADD("xword$(USHRT_MIN)  = %s",10), xword$(ax)
    printf

    mov eax, udwMax
    printf SADD("udword$(ULONG_MAX) = %s",10), udword$(eax)
    mov eax, udwMin
    printf SADD("udword$(ULONG_MIN) = %s",10), udword$(eax)
    printf
    mov eax, sdwMax
    printf SADD("sdword$(LONG_MAX)  = %s",10), sdword$(eax)
    mov eax, sdwMin
    printf SADD("sdword$(LONG_MIN)  = %s",10), sdword$(eax)
    printf 
    mov eax, udwMax
    printf SADD("xdword$(ULONG_MAX) = %s",10), xdword$(eax)
    mov eax, udwMin
    printf SADD("xdword$(ULONG_MIN) = %s",10), xdword$(eax)
    printf

    mov esi, OFFSET uqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("uqword$(_UI64_MAX) = %s",10), uqword$(edx::eax)
    mov esi, OFFSET uqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("uqword$(_UI64_MIN) = %s",10), uqword$(edx::eax)
    printf
    mov esi, OFFSET sqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("sqword$(_I64_MAX)  = %s",10), sqword$(edx::eax)
    mov esi, OFFSET sqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("sqword$(_I64_MIN)  = %s",10), sqword$(edx::eax)
    printf
    mov esi, OFFSET uqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("xqword$(_UI64_MAX) = %s",10), xqword$(edx::eax)
    mov esi, OFFSET uqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("xqword$(_UI64_MIN) = %s",10), xqword$(edx::eax)
    printf

    mov eax, r4Max
    printf SADD("real4$(FLT_MAX)    = %s",10), real4$(eax)
    mov eax, r4Min
    printf SADD("real4$(FLT_MIN)    = %s",10), real4$(eax)
    printf

    mov esi, OFFSET r8Max
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("real8$(DBL_MAX)    = %s",10), real8$(edx::eax)
    mov esi, OFFSET r8Min
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("real8$(DBL_MIN)    = %s",10), real8$(edx::eax)
    printf

    finit
    fld r10Max
    printf SADD("real10$(LDBL_MAX)  = %s",10), real10$(ST(0))
    fstp st(0)
    fld r10Min
    printf SADD("real10$(LDBL_MIN)  = %s",10), real10$(ST(0))
    fstp st(0)
   
    WaitKey
         
    invoke ExitProcess, 0

end start



hutch--

Greg,

I found that ml 6.14 was broken on the TYPE return size for a BYTE where ml 7.0 is not so I put this macro together to be reliable on both.


  ; **********************************
  ; test if an argument is an integer
  ; register and return its byte size
  ; if it is else return zero if it
  ; is not a register.
  ; **********************************
    iregsize MACRO item
      LOCAL rv
      rv = 0
      for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
        IFIDNI <arg>,<item>
          rv = 4
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      for arg,<al,ah,bl,bh,cl,ch,dl,dh>
        IFIDNI <arg>,<item>
          rv = 1
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      for arg,<ax,bx,cx,dx,sp,bp,si,di>
        IFIDNI <arg>,<item>
          rv = 2
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      EXITM %rv
    ENDM
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

I am using ML 6.15, TYPE works correctly on byte sized memory variables but it fails on byte sized registers, it's the same as 6.14 I believe. I like the new macro.

I'm pretty happy with the sprintf macros posted above, if you have any suggestions for improvement or concerns, let me know.


Phil

Will the new macro automatically handle upper-case registers like 'AL', 'BL', etc., or should we always use lower-case to use anything that uses these macros? Does the case dependency depend on the command line options that apply to variable names? The macro looks nice!

GregL

Phil,

IFIDNI is case insensitive so the macro is case insensitive.


Hutch,

I was playing around with your macro, I extended it, and this works. :dance:


;------------------------------------------------------------
; **********************************
; test if an argument is a register
; and return its byte size if it is
; else return zero if it is not a
; register.
; **********************************
iregsize MACRO item
  LOCAL rv
  rv = 0
  for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
    IFIDNI <arg>,<item>
      rv = 4
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<al,ah,bl,bh,cl,ch,dl,dh>
    IFIDNI <arg>,<item>
      rv = 1
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<ax,bx,cx,dx,sp,bp,si,di>
    IFIDNI <arg>,<item>
      rv = 2
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<edx::eax,ecx::ebx>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF 
  for arg,<st,st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)>
    IFIDNI <arg>,<item>
      rv = 10
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF 
  for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF   
  for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
    IFIDNI <arg>,<item>
      rv = 16
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF     
  EXITM %rv
ENDM


hutch--

#83
Greg,

The mod looks good. I wonder if there will be any problems with alternative syntax on fp, mmx and xmm register names.

LATER :

I tweaked the version to handle both syntaxes, with or without brackets for the index on mm, xmm and st registers. It was starting to get a bit long so I did a length test on the arg and branched on the length which should prevent redundant code execution.


  ; ************************************
  ; Return a register size in BYTES or *
  ; 0 if the arguent is not a register *
  ; ************************************
    regsize MACRO item
      LOCAL rv,ln
      rv = 0
      ln SIZESTR <item>

      IF ln EQ 2
        goto two
      ELSEIF ln EQ 3
        goto three
      ELSEIF ln EQ 4
        goto four
      ELSEIF ln EQ 5
        goto five
      ELSEIF ln EQ 6
        goto six
      ELSE
        goto notreg
      ENDIF

    :two
      for arg,<al,ah,bl,bh,cl,ch,dl,dh>
        IFIDNI <arg>,<item>
          rv = 1
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<ax,bx,cx,dx,sp,bp,si,di>
        IFIDNI <arg>,<item>
          rv = 2
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :three
      for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
        IFIDNI <arg>,<item>
          rv = 4
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<st0,st1,st2,st3,st4,st5,st6,st7>
        IFIDNI <arg>,<item>
          rv = 10
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7>
        IFIDNI <arg>,<item>
          rv = 8
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :four
      for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
        IFIDNI <arg>,<item>
          rv = 16
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :five
      for arg,<mm(0),mm(1),mm(2),mm(3),mm(4),mm(5),mm(6),mm(7)>
        IFIDNI <arg>,<item>
          rv = 8
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)>
        IFIDNI <arg>,<item>
          rv = 10
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :six
      for arg,<xmm(0),xmm(1),xmm(2),xmm(3),xmm(4),xmm(5),xmm(6),xmm(7)>
        IFIDNI <arg>,<item>
          rv = 16
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

    :notreg
      EXITM %rv
    ENDM
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

Oops. :red  It looks like you have to list them all out.


; **********************************
; test if an argument is a register
; and return its byte size if it is
; else return zero if it is not a
; register.
; **********************************
iregsize MACRO item
  LOCAL rv
  rv = 0
  for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
    IFIDNI <arg>,<item>
      rv = 4
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<al,ah,bl,bh,cl,ch,dl,dh>
    IFIDNI <arg>,<item>
      rv = 1
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<ax,bx,cx,dx,sp,bp,si,di>
    IFIDNI <arg>,<item>
      rv = 2
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  for arg,<edx::eax,ecx::ebx>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF 
  for arg,<st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7),st,st0,st1,st2,st3,st4,st5,st6,st7>
    IFIDNI <arg>,<item>
      rv = 10
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF 
  for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7,mm,mm(0),mm(1),mm(2),mm(3),mm(4),mm(5),mm(6),mm(7)>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF   
  for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm,xmm(0),xmm(1),xmm(2),xmm(3),xmm(4),xmm(5),xmm(6),xmm(7)>
    IFIDNI <arg>,<item>
      rv = 16
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF     
  EXITM %rv
ENDM





hutch--

I think I forgot to put the EDX::EAX register pair test but the idea was to try and reduce the amount of macro code so that it did not get too slow. That was the idea of the length test first so you could branch a lot closewr than running them all until you found a match.

Here is the test piece I used.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
       
comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

  ; ************************************
  ; Return a register size in BYTES or *
  ; 0 if the arguent is not a register *
  ; ************************************
    regsize MACRO item
      LOCAL rv,ln
      rv = 0
      ln SIZESTR <item>

      IF ln EQ 2
        goto two
      ELSEIF ln EQ 3
        goto three
      ELSEIF ln EQ 4
        goto four
      ELSEIF ln EQ 5
        goto five
      ELSEIF ln EQ 6
        goto six
      ELSE
        goto notreg
      ENDIF

    :two
      for arg,<al,ah,bl,bh,cl,ch,dl,dh>
        IFIDNI <arg>,<item>
          rv = 1
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<ax,bx,cx,dx,sp,bp,si,di>
        IFIDNI <arg>,<item>
          rv = 2
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :three
      for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
        IFIDNI <arg>,<item>
          rv = 4
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<st0,st1,st2,st3,st4,st5,st6,st7>
        IFIDNI <arg>,<item>
          rv = 10
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7>
        IFIDNI <arg>,<item>
          rv = 8
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :four
      for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
        IFIDNI <arg>,<item>
          rv = 16
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :five
      for arg,<mm(0),mm(1),mm(2),mm(3),mm(4),mm(5),mm(6),mm(7)>
        IFIDNI <arg>,<item>
          rv = 8
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

      for arg,<st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)>
        IFIDNI <arg>,<item>
          rv = 10
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF
      goto notreg

    :six
      for arg,<xmm(0),xmm(1),xmm(2),xmm(3),xmm(4),xmm(5),xmm(6),xmm(7)>
        IFIDNI <arg>,<item>
          rv = 16
          EXITM
        ENDIF
      ENDM
      IF rv NE 0
        EXITM %rv
      ENDIF

    :notreg
      EXITM %rv
    ENDM


    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    % echo regsize(al)
    % echo regsize(ah)

    % echo regsize(ax)
    % echo regsize(bx)

    % echo regsize(eax)
    % echo regsize(edi)

    % echo regsize(mm0)
    % echo regsize(mm(4))

    % echo regsize(st0)
    % echo regsize(st(5))

    % echo regsize(xmm7)
    % echo regsize(xmm(3))

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

I missed the 'LATER' part. Yes, it was getting pretty large, the length test helps a lot.

MASM macros are amazing, I never did a lot with them before. I'm just starting to realize what all can be done with them. Thanks for prodding me into learning more about them.


GregL

#87
I'm getting about sick of these sprintf conversion macros, I'm sure everyone else is too. :wink  But I want to get them right.

Here is the latest update, I hope I'm done with these.


.586
.MODEL FLAT, stdcall
option casemap:none

include c:\masm32\include\windows.inc

include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\masm32.inc
include c:\masm32\include\msvcrt.inc

include c:\masm32\macros\macros.asm

includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\masm32.lib
includelib c:\masm32\lib\msvcrt.lib

; ************************************
; Return a register size in BYTES or *
; 0 if the arguent is not a register *
; ************************************
regsize MACRO item
  LOCAL rv,ln
  rv = 0
  ln SIZESTR <item>

  IF ln EQ 2
    goto two
  ELSEIF ln EQ 3
    goto three
  ELSEIF ln EQ 4
    goto four
  ELSEIF ln EQ 5
    goto five
  ELSEIF ln EQ 6
    goto six
  ELSEIF ln EQ 8
    goto eight
  ELSE
    goto notreg
  ENDIF

:two
  for arg,<al,ah,bl,bh,cl,ch,dl,dh>
    IFIDNI <arg>,<item>
      rv = 1
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF

  for arg,<ax,bx,cx,dx,sp,bp,si,di>
    IFIDNI <arg>,<item>
      rv = 2
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  goto notreg

:three
  for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
    IFIDNI <arg>,<item>
      rv = 4
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF

  for arg,<st0,st1,st2,st3,st4,st5,st6,st7>
    IFIDNI <arg>,<item>
      rv = 10
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF

  for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  goto notreg

:four
  for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
    IFIDNI <arg>,<item>
      rv = 16
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  goto notreg

:five
  for arg,<mm(0),mm(1),mm(2),mm(3),mm(4),mm(5),mm(6),mm(7)>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF

  for arg,<st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)>
    IFIDNI <arg>,<item>
      rv = 10
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
  goto notreg

:six
  for arg,<xmm(0),xmm(1),xmm(2),xmm(3),xmm(4),xmm(5),xmm(6),xmm(7)>
    IFIDNI <arg>,<item>
      rv = 16
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF
 
:eight
  for arg,<edx::eax,ecx::ebx>
    IFIDNI <arg>,<item>
      rv = 8
      EXITM
    ENDIF
  ENDM
  IF rv NE 0
    EXITM %rv
  ENDIF 

:notreg
  EXITM %rv
ENDM
;---------------------------------------------------
issize MACRO var:req, bytes:req
    LOCAL rv
    rv = regsize(var)
    IFE rv ; if not a register use SIZE
        IF SIZE var EQ bytes
            EXITM <1>
        ELSE
            EXITM <0>
        ENDIF
    ELSE   ; it's a register       
        IF rv EQ bytes
            EXITM <1>       
        ELSE
            EXITM <0>
        ENDIF   
    ENDIF
ENDM
; ----------------------------------------------
isregister MACRO var:req
    IF regsize(var)
        EXITM <1>
    ELSE
        EXITM <0>
    ENDIF   
ENDM   
; ----------------------------------------------
ubyte$ MACRO ubytevalue:req
    ;; unsigned byte
    LOCAL buffer, ubtmp
    .data?
        ubtmp  BYTE ?
        buffer BYTE 4 dup(?)
    IFNDEF ubfmt   
    .data   
        ubfmt  BYTE "%hhu", 0
    ENDIF   
    .code
        IFE issize(ubytevalue, 1)
            echo ----------------------
            echo ubyte$ - requires BYTE
            echo ----------------------
            .ERR
        ENDIF               
        mov    buffer[0], 0
        IF isregister(ubytevalue)
            mov   ubtmp, ubytevalue
            movzx eax, ubtmp
        ELSE
            mov   al, ubytevalue
            movzx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR ubfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
sbyte$ MACRO sbytevalue:req
    ;; signed byte
    LOCAL buffer, sbtmp
    .data?
        sbtmp  SBYTE ?
        buffer BYTE  8 dup(?)
    IFNDEF sbfmt     
    .data   
        sbfmt  BYTE "%hhd", 0
    ENDIF   
    .code
        IFE issize(sbytevalue, 1)
            echo -----------------------
            echo sbyte$ - requires SBYTE
            echo -----------------------
            .ERR
        ENDIF               
        mov    buffer[0], 0
        IF isregister(sbytevalue)
            mov   sbtmp, sbytevalue
            movsx eax, sbtmp
        ELSE     
            mov   al, sbytevalue
            movsx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR sbfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
xbyte$ MACRO xbytevalue:req
    ;; unsigned hex byte
    LOCAL buffer, xbtmp
    .data?
        xbtmp  BYTE ?
        buffer BYTE 4 dup(?)
    IFNDEF xbfmt   
    .data   
        xbfmt  BYTE "%hhX", 0
    ENDIF   
    .code
        IFE issize(xbytevalue, 1)
            echo ----------------------
            echo xbyte$ - requires BYTE
            echo ----------------------
            .ERR
        ENDIF               
        mov buffer[0], 0
        IF isregister(xbytevalue)
            mov   xbtmp, xbytevalue
            movzx eax, xbtmp
        ELSE
            mov   al, xbytevalue
            movzx eax, al
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR xbfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
uword$ MACRO uwordvalue:req
    ;; unsigned word
    LOCAL buffer, uwtmp
    .data?
        uwtmp  WORD ?
        buffer BYTE 8 dup(?)
    IFNDEF uwfmt   
    .data   
        uwfmt  BYTE "%hu", 0
    ENDIF   
    .code
        IFE issize(uwordvalue, 2)
            echo ----------------------
            echo uword$ - requires WORD
            echo ----------------------
            .ERR
        ENDIF           
        mov   buffer[0], 0
        IF isregister(uwordvalue)
            mov   uwtmp, uwordvalue
            movzx eax, uwtmp
        ELSE       
            mov   ax, uwordvalue
            movzx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR uwfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
sword$ MACRO swordvalue:req
    ;; signed word
    LOCAL buffer, swtmp
    .data?
        swtmp  SWORD ?
        buffer BYTE  8 dup(?)
    IFNDEF swfmt   
    .data   
        swfmt  BYTE "%hd", 0
    ENDIF   
    .code
        IFE issize(swordvalue, 2)
            echo -----------------------
            echo sword$ - requires SWORD
            echo -----------------------
            .ERR
        ENDIF           
        mov   buffer[0], 0
        IF isregister(swordvalue)
            mov   swtmp, swordvalue
            movsx eax, swtmp
        ELSE   
            mov   ax, swordvalue
            movsx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR swfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
xword$ MACRO xwordvalue:req
    ;; unsigned hex word
    LOCAL buffer, xwtmp
    .data?
        xwtmp  WORD ?
        buffer BYTE 8 dup(?)
    IFNDEF xwfmt   
    .data   
        xwfmt  BYTE "%hX", 0
    ENDIF   
    .code
        IFE issize(xwordvalue, 2)
            echo ----------------------
            echo xword$ - requires WORD
            echo ----------------------
            .ERR
        ENDIF       
        mov   buffer[0], 0
        IF isregister(xwordvalue)
            mov   xwtmp, xwordvalue
            movzx eax, xwtmp
        ELSE               
            mov   ax, xwordvalue
            movzx eax, ax
        ENDIF   
        invoke crt_sprintf, ADDR buffer, ADDR xwfmt, eax
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
udword$ MACRO udwordvalue:req
    ;; unsigned dword
    LOCAL buffer
    .data?
        buffer BYTE  12 dup(?)
    IFNDEF udfmt   
    .data   
        udfmt  BYTE "%lu", 0
    ENDIF   
    .code
        IFE issize(udwordvalue, 4)
            echo ------------------------
            echo udword$ - requires DWORD
            echo ------------------------
            .ERR
        ENDIF   
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR udfmt, udwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
sdword$ MACRO sdwordvalue:req
    ;; signed dword
    LOCAL buffer
    .data?
        buffer BYTE   12 dup(?)
    IFNDEF sdfmt   
    .data   
        sdfmt BYTE "%ld", 0
    ENDIF   
    .code
        IFE issize(sdwordvalue, 4)
            echo -------------------------
            echo sdword$ - requires SDWORD
            echo -------------------------
            .ERR
        ENDIF       
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR sdfmt, sdwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
xdword$ MACRO xdwordvalue:req
    ;; unsigned hex dword
    LOCAL buffer
    .data?
        buffer BYTE  12 dup(?)
    IFNDEF xdfmt   
    .data   
        xdfmt BYTE "%lX", 0
    ENDIF   
    .code
        IFE issize(xdwordvalue, 4)
            echo ------------------------
            echo xdword$ - requires DWORD
            echo ------------------------
            .ERR
        ENDIF       
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR xdfmt, xdwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
uqword$ MACRO uqwordvalue:req
    ;; unsigned qword
    LOCAL buffer
    .data?
        buffer BYTE 24 dup(?)
    IFNDEF uqwfmt   
    .data   
        uqwfmt BYTE "%I64u", 0
    ENDIF   
    .code
        IFE issize(uqwordvalue, 8)
            echo ------------------------
            echo uqword$ - requires QWORD
            echo ------------------------
            .ERR
        ENDIF       
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR uqwfmt, uqwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
sqword$ MACRO sqwordvalue:req
    ;; signed qword
    LOCAL buffer
    .data?
        buffer BYTE 24 dup(?)
    IFNDEF sqwfmt   
    .data   
        sqwfmt BYTE "%I64d", 0
    ENDIF   
    .code
        IFE issize(sqwordvalue, 8)
            echo ------------------------
            echo sqword$ - requires QWORD
            echo ------------------------
            .ERR
        ENDIF           
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR sqwfmt, sqwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
xqword$ MACRO xqwordvalue:req
    ;; unsigned hex qword
    LOCAL buffer
    .data?
        buffer BYTE 20 dup(?)
    IFNDEF xqwfmt   
    .data   
        xqwfmt BYTE "%I64X", 0
    ENDIF   
    .code
        IFE issize(xqwordvalue, 8)
            echo ------------------------
            echo xqword$ - requires QWORD
            echo ------------------------
            .ERR
        ENDIF           
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR xqwfmt, xqwordvalue
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
real4$ MACRO r4value:req
    LOCAL buffer, r8value, r4tmp
    .data?
        r4tmp   REAL4 ?
        r8value REAL8 ?
        buffer  BYTE  48 dup(?)
    IFNDEF r8fmt   
    .data
        r8fmt   BYTE "%lf", 0
    ENDIF   
    .code
        IFE issize(r4value, 4)
            echo ------------------------
            echo real4$ - requires REAL4
            echo ------------------------
            .ERR
        ENDIF           
        IF isregister(r4value)
            push   r4value
            pop    r4tmp
            finit
            fld    r4tmp
        ELSE
            finit
            fld    r4value
        ENDIF   
        fstp   r8value
        fwait
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
real8$ MACRO r8value:req
    LOCAL buffer
    .data?
        buffer BYTE 320 dup(?)
    IFNDEF r8fmt   
    .data   
        r8fmt  BYTE "%lf", 0
    ENDIF   
    .code
        IFE issize(r8value, 8)
            echo ------------------------
            echo real8$ - requires REAL8
            echo ------------------------
            .ERR
        ENDIF           
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
real10$ MACRO r10value:req
    LOCAL buffer, r8value
    .data?
        r8value REAL8 ?
        buffer  BYTE  320 dup(?)
    IFNDEF r8fmt   
    .data   
        r8fmt   BYTE "%lf", 0
    ENDIF   
    .code
        IFE issize(r10value, 10)
            echo -------------------------
            echo real10$ - requires REAL10
            echo -------------------------
            .ERR
        ENDIF       
        fld    r10value
        fstp   r8value
        fwait
        mov    buffer[0], 0
        invoke crt_sprintf, ADDR buffer, ADDR r8fmt, r8value
        EXITM <OFFSET buffer>
ENDM
; ----------------------------------------------
; ----------------------------------------------
printf MACRO pszFmt, args:VARARG
    IFB <args>
        IFB <pszFmt>
            invoke crt_printf, SADD(10)
        ELSE   
            invoke crt_printf, pszFmt
        ENDIF
    ELSE
        invoke crt_printf, pszFmt, args
    ENDIF   
ENDM   
;------------------------------------------------------------

.DATA
       
    ubyMax BYTE   255                        ; UCHAR_MAX
    ubyMin BYTE     0                        ; UCHAR_MIN
   
    sbyMax SBYTE  127                        ; CHAR_MAX
    sbyMin SBYTE -128                        ; CHAR_MIN
   
    uwdMax WORD   65535                      ; USHRT_MAX
    uwdMin WORD       0                      ; USHRT_MIN
   
    swdMax SWORD  32767                      ; SHRT_MAX
    swdMin SWORD -32768                      ; SHRT_MIN
   
    udwMax DWORD   4294967295                ; ULONG MAX
    udwMin DWORD            0                ; ULONG_MIN
   
    sdwMax SDWORD  2147483647                ; LONG_MAX
    sdwMin SDWORD -2147483648                ; LONG_MIN
   
    uqwMax QWORD 18446744073709551615        ; _UI64_MAX
    uqwMin QWORD                    0        ; _UI64_MIN
   
    sqwMax QWORD  9223372036854775807        ; _I64_MAX
    sqwMin QWORD -9223372036854775808        ; _I64_MIN
   
    r4Max  REAL4   3.402823466E+38           ; FLT_MAX
    r4Min  REAL4  -1.175494351E-38           ; FLT_MIN
   
    r8Max  REAL8   1.7976931348623158E+308   ; DBL_MAX
    r8Min  REAL8  -2.2250738585072014E-308   ; DBL_MIN
   
    r10Max REAL10  1.7976931348623158E+308   ; LDBL_MAX ( = DBL_MAX)
    r10Min REAL10 -2.2250738585072014E-308   ; LDBL_MIN ( = DBL_MIN)
       
.CODE

start:
   
    printf SADD("Memory variables",10)
    printf SADD("================",10,10)
   
    printf SADD("ubyte$(UCHAR_MAX)  = %s",10), ubyte$(ubyMax)
    printf SADD("ubyte$(UCHAR_MIN)  = %s",10), ubyte$(ubyMin)
    printf
    printf SADD("sbyte$(CHAR_MAX)   = %s",10), sbyte$(sbyMax)
    printf SADD("sbyte$(CHAR_MIN)   = %s",10), sbyte$(sbyMin)
    printf
    printf SADD("xbyte$(UCHAR_MAX)  = %s",10), xbyte$(ubyMax)
    printf SADD("xbyte$(UCHAR_MIN)  = %s",10), xbyte$(ubyMin)
    printf
    printf SADD("uword$(USHRT_MAX)  = %s",10), uword$(uwdMax)
    printf SADD("uword$(USHRT_MIN)  = %s",10), uword$(uwdMin)
    printf
    printf SADD("sword$(SHRT_MAX)   = %s",10), sword$(swdMax)
    printf SADD("sword$(SHRT_MIN)   = %s",10), sword$(swdMin)
    printf
    printf SADD("xword$(USHRT_MAX)  = %s",10), xword$(uwdMax)
    printf SADD("xword$(USHRT_MIN)  = %s",10), xword$(uwdMin)
    printf
    printf SADD("udword$(ULONG_MAX) = %s",10), udword$(udwMax)
    printf SADD("udword$(ULONG_MIN) = %s",10), udword$(udwMin)
    printf
    printf SADD("sdword$(LONG_MAX)  = %s",10), sdword$(sdwMax)
    printf SADD("sdword$(LONG_MIN)  = %s",10), sdword$(sdwMin)
    printf 
    printf SADD("xdword$(ULONG_MAX) = %s",10), xdword$(udwMax)
    printf SADD("xdword$(ULONG_MIN) = %s",10), xdword$(udwMin)
    printf
    printf SADD("uqword$(_UI64_MAX) = %s",10), uqword$(uqwMax)
    printf SADD("uqword$(_UI64_MIN) = %s",10), uqword$(uqwMin)
    printf
    printf SADD("sqword$(_I64_MAX)  = %s",10), sqword$(sqwMax)
    printf SADD("sqword$(_I64_MIN)  = %s",10), sqword$(sqwMin)
    printf
    printf SADD("xqword$(_UI64_MAX) = %s",10), xqword$(uqwMax)
    printf SADD("xqword$(_UI64_MIN) = %s",10), xqword$(uqwMin)
    printf
    printf SADD("real4$(FLT_MAX)    = %s",10), real4$(r4Max)
    printf SADD("real4$(FLT_MIN)    = %s",10), real4$(r4Min)
    printf
    printf SADD("real8$(DBL_MAX)    = %s",10), real8$(r8Max)
    printf SADD("real8$(DBL_MIN)    = %s",10), real8$(r8Min)
    printf
    printf SADD("real10$(LDBL_MAX) = %s",10), real10$(r10Max)
    printf SADD("real10$(LDBL_MIN) = %s",10), real10$(r10Min)
    printf
   
    printf SADD("Register variables",10)
    printf SADD("==================",10,10)
   
    mov al, ubyMax
    printf SADD("ubyte$(UCHAR_MAX)  = %s",10), ubyte$(al)
    mov al, ubyMin
    printf SADD("ubyte$(UCHAR_MIN)  = %s",10), ubyte$(al)
    printf
    mov al, sbyMax
    printf SADD("sbyte$(CHAR_MAX)   = %s",10), sbyte$(al)
    mov al, sbyMin
    printf SADD("sbyte$(CHAR_MIN)   = %s",10), sbyte$(al)
    printf
    mov al, ubyMax
    printf SADD("xbyte$(UCHAR_MAX)  = %s",10), xbyte$(al)
    mov al, ubyMin
    printf SADD("xbyte$(UCHAR_MIN)  = %s",10), xbyte$(al)
    printf

    mov ax, uwdMax
    printf SADD("uword$(USHRT_MAX)  = %s",10), uword$(ax)
    mov ax, uwdMin
    printf SADD("uword$(USHRT_MIN)  = %s",10), uword$(ax)
    printf
    mov ax, swdMax
    printf SADD("sword$(SHRT_MAX)   = %s",10), sword$(ax)
    mov ax, swdMin
    printf SADD("sword$(SHRT_MIN)   = %s",10), sword$(ax)
    printf
    mov ax, uwdMax
    printf SADD("xword$(USHRT_MAX)  = %s",10), xword$(ax)
    mov ax, uwdMin
    printf SADD("xword$(USHRT_MIN)  = %s",10), xword$(ax)
    printf

    mov eax, udwMax
    printf SADD("udword$(ULONG_MAX) = %s",10), udword$(eax)
    mov eax, udwMin
    printf SADD("udword$(ULONG_MIN) = %s",10), udword$(eax)
    printf
    mov eax, sdwMax
    printf SADD("sdword$(LONG_MAX)  = %s",10), sdword$(eax)
    mov eax, sdwMin
    printf SADD("sdword$(LONG_MIN)  = %s",10), sdword$(eax)
    printf 
    mov eax, udwMax
    printf SADD("xdword$(ULONG_MAX) = %s",10), xdword$(eax)
    mov eax, udwMin
    printf SADD("xdword$(ULONG_MIN) = %s",10), xdword$(eax)
    printf

    mov esi, OFFSET uqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("uqword$(_UI64_MAX) = %s",10), uqword$(edx::eax)
    mov esi, OFFSET uqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("uqword$(_UI64_MIN) = %s",10), uqword$(edx::eax)
    printf
    mov esi, OFFSET sqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("sqword$(_I64_MAX)  = %s",10), sqword$(edx::eax)
    mov esi, OFFSET sqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("sqword$(_I64_MIN)  = %s",10), sqword$(edx::eax)
    printf
    mov esi, OFFSET uqwMax
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("xqword$(_UI64_MAX) = %s",10), xqword$(edx::eax)
    mov esi, OFFSET uqwMin
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("xqword$(_UI64_MIN) = %s",10), xqword$(edx::eax)
    printf

    mov eax, r4Max
    printf SADD("real4$(FLT_MAX)    = %s",10), real4$(eax)
    mov eax, r4Min
    printf SADD("real4$(FLT_MIN)    = %s",10), real4$(eax)
    printf

    mov esi, OFFSET r8Max
    mov edx, [esi+4]
    mov eax, [esi+0]       
    printf SADD("real8$(DBL_MAX)    = %s",10), real8$(edx::eax)
    mov esi, OFFSET r8Min
    mov edx, [esi+4]
    mov eax, [esi+0]
    printf SADD("real8$(DBL_MIN)    = %s",10), real8$(edx::eax)
    printf

    finit
    fld r10Max
    printf SADD("real10$(LDBL_MAX)  = %s",10), real10$(ST(0))
    fstp st(0)
    fld r10Min
    printf SADD("real10$(LDBL_MIN)  = %s",10), real10$(ST(0))
    fstp st(0)
   
    inkey SADD(10, "Press any key to exit...")
         
    invoke ExitProcess, 0

end start




[attachment deleted by admin]

zooba

Wouldn't it be possible to test the register by using INSTR rather than a loop? Though you may lose the case-insensitivity then...

Also, with the really long code pieces, could they be put in zip files rather than code tags. I'm running a huge (1920x1200) screen and they're still annoying, so people with 1024x768 must be really angry at you ;)

hutch--

zooba,

I would not worry too much about the problem, this work of Greg's will end up in the macros.asm file so it will not irritate anyone there. the "PHUN" part is I have to produce the documentation for them now that they are stable.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php