| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# cpuext32.htm
Macros
Align2Dword
Align2Oword
Align2Qword
Clear
Compare
CopyTo
LodD
LodH
LodQD
LodQH
StoD
StoH
StoQD
StoQH
StripApostrophes
StripColons
StripQuotes
StripSpaces

This file can be included to 32bit programs written in Euro Assembler.
The library contains OS-independent macroinstructions with calling convention similar to the standard Intel machine instruction set. They mostly pass operands in general-purpose registers and change the register contents on return.

Align* performs alignment at run time,
Clear, Compare, CopyTo provide some string operations,
Lod* converts numbers from human-readable notation to a binary number,
Sto* does the opposite,
Strip* trims the string from garbage characters which may surround it.

Similar macros with identical names for different program width are defined in cpuext16.htm and cpuext64.htm.

See also cpuext.htm for width-indepentent macros.

    cpuext32 HEAD
           INCLUDEHEAD1 status32.htm

    ; Definition of flags used by macros in this library.
    %cpuextMinus    %SETA 0x80
    %cpuextSigned   %SETA 0x40
    %cpuextAlignL   %SETA 0x20
    %cpuextLeading0 %SETA 0x10
    %cpuextLowCase  %SETA 0x08
    ; Saved values in standard EBP frame.
    %Param4         %SET EBP+48
    %Param3         %SET EBP+44
    %Param2         %SET EBP+40
    %Param1         %SET EBP+36
    %ReturnEAX      %SET EBP+28
    %ReturnECX      %SET EBP+24
    %ReturnEDX      %SET EBP+20
    %ReturnEBX      %SET EBP+16
    %ReturnEBP      %SET EBP+08
    %ReturnESI      %SET EBP+04
    %ReturnEDI      %SET EBP+00

↑ Align2Dword Variable
  This inline macro will align the 32bit GPR or contents of memory variable to DWORD (4) value upward.
Input
  Variable is 32bit register or memory operand.
Output
  CF=0, other registers unchanged.
Examples
  Align2Dword ECX Align2Dword [DwPointer]

    Align2Dword %MACRO Variable
                   ADDD %Variable,  3
                   ANDD %Variable, ~3
                %ENDMACRO Align2Dword

↑ Align2Qword Variable
  This inline macro will align the 32bit GPR or memory variable to QWORD (8) value upward.
Input
  Variable is 32bit register or memory operand.
Output
  CF=0, registers unchanged.
Example
  Align2Qword ECX ; ECX changed from 12 to 16. Align2Qword [mem32]

    Align2Qword %MACRO Variable
                   ADDD %Variable,  7
                   ANDD %Variable, ~7
                %ENDMACRO Align2Qword

↑ Align2Oword Variable
  This inline macro will align the 32bit GPR or memory variable to OWORD alias paragraph (16) value upward.
Input
  Variable is 32bit register or memory operand.
Output
  CF=0, registers unchanged.
Example
  Align2Oword ECX Align2Oword [mem32]

    Align2Oword %MACRO Variable
                   ADDD %Variable,  15
                   ANDD %Variable, ~15
                %ENDMACRO Align2Oword

↑ Clear Operand, Size=, Filler=0
  This macro will fill the string in memory at Operand offset with the character Filler=.
Input
  Operand is pointer to a memory variable.
  Size= specifies number of bytes to fill. By default it is `SIZE# Operand`.
  Filler=0 is DWORD value whose LSB will be used to fill the Operand.
Output
  All registers are preserved.
Examples
  Clear Buffer1, Filler=" " ; Fill the whole memory variable Buffer1 with spaces. Clear EDI, Size=80, Filler=EAX ; Fill the memory at EDI with the contents of AL.

    Clear %MACRO Operand, Size=, Filler=0
            PUSHD %Operand
            %IF "%Size" !=== ""
              PUSHD %Size
            %ELSE
              PUSHD SIZE# (%Operand)
            %ENDIF
            PUSHD %Filler
            CALL Clear32@RT:
    Clear32@RT: PROC1
        PUSH EAX,ECX,EDX,EDI
          MOV EDX,[ESP+20] ; Filler
          MOV ECX,[ESP+24] ; Size
          MOV EDI,[ESP+28] ; Operand
          SHRD EAX,EDX,8
          SHRD EAX,EDX,8
          SHRD EAX,EDX,8
          SHRD EAX,EDX,8
          SHR ECX,1
          JNC .10
          STOSB
    .10:  SHR ECX,1
          JNC .20
          STOSW
    .20:  JECXZ .90
          REP:STOSD
    .90:POP EDI,EDX,ECX,EAX
        RET 12
       ENDP1 Clear32@RT:
    %ENDMACRO Clear

↑ Compare Data1Ptr, Data1Size, Data2Ptr, Data2Size
  This macro will compare two data fields (strings) byte per byte.
Input
  Data1Ptr and Data1Size specify the first data field,
  Data2Ptr andData2Size the second one.
  The last parameter (Data2Size) may be omitted and it equals to Data1Size in this case.
Output
  ZF=1 if both fields are identical, otherwise ZF=0. All registers are preserved, .
Examples
  Compare F1, SIZE# F1, F2, SIZE# F2 Compare EDI,ESI,ECX

    Compare  %MACRO Data1Ptr,Data1Size,Data2Ptr,Data2Size
             %IF %# < 3                                                                                ; >
               %ERROR ID=5911, "Macro Compare requires 3 or 4 parameters."
               %EXITMACRO
             %ENDIF
             %IF %# > 3
               PUSHD %Data2Size,%Data2Ptr,%Data1Size,%Data1Ptr
             %ELSE
               PUSHD %Data1Size,%Data2Ptr,%Data1Size,%Data1Ptr
             %ENDIF
             CALL Compare32@RT:
    Compare32@RT: PROC1
           PUSH ECX,ESI,EDI
            MOV ESI,[ESP+16] ; %Data1Ptr
            MOV ECX,[ESP+20] ; %Data1Size
            MOV EDI,[ESP+24] ; %Data2Ptr
            CMP ECX,[ESP+28] ; %Data2Size
            JNE .90:
            REPE:CMPSB
       .90:POP EDI,ESI,ECX
           RET 16
      ENDP1 Compare32@RT:
    %ENDMACRO Compare

↑ CopyTo Destination, Source, Size=
  This macro will copy the memory content from Source to Destination.
Input
  Destination is a pointer to target memory.
  Source is a pointer to the source of data.
  Size= specifies number of bytes to copy. By default it is the SIZE# Destination attribute, if possible. The size may be alternatively specified with the keyword Size=.
Output
  All registers are preserved.
Examples
  CopyTo Buffer1, Buffer2 CopyTo EDI,ESI,ECX CopyTo EDI,Line,Size=80

    CopyTo  %MACRO Destination, Source, Size=
            %IF "%Size" !=== ""
              PUSHD %Size
            %ELSE
              %IF TYPE# %Destination = 'R'
                %ERROR ID=5912, "CopyTo data size not specified."
                %EXITMACRO CopyTo
              %ELSE
                PUSHD SIZE# (%Destination)
              %ENDIF
             %ENDIF
          PUSHD %Source, %Destination
          CALL CopyTo32@RT:
    CopyTo32@RT: PROC1
           PUSH ECX,ESI,EDI
            MOV ECX,[ESP+24] ; %Size
            MOV ESI,[ESP+20] ; %Source
            MOV EDI,[ESP+16] ; %Destination
            SHR ECX,1
            JNC .10:
            MOVSB
       .10: SHR ECX,1
            JNC .20:
            MOVSW
       .20: JECXZ .90
            REP:MOVSD
       .90:POP EDI,ESI,ECX
           RET 12
      ENDPROC1 CopyTo32@RT:
    %ENDMACRO CopyTo

↑ LodD Source, Size=
  Load signed or unsigned integer number in decimal notation and return its binary value in EAX.
  LodD tolerates leading white spaces before the number and underscores `_` inside the notation. The number may begin with `+` or `-`, at least one digit must immediately follow the sign.
  Parsing stops when non-digit character is encountered or when the number of characters specified with Size= has been examinated.
Input
  Source is a pointer to ANSI-encoded decimal number.
  When the Source operand is not specified explicitly, ESI is assumed.
  Size= specifies length of the source field in characters (=bytes). By default it is unlimited.
Output
  CF=0, EAX=loaded number in range -2_147_483_648 .. 4_294_967_295.
  ESI points behind the last parsed digit.
Error
  CF=1, EAX,ESI unchanged
  when the source number has wrong format:
  1. After skipping the leading white spaces Source does not start with a digit or sign.
  2. No digit immediately follows the sign.
  3. Loaded number does not fit into 32 bits.
Example
  InputField DB " -123.45" LodD InputField ; Loads EAX with -123d=0xFFFFFF85
Tested by
  tmac32.htm

    LodD  %MACRO  Source, Size=
        %IF "%Size" === ""
          %IF "%Source" === "" || "%Source" == "ESI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Source)
          %ENDIF
        %ELSE               ; Explicit Size was specified.
           PUSHD %Size
        %ENDIF
        %IF "%Source" === ""
           PUSH ESI         ; Implicit source.
        %ELSE
           PUSHD %Source
        %ENDIF
        CALL LodD32@RT:
    LodD32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
           MOV EDX,[EBP+40] ; Size.
           MOV ESI,[EBP+36] ; Source.
           MOV ECX,EDX
           ADD EDX,ESI      ; Parse end limit.
           INC ECX
           JNZ .00:
           MOV EDX,-1
     .00:  SUB EAX,EAX
           SUB ECX,ECX      ; Signum.
           SUB EBX,EBX      ; Output value accumulator.
           MOV EDI,10
     .10:  CMP ESI,EDX
           JNB .Error:
           LODSB
           CMP AL,' '
           JBE .10:         ; Skip leading white spaces.
           ; Sign or digit expected.
           CMP AL,'+'
           JE .20:
           CMP AL,'-'
           JNE .30:
           DEC ECX
     .20: ; At least one digit expected behind the signum, otherwise error.
           CMP ESI,EDX
           JNB .Error:
           LODSB
     .30:  SUB AL,'0'
           JB .Error:
           CMP AL,9
           JA .Error:
           MOV EBX,EAX      ; Most significant digit loaded.
     .40: ; Other digits or underscores expexted, otherwise the parsing stops.
           CMP ESI,EDX
           JNB .EndOfNumber:
           LODSB
           CMP AL,'_'
           JE .40:
           SUB AL,'0'
           JB .EndOfNumber1:
           CMP AL,9
           JA .EndOfNumber1:
           XCHG EAX,EBX
           PUSH EDX
            MUL EDI
           POP EDX
           JC .Error:
           ADD EBX,EAX
           JC .Error:
           SUB EAX,EAX
           JMP .40:
     .Error:DEC ESI
           STC
           JMP .95:
     .EndOfNumber1:DEC ESI
     .EndOfNumber:
           TEST ECX         ; Minus?
           JZ .90:
           NEG EBX
      .90: CLC
           MOV [%ReturnEAX],EBX
      .95: MOV [%ReturnESI],ESI
         POPAD
         RET 8
      ENDPROC1 LodD32@RT:
    %ENDMACRO LodD

↑ LodQD Source, Size=, Align=Left
  Load 64bit number in decimal notation and return its binary value in register pair EDX:EAX.
  LodQD tolerates underscores `_` inside the notation. The number may begin with `+` or `-`, at least one digit must immediately follow the sign.
  Parsing stops when non-digit character is encountered or when the number of characters specified with Size= has been examinated.
Input
  Source is a pointer to ANSI-encoded decimal number.
  When the Source operand is not specified explicitly, `ESI` is assumed.
  Size= specifies number of characters (=bytes) in the source field. When the Size is not explicitly specified, it assumes `SIZE# %Source`. Size is not limited if it cannot be determined from %Source.
  Align=Left. By default the source must start with sign or digit. LodQD will tolerate leading spaces or control characters only when `Align=right`.
Output
  CF=0, EDX:EAX=loaded number in range -9_223_372_036_854_775_808 .. 18_446_744_073_709_551_615.
  ESI points behind the last parsed digit.
Error
  CF=1, EDX,EAX undefined
  ESI unchanged
  when the source number has wrong format:
  1. source does not start with a digit or sign
  2. no digit immediately follows the sign
  3. loaded number does not fit into 64 bits
Example
  InputField DB " +123.45" LodQD InputField, Align=right ; loads EDX=0, EAX=123d=0x0000007B MOV EBX,EAX ; save the integer part LODSB ; skips the decimal point LodQD ; loads EDX=0, EAX=45d=0x0000002D

    LodQD  %MACRO  Source, Size=, Align=Left
        %LodQDflags %SETA %cpuextAlignL & "%Align[1]" == "L"
        PUSHD %LodQDflags
        %IF "%Size" === ""
          %IF "%Source" === "" || "%Source" == "ESI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Source)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Source" === ""
           PUSH ESI
        %ELSE
          PUSHD %Source
        %ENDIF
        CALL LodQD32@RT:
    LodQD32@RT: PROC1
         SUB EAX,EAX          ; Initialize the result.
         SUB EDX,EDX
         PUSHAD
           MOV EBP,ESP
     %LodQD@RTflags  %SET EBP+44
     %LodQD@RTSize   %SET EBP+40
     %LodQD@RTSource %SET EBP+36
           MOV ESI,[%LodQD@RTSource]
           MOV ECX,[%LodQD@RTSize]
           SUB EAX,EAX
           SUB EBX,EBX
           MOV EDI,10
           JECXZ .Error:
           JSt [%LodQD@RTflags],%cpuextAlignL,.30
      .10: LODSB               ; White spaces are tolerated.
           CMP AL,' '
           JA .40:
           LOOP .10:
     .Error:STC ; Error
           JMP .99:
      .30: LODSB               ; Signum or digit expected.
      .40: CMP AL,'+'
           JE .70:
           CMP AL,'-'
           JNE .60:
           SetSt [%LodQD@RTflags],%cpuextMinus
           JMP .70:
      .50: SUB EAX,EAX         ; Decimal digit expected.
           LODSB
      .60: SUB AL,'0'
           JB .EON:
           CMP AL,9
           JA .EON:
           MOV EBX,EAX         ; Temporary save number 0..9
           ; Multiply partial result in %ReturnEDX:%ReturnEAX by EDI=10
           MOV EAX,[%ReturnEDX]
           MUL EDI
           JC .Error:
           MOV [%ReturnEDX],EAX
           MOV EAX,[%ReturnEAX]
           MUL EDI
           MOV [%ReturnEAX],EAX
           ADD [%ReturnEDX],EDX
           JC .Error:
           ADD [%ReturnEAX],EBX
           ADCD [%ReturnEDX],0
           JC .Error:
           SetSt [%LodQD@RTflags],%cpuextLeading0 ; At least one digit was found.
      .70: LOOP .50:
           INC ESI
      .EON:DEC ESI ; End of numer
           JNSt [%LodQD@RTflags],%cpuextLeading0,.Error:
           JNSt [%LodQD@RTflags],%cpuextMinus,.90:
           NOTD [%ReturnEAX]
           NOTD [%ReturnEDX]
           ADDD [%ReturnEAX],1
           ADCD [%ReturnEDX],0
      .90: CLC
           MOV [%ReturnESI],ESI
     .99: POPAD
         RET 12
      ENDP1 LodQD32@RT:
    %ENDMACRO LodQD

↑ LodH Source, Size=, Align=Left
  Load 32bit number in hexadecimal notation to register EAX. Number may contain hexadecimal digits '0'..'9', 'a'..'f', 'A'..'F' optionally prefixed with '+' or '-' sign. At least one hexadecimal digit should immediately follow the sign. Parsing stops when non-hexadigit character is encountered or when Size= is exhausted.
  Prefix `0x` is not supported (LodH would return EAX=0 and ESI behind the `0x`.
Input
  Source is a pointer to the ANSI-encoded hexadecimal number.
  ESI is assumed when the Source operand is not specified explicitly.
  Size= is number of characters in the source field. When the size is not explicitly specified, `SIZE# %Source` is assumed. Size is not limited if it cannot be determined from %Source.
  Align=Left. By default the source must start with sign or hexadecimal digit. LodH will tolerate leading spaces or control characters only when Align=right.
Output
  CF=0, EAX=loaded number
  ESI=behind the last parsed source digit.
Error
  CF=1, EAX,ESI unchanged
  when the source number has wrong format:
  1. source does not start with a hexadecimal digit or sign,
  2. no hexadecimal digit immediately follows the sign,
  3. loaded number does not fit into 32 bits.
Example
  InputField DB "3FCh" LodH InputField ; loads EAX with 0x3FC=1020, ESI points to 'h'

    LodH  %MACRO  Source, Size=, Align=Left
        %LodHflags %SETA  %cpuextAlignL & "%Align[1]" == "L"
        PUSHD %LodHflags
        %IF "%Size" === ""
          %IF "%Source" === "" || "%Source" == "ESI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Source)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Source" === ""
          PUSH ESI
        %ELSE
          PUSHD %Source
        %ENDIF
        CALL LodH32@RT:
    LodH32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
     %LodH@RTflags  %SET EBP+44
     %LodH@RTSize   %SET EBP+40
     %LodH@RTSource %SET EBP+36
           MOV ESI,[%LodH@RTSource]
           MOV ECX,[%LodH@RTSize]
           SUB EAX,EAX
           SUB EBX,EBX
           JECXZ .20:
           JSt [%LodH@RTflags],%cpuextAlignL,.30
      .10: LODSB             ; White spaces are tolerated.
           CMP AL,' '
           JA .40:
           LOOP .10:
      .20: STC ; Error.
           JMP .95:
      .30: LODSB             ; Signum or digit expected.
      .40: CMP AL,'+'
           JE .70:
           CMP AL,'-'
           JNE .60:
           SetSt [%LodH@RTflags],%cpuextMinus
           JMP .70:
      .50: ; Digit expected.
           LODSB
      .60: SUB AL,'0'
           JB .80:
           CMP AL,9
           JNA .65:
           SUB AL,'A'-'0'
           JB .80:
           CMP AL,5
           JNA .64:
           SUB AL,'a'-'A'
           JB .80:
           CMP AL,5
           JA .80:
      .64: ADD AL,10
      .65: ; EAX is now a valid nibble 0x00000000..0x0000000F.
           TEST EBX,0xF000_0000
           JNZ .20: ; Overflow.
           SAL EBX,4
           ADD EBX,EAX
           SetSt [%LodH@RTflags],%cpuextLeading0 ; At least one digit was found.
      .70: LOOP .50:
           JMP .85:
      .80: DEC ESI
      .85: JNSt [%LodH@RTflags],%cpuextLeading0,.20:
           JNSt [%LodH@RTflags],%cpuextMinus,.90:
           NEG EBX
      .90: CLC
           MOV [%ReturnEAX],EBX
           MOV [%ReturnESI],ESI
     .95:POPAD
         RET 12
      ENDP1 LodH32@RT:
    %ENDMACRO LodH

↑ LodQH Source, Size=, Align=Left
  Load 64bit number in hexadecimal notation to register pair EDX:EAX.
  Number may contain hexadecimal digits '0'..'9', 'a'..'f', 'A'..'F' optionally prefixed with '+' or '-' sign. At least one hexadecimal digit should immediately follow the sign. Parsing stops when non-hexadigit character is encountered or when Size= is exhausted. Prefix `0x` is not supported (LodQH would return EDX:EAX=0 and ESI behind the `0x`.
Input
  Source is a pointer to the ANSI-encoded hexadecimal number.
  ESI is assumed when the Source operand is not specified explicitly.
  Size= specifies the length of the source field. When the size is not explicitly specified, `SIZE# %Source` is assumed. Size is not limited if it cannot be determined from %Source.
  Align=Left. By default the source must start with sign or hexadecimal digit. LodH will tolerate leading spaces or control characters only when Align=right.
Output
  CF=0, EDX:EAX=loaded number
  ESI=behind the last accepted source digit
Error
  CF=1, EAX,ESI unchanged
  when the source number has wrong format:
  1. source does not start with a hexadecimal digit or sign
  2. no hexadecimal digit immediately follows the sign
  3. loaded number does not fit into 64 bits
Example
  InputField DB "3FCh" LodQH InputField ; loads EDX=0, EAX=0x3FC=1020, ESI points to 'h'

    LodQH  %MACRO  Source, Size=, Align=Left
        %LodQHflags %SETA  %cpuextAlignL & "%Align[1]" == "L"
        PUSHD %LodQHflags
        %IF "%Size" === ""
          %IF "%Source" === "" || "%Source" == "ESI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Source)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Source" === ""
          PUSH ESI
        %ELSE
          PUSHD %Source
        %ENDIF
        CALL LodQH32@RT:
    LodQH32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
     %LodQH@RTflags  %SET EBP+44
     %LodQH@RTSize   %SET EBP+40
     %LodQH@RTSource %SET EBP+36
           MOV ESI,[%LodQH@RTSource]
           MOV ECX,[%LodQH@RTSize]
           SUB EAX,EAX
           SUB EBX,EBX
           SUB EDX,EDX ; Result is calculated in EDX:EBX.
           JECXZ .20:
           JSt [%LodQH@RTflags],%cpuextAlignL,.30
      .10: LODSB            ; White spaces are tolerated.
           CMP AL,' '
           JA .40:
           LOOP .10:
      .20: STC ; Error
           JMP .95:
      .30: LODSB            ; Signum or digit expected.
      .40: CMP AL,'+'
           JE .70:
           CMP AL,'-'
           JNE .60:
           SetSt [%LodQH@RTflags],%cpuextMinus
           JMP .70:
      .50: ; Digit expected.
           LODSB
      .60: SUB AL,'0'
           JB .80:
           CMP AL,9
           JNA .65:
           SUB AL,'A'-'0'-10
           JB .80:
           CMP AL,15
           JNA .65
           SUB AL,'a'-'A'
           JB .80:
           CMP AL,15
           JA .80:
      .65: SAL EBX,1
           RCL EDX,1
           JC .20:
           SAL EBX,1
           RCL EDX,1
           JC .20:
           SAL EBX,1
           RCL EDX,1
           JC .20:
           SAL EBX,1
           RCL EDX,1
           JC .20:
           ADD EBX,EAX
           SetSt [%LodQH@RTflags],%cpuextLeading0 ; At least one digit was found.
      .70: LOOP .50:
      .80: JNSt [%LodQH@RTflags],%cpuextLeading0,.20:
           JNSt [%LodQH@RTflags],%cpuextMinus,.90:
           NOT EBX
           NOT EDX
           ADD EBX,1
           ADC EDX,0
      .90: CLC
           MOV [%ReturnEAX],EBX
           MOV [%ReturnEDX],EDX
           MOV [%ReturnESI],ESI
      .95:POPAD
         RET 12
      ENDP1 LodQH32@RT:
    %ENDMACRO LodQH

↑ StoD Destination, Size=, Signed=Yes, Align=Left, LeadingZeroes=No
  Store 32bit integer from EAX in decimal notation.
Input
  EAX contains the input number.
  Destination is a pointer to memory where the decimal number will be stored. EDI is assumed when Destination is omitted.
  Size= specifies length of the Destination field. When the size is not explicitly specified, it is taken from `SIZE# %Destination` . Size is not limited if it cannot be determined from %Destination. Size will never exceed 11 characters. The output string is ANSI (1byte per digit).
  Signed=Yes specifies whether the input number is treated as signed. Negative numbers will be prefixed with minus sign `-`, positive sign is not used.
  Align=Left specifies alignment of the number in Destination field. If Size= cannot be determined, this parameter is ignored. When Align=right and Size= is specified, the vacant characters on the left side will be filled with spaces or unsignificant leading zeroes.
  LeadingZeroes=No specifies if the whole field should be filled with unsignificant `0` from the left side. When Align=Left or when the Size= is not determined, leading zeroes are not used.
Output
  CF=0, Destination filled, EDI points behind the last stored destination digit.
Error
  CF=1 on overflow (destination field was not long enough), EDI is unchanged.
Example
  OutputField DB 12*B'?' MOV EAX,123 StoD OutputField MOV AL,'.' STOSB MOV EAX,45 StoD ; OutputField is now "123.45??????", ; EDI points to the 1st question mark
Tested by
  tmac32.htm

    StoD  %MACRO  Destination, Size=, Signed=Yes, Align=Left, LeadingZeroes=No
        %StoDflags %SETA              %cpuextSigned   & "%Signed[1]" !== "N"
        %StoDflags %SETA %StoDflags | %cpuextAlignL   & "%Align[1]" == "L"
        %StoDflags %SETA %StoDflags | %cpuextLeading0 & "%LeadingZeroes[1]" !== "N"
        %IF "%Align[1]" !== "L" && "%Size" === "" && ("%Destination" === "" || "%Destination" == "EDI")
          %ERROR ID=5913, "StoD cannot Align=right when Size is not specified."
          %StoDflags %SETA %StoDflags | %cpuextAlignL
        %ENDIF
        PUSHD %StoDflags
        %IF "%Size" === ""
          %IF "%Destination" === "" || "%Destination" == "EDI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Destination)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Destination" === ""
          PUSH EDI
        %ELSE
          PUSHD %Destination
        %ENDIF
        CALL StoD32@RT:
    StoD32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
     %StoD@RTflags       %SET EBP+44
     %StoD@RTSize        %SET EBP+40
     %StoD@RTDestination %SET EBP+36
     %StoD@RTlength      %SET EBP-4
           SUB ESP,12+4
           MOV EDX,EAX ; input value
           MOV EDI,ESP ; temporary destination field
           PUSHD 10,100,1000,10000,100000,1000000, 10000000,100000000,1000000000
           MOV ESI,ESP
           MOV ECX,9
           JNSt [%StoD@RTflags],%cpuextSigned,.10:
           TEST EDX
           JNS .10:
           MOV AL,'-'
           NEG EDX
           SetSt [%StoD@RTflags],%cpuextMinus
           STOSB
      .10: LODSD ; 10^9, 10^8, 10^7 ...
           CMP EDX,EAX
           JNB .20
           LOOP .10:
           JMP .40:
      .20: MOV EBX,EAX
           SUB EAX,EAX
           XCHG EAX,EDX
           DIV EBX
           ADD AL,'0'
           STOSB
           LODSD
           LOOP .20:
           LEA ESI,[ESI-4]
      .40: MOV EAX,EDX
           ADD AL,'0'
           STOSB ; the last digit
           SUB EDI,ESI
           MOV [%StoD@RTlength],EDI
           MOV ECX,[%StoD@RTSize]
           SUB ECX,EDI ; padding characters if Align=right
           MOV EDI,[%StoD@RTDestination]
           JB .95: ; overflow
           JSt [%StoD@RTflags],%cpuextAlignL,.80:
           CMPD [%StoD@RTSize],-1
           JE .80: ; unspecified Size=
           JECXZ .80
           MOV AL,' '
           JNSt [%StoD@RTflags],%cpuextLeading0,.70:
           JNSt [%StoD@RTflags],%cpuextMinus,.60:
           DECD [%StoD@RTlength]
           MOVSB ; copy Minus sign
     .60:  MOV AL,'0'
     .70:  REP STOSB ; leading spaces or zeroes
     .80:  MOV ECX,[%StoD@RTlength]
           REP MOVSB ; significant digits
           CLC
           MOV [%ReturnEDI],EDI
     .95:  MOV ESP,EBP
         POPAD
         RET 12
      ENDP1 StoD32@RT:
    %ENDMACRO StoD

↑ StoQD Destination, Size=, Signed=Yes, Align=Left, LeadingZeroes=No
  Store 64bit integer number from register pair EDX:EAX in decimal notation do Destination.
Input
  EDX:EAX contains the input number.
  Destination is a pointer to memory where the decimal number will be stored. EDI is assumed when this operand is omitted.
  Size= specifies length of the Destination field. When the size is not explicitly specified, it is assumed `SIZE# %Destination`. Size is not limited if it cannot be determined from %Destination. Size will never exceed 20 characters. The output string is ANSI (1byte per digit).
  Signed=Yes specifies whether the input number is treated as signed. Negative numbers will be prefixed with `-` sign, positive sign is not used.
  Align=Left specifies alignment of the number in Destination field. If Size= cannot be determined, this parameter is ignored.
  When Align=Right and Size= is specified, the vacant characters on the left side will be filled with spaces or unsignificant leading zeroes.
  LeadingZeroes=No specifies if the whole field should be filled with unsignificant `0` from the left side. When Align=Left or when the Size= is not determined, leading zeroes are not used.
Output
  CF=0, Destination is filled,
  EDI points behind the last stored destination digit.
Error
  CF=1 on overflow (destination field was not long enough),
  EDI is unchanged.
Example
  OutputField DB 12*B'?' MOV EAX,123 CDQ StoQD OutputField MOV AL,'.' STOSB MOV EAX,45 StoQD ; OutputField is now "123.45??????", ; EDI points to the 1st question mark

    StoQD  %MACRO  Destination, Size=, Signed=Yes, Align=Left, LeadingZeroes=No
        %StoQDflags %SETA               %cpuextSigned   & "%Signed[1]" !== "N"
        %StoQDflags %SETA %StoQDflags | %cpuextAlignL   & "%Align[1]" == "L"
        %StoQDflags %SETA %StoQDflags | %cpuextLeading0 & "%LeadingZeroes[1]" !== "N"
        %IF "%Align[1]" !== "L" && "%Size" === "" && ("%Destination" === "" || "%Destination" == "EDI")
          %ERROR ID=5914, "StoQD cannot Align=right when Size= is not specified."
          %StoQDflags %SETA %StoQDflags | %cpuextAlignL
        %ENDIF
        PUSHD %StoQDflags
        %IF "%Size" === ""
          %IF "%Destination" === "" || "%Destination" == "EDI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Destination)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Destination" === ""
          PUSH EDI
        %ELSE
          PUSH %Destination
        %ENDIF
        CALL StoQD32@RT:
    StoQD32@RT: PROC1
        PUSHAD
          MOV EBP,ESP
    %StoQD@RTflags       %SET EBP+44
    %StoQD@RTSize        %SET EBP+40
    %StoQD@RTDestination %SET EBP+36
          SUB ESP,20
    %Result %SET EBP-20 ; Room for 20 digits.
           PUSHD 0x00000000,0x0000000A ; 10^1
           PUSHD 0x00000000,0x00000064 ; 10^2
           PUSHD 0x00000000,0x000003E8 ; 10^3
           PUSHD 0x00000000,0x00002710 ; 10^4
           PUSHD 0x00000000,0x000186A0 ; 10^5
           PUSHD 0x00000000,0x000F4240 ; 10^6
           PUSHD 0x00000000,0x00989680 ; 10^7
           PUSHD 0x00000000,0x05F5E100 ; 10^8
           PUSHD 0x00000000,0x3B9ACA00 ; 10^9
           PUSHD 0x00000002,0x540BE400 ; 10^10
           PUSHD 0x00000017,0x4876E800 ; 10^11
           PUSHD 0x000000E8,0xD4A51000 ; 10^12
           PUSHD 0x00000918,0x4E72A000 ; 10^13
           PUSHD 0x00005AF3,0x107A4000 ; 10^14
           PUSHD 0x00038D7E,0xA4C68000 ; 10^15
           PUSHD 0x002386F2,0x6FC10000 ; 10^16
           PUSHD 0x01634578,0x5D8A0000 ; 10^17
           PUSHD 0x0DE0B6B3,0xA7640000 ; 10^18
           PUSHD 0x8AC72304,0x89E80000 ; 10^19
           JNSt [%StoQD@RTflags],%cpuextSigned, .10:
           ; If the input is signed and negative, negate it first.
           TEST EDX
           JNS .10:
           SetSt [%StoQD@RTflags],%cpuextMinus ; Minus sign will be prefixed to result.
           NOT EAX
           NOT EDX
           ADD EAX,1
           ADC EDX,0
     .10:  MOV EBX,EAX
           ; EDX:EBX is unsigned 64bit integer.
           LEA EDI,[%Result]
           MOV AH,20            ; Number of digits in result.
     .20:  DEC AH
           JZ .40:
           MOV AL,'0'-1
           POP ECX,ESI          ; ESI:ECX is constant divisor 10^19, 10^18,,,
     .30:  INC AL
           SUB EBX,ECX
           SBB EDX,ESI
           JNB .30:
           ADD EBX,ECX
           ADC EDX,ESI
           STOSB
           JMP .20:
     .40:  MOV EAX,EBX
           ADD AL,'0'
           STOSB                ; The last digit of the result.
           LEA EDI,[%Result]
           MOV ECX,20
           MOV AL,'0'
           REPE SCASB
           LEA ESI,[EDI-1]      ; 1st significatnt digit.
           MOV EBX,[%StoQD@RTSize]
           MOV EDI,[%StoQD@RTDestination]
           MOV ECX,EBX
           MOV [%ReturnEDI],EDI ; For the case of overflow.
           LEA EAX,[%Result+20]
           JNSt [%StoQD@RTflags],%cpuextMinus,.45:
           DEC ECX ; %StoQD@RTSize-1
      .45: SUB EAX,ESI
           MOV EDX,EAX          ; Number of significant digits.
           SUB ECX,EAX          ; Stuff size.
           JC .99:              ; Size too small.
           JZ .80:              ; No stuff, ignore Alignment and Leading0.
           INC EBX
           JZ .80:              ; Undefined size - force align left.
           JSt [%StoQD@RTflags],%cpuextAlignL,.80:
           JSt [%StoQD@RTflags],%cpuextLeading0,.70:
           MOV AL,' '
           REP STOSB
           JMP .80:
      .70: JNSt [%StoQD@RTflags],%cpuextMinus,.75:
           MOV AL,'-'
           STOSB
      .75: MOV AL,'0'
           REP STOSB
           JMP .85:
      .80: JNSt [%StoQD@RTflags],%cpuextMinus,.85:
           MOV AL,'-'
           STOSB
      .85: MOV ECX,EDX
           REP MOVSB
           MOV [%ReturnEDI],EDI
     .99:  MOV ESP,EBP
         POPAD
         RET 12
      ENDP1 StoQD32@RT:
    %ENDMACRO StoQD

↑ StoH Destination, Size=, Case=Upper, Align=Right, LeadingZeroes=Yes
  Store 32bit signed integer number from EAX in hexadecimal notation.
Input
  EAX contains the input number.
  Destination is a pointer to memory where the hexadecimal number will be stored. EDI is assumed when Destination is omitted.
  Size= specifies the length of the Destination field. When the size is not explicitly specified, it is taken from `SIZE# %Destination`. Size is not limited if it cannot be determined from %Destination but it will never exceed 8 characters. The output string is ANSI (1byte per digit).
  Case=upper (or lower). This parameter will select between `ABCDEF` and `abcdef` digits.
  Align=right (or left) specifies alignment of the number in Destination field. If Size= cannot be determined, this parameter is ignored. When Align=right and Size= is specified, the vacant characters on the left side will be filled with spaces or unsignificant leading characters.
  LeadingZeroes=yes (or no) specifies if the whole field should be filled from the left side with unsignificant `0` or `F`. When Align=Left or when the Size= is not determined, leading characters are not used.
Output
  CF=0,
  EDI points behind the last stored destination digit.
Error
  CF=1,
  EDI is unchanged on overflow (destination field was not long enough).
Example
  OutputField DB 12*B'?' MOV EAX,123 StoH OutputField, Size=3, Align=Right ; OutputField is now '07B?????????', EDI points to the 1st '?' MOV EAX,-4567 StoH OutputField, Align=Left ; OutputField is now 'EE29????????' StoH OutputField ; OutputField is now 'FFFFFFFFEE29'
Tested by
  tmac32.htm

    StoH  %MACRO  Destination, Size=, Case=Upper, Align=Right, LeadingZeroes=Yes
        %StoHflags %SETA              %cpuextLowCase  & "%Case[1]" !== "U"
        %StoHflags %SETA %StoHflags | %cpuextAlignL   & "%Align[1]" !== "R"
        %StoHflags %SETA %StoHflags | %cpuextLeading0 & "%LeadingZeroes[1]" !== "N"
        %IF "%Align[1]" == "R" && "%Size" === "" && ("%Destination" === "" || "%Destination" == "EDI")
          %ERROR ID=5915, StoH cannot Align=right when Size= is not specified.
          %StoHflags %SETA %StoHflags | %cpuextAlignL
        %ENDIF
        PUSHD %StoHflags
        %IF "%Size" === ""
          %IF "%Destination" === "" || "%Destination" == "EDI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Destination)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Destination" === ""
          PUSHD EDI
        %ELSE
          PUSHD %Destination
        %ENDIF
        CALL StoH32@RT:
    StoH32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
     %StoH@RTflags       %SET EBP+44
     %StoH@RTSize        %SET EBP+40
     %StoH@RTDestination %SET EBP+36
           SUB ESP,8
           MOV EDX,EAX
           MOV EDI,ESP
           MOV ESI,ESP
           SUB EBX,EBX
           JNSt [%StoH@RTflags],%cpuextLowCase,.10:
           OR BL,'x'^'X'
      .10: TEST EDX
           MOV ECX,7
           JNS .20:
           MOV BH,0x0F           ; Unsignificant nibble is 0 of F.
      .20: SHLD EAX,EDX,4
           ROL EDX,4
           AND EAX,0x0000000F
           CMP AL,BH
           LOOPE .20:
           INC ECX
      .30: ADD AL,0x90
           DAA
           ADC AL,0x40
           DAA
           OR EAX,EBX ; LowCase
           STOSB
           SHLD EAX,EDX,4
           ROL EDX,4
           AND EAX,0x0000000F
           LOOP .30:
           ADD AL,0x90
           DAA
           ADC AL,0x40
           DAA
           OR EAX,EBX            ; LowCase.
           STOSB
           SUB EDI,ESI
           MOV EDX,EDI           ; Length of significant string.
           MOV ECX,[%StoH@RTSize]
           SUB ECX,EDI           ; Padding characters if Align=right.
           MOV EDI,[%StoH@RTDestination]
           JB .90: ; overflow
           JSt [%StoH@RTflags],%cpuextAlignL,.80:
           CMPD [%StoH@RTSize],-1
           JE .80:               ; Size= is not specified.
           JECXZ .80
           ; Leading character is 'F' or 'f' or '0' or ' '
           TEST BH
           MOV AL,'F'
           JZ .50:
           OR AL,BL
           JMP .70:
     .50:  MOV AL,'0'
           JSt [%StoH@RTflags],%cpuextLeading0,.70:
           MOV AL,' '
     .70:  REP STOSB             ; Leading spaces or zeroes or 'F's
     .80:  MOV ECX,EDX
           REP MOVSB             ; Significant digits.
           CLC
           MOV [%ReturnEDI],EDI
      .90: MOV ESP,EBP
         POPAD
         RET 12
      ENDP1 StoH32@RT:
     %ENDMACRO StoH

↑ StoQH Destination, Size=, Case=Upper, Align=Right, LeadingZeroes=Yes
  Store 64bit signed integer number from EDX:EAX in hexadecimal notation.
Input
  EDX:EAX contains the input number.
  Destination is a pointer to memory where the hexadecimal number will be stored. EDI is assumed when Destination is omitted.
  Size= specifies the length of the Destination field. When the size is not explicitly specified, it is assumed `SIZE# %Destination`.
  Size is not limited if it cannot be determined from %Destination but it will never exceed 16 characters. The output string is ANSI (1byte per digit).
  Case=upper (or lower). This parameter will select between `ABCDEF` and `abcdef`.
  Align=right (or left) specifies alignment of the number in Destination field. If Size= cannot be determined, this parameter is ignored.
  When Align=right and Size= is specified, the vacant characters on the left side will be filled with spaces or with unsignificant leading characters (`0` or `F`).
  LeadingZeroes=yes (or no) specifies if the whole field should be filled from the left side with unsignificant `0` or `F`. When Align=Left or when the Size= is not determined, leading characters are not used.
Output
  CF=0,
  EDI points behind the last stored destination digit.
Error
  CF=1,
  EDI is unchanged on overflow (destination field was not long enough).
Example
  OutputField DB 12*B'?' MOV EAX,123 CDQ StoQH OutputField, Size=3, Align=right ; OutputField is now '07B?????????', EDI points to the 1st '?' MOV EAX,-4567 CDQ StoQH OutputField, Align=Left ; OutputField is now 'EE29????????' StoQH OutputField ; OutputField is now 'FFFFFFFFEE29'

     StoQH  %MACRO  Destination, Size=, Case=Upper, Align=Right, LeadingZeroes=Yes
        %StoQHflags %SETA               %cpuextLowCase  & "%Case[1]"!=="U"
        %StoQHflags %SETA %StoQHflags | %cpuextAlignL   & "%Align[1]"!=="R"
        %StoQHflags %SETA %StoQHflags | %cpuextLeading0 & "%LeadingZeroes[1]"!=="N"
        %IF "%Align[1]" == "R" && "%Size" === "" && ("%Destination" === "" || "%Destination" == "EDI")
          %ERROR ID=5916, StoQH cannot Align=right when Size= is not specified.
          %StoQHflags %SETA %StoQHflags | %cpuextAlignL
        %ENDIF
        PUSHD %StoQHflags
        %IF "%Size" === ""
          %IF "%Destination" === "" || "%Destination" == "EDI"
            PUSHD -1
          %ELSE
            PUSHD SIZE# (%Destination)
          %ENDIF
        %ELSE
          PUSHD %Size
        %ENDIF
        %IF "%Destination" === ""
          PUSH EDI
        %ELSE
          PUSHD %Destination
        %ENDIF
        CALL StoQH32@RT:
     StoQH32@RT: PROC1
         PUSHAD
           MOV EBP,ESP
     %StoQH@RTflags       %SET EBP+44
     %StoQH@RTSize        %SET EBP+40
     %StoQH@RTDestination %SET EBP+36
           CMPD [%StoQH@RTSize],-1
           JNE .05:
           SetSt [%StoQH@RTflags],%cpuextAlignL
      .05: PUSHD 'CDEF'
           PUSHD '89AB'
           PUSHD '4567'
           PUSHD '0123'
           LEA EBX,[EBP-16]              ; Table '0'..'F'
           JNSt [%StoQH@RTflags],%cpuextLowCase,.10:
           MOVW [EBX+10],'ab'
           MOVD [EBX+12],'cdef'
      .10: SUB ESP,16 ; Room for output digits.
           MOV EDI,ESP
           MOV ECX,8
      .20: MOV EAX,EDX
           ROL EDX,4
           SHR EAX,28
           MOV AL,[EAX+EBX]
           STOSB
           LOOP .20:
           MOV CL,8
           MOV EDX,[%ReturnEAX]
      .30: MOV EAX,EDX
           ROL EDX,4
           SHR EAX,28
           MOV AL,[EAX+EBX]
           STOSB
           LOOP .30:
           MOV EDX,[%ReturnEDX]
           MOV EAX,[%ReturnEAX]         ; Find the number of significant hexadigits to ECX.
           TEST EDX
           JNS .40:
           SetSt [%StoQH@RTflags],%cpuextMinus
           NOT EAX ; EDX:EAX is negative.
           NOT EDX
           ADD EAX,1
           ADC EDX,0
      .40: ; Number is positive.
           BSR ECX,EDX
           JZ .50:
           ADD CL,36 ; ECX is now 36..67
           SAR ECX,2
           JMP .60:
      .50: BSR ECX,EAX
           JNZ .55:
           MOV ECX,EAX
      .55: ADD CL,4
           SAR ECX,2
      .60: ; ECX=number of significant digits (1..16)
           LEA ESI,[ESP+16]
           SUB ESI,ECX
           MOV EDI,[%StoQH@RTDestination]
           MOV EDX,[%StoQH@RTSize]
           MOV AL,'0'
           JNSt [%StoQH@RTflags],%cpuextMinus, .70:
           MOV AL,[EBX+15]                         ; 'F' or 'f'
      .70: JSt [%StoQH@RTflags],%cpuextLeading0,.75:
           MOV AL,' '
           CMPB [ESI],'8'
           JB .72:
           JSt [%StoQH@RTflags],%cpuextMinus,.75:
           InvSt [%StoQH@RTflags],%cpuextMinus
      .72: JNSt [%StoQH@RTflags],%cpuextMinus,.75:
           CMP CL,16
           JNB .75:
           INC ECX
           DEC ESI
      .75: SUB EDX,ECX                             ; Number of unsignificant digits
           JC .90:                                 ; Output %Size too small.
           JZ .80:
           JSt [%StoQH@RTflags],%cpuextAlignL,.80: ; No leading characters
           XCHG ECX,EDX
           REP STOSB                               ; Leading characters '0','F' or ' '
           XCHG EDX,ECX
     .80:  REP MOVSB ; significant digits
           CLC
     .90:  MOV [%ReturnEDI],EDI
           MOV ESP,EBP
         POPAD
         RET 12
      ENDP1 StoQH32@RT:
     %ENDMACRO StoQH

↑ StripColons PtrReg, SizeReg, Unicode=%^UNICODE
  Remove leading and trailing colon(s) `:` from input field.
Input
  PtrReg is a register which points to the input field.
  SizeReg is a register with size of the input field in bytes. Both arguments must be specified as general purpose 32bit registers.
  Unicode= is a logical parameter which tells whether the strings is ANSI or WIDE.
Output
  Both input registers are changed if the field begins and|or ends with colons. If the input field only contains one or more colons, the 2nd register will return 0.

    StripColons %MACRO PtrReg, SizeReg, Unicode=%^UNICODE
          %IF TYPE#%PtrReg <> 'R' || TYPE#%SizeReg <> 'R'
            %ERROR ID=5918, "Both arguments of StripColons must be GPR."
            %EXITMACRO StripColons
          %ENDIF
          %IF %Unicode ; WIDE variant.
     StripColons1%.:
            CMP %SizeReg,2
            JL StripColons9%.:
            CMPW [%PtrReg+%SizeReg-2],":"
            JNE StripColons2%.:
            DEC %SizeReg,%SizeReg
            JMP StripColons1%.:
     StripColons2%.:
            CMPW [%PtrReg],":"
            JNE StripColons9%.:
            INC %PtrReg,%PtrReg
            CMP %SizeReg,2
            JL StripColons9%.:
            DEC %SizeReg,%SizeReg
            JMP StripColons2%.:
     StripColons9%.:
          %ELSE ; ANSI variant.
            TEST %SizeReg
            JZ StripColons9%.:
     StripColons1%.:
            CMPB [%PtrReg+%SizeReg-1],':'
            JNE StripColons2%.:
            DEC %SizeReg
            JNG StripColons9%.:
            JMP StripColons1%.:
     StripColons2%.:
            CMPB [%PtrReg],':'
            JNE StripColons9%.:
            INC %PtrReg
            DEC %SizeReg
            JMP StripColons2%.:
          %ENDIF
     StripColons9%.:
     %ENDMACRO StripColons

↑ StripQuotes PtrReg, SizeReg, Unicode=%^UNICODE
  Remove leading and trailing double quote `"` from input field.
Input
  PtrReg is a register which points to the input field.
  SizeReg is the register with size of the input field in bytes. Both arguments must be specified as general purpose 32bit registers.
  Unicode= is a logical parameter which tells whether the strings is ANSI or WIDE.
Output
  Both input registers are changed if the field begins and/or ends with double quote. If the input field only contains one or two quotes, the 2nd register will return 0.

    StripQuotes %MACRO PtrReg, SizeReg, Unicode=%^UNICODE
          %IF TYPE#%PtrReg <> 'R' || TYPE#%SizeReg <> 'R'
            %ERROR ID=5919, "Both arguments of StripQuotes must be GPR."
            %EXITMACRO StripQuotes
          %ENDIF
          %IF %Unicode  ; WIDE variant.
            CMP %SizeReg,2*2
            JB StripQuotes9%.:
            CMPW [%PtrReg+%SizeReg-2],'"'
            JNE StripQuotes1%.:
            DEC %SizeReg,%SizeReg
     StripQuotes1%.:
            CMPW [%PtrReg],'"'
            JNE StripQuotes9%.:
            INC %PtrReg,%PtrReg
            DEC %SizeReg,%SizeReg
     StripQuotes9%.:
          %ELSE  ; ANSI variant.
            CMP %SizeReg,2
            JB StripQuotes9%.:
            CMPB [%PtrReg+%SizeReg-1],'"'
            JNE StripQuotes1%.:
            DEC %SizeReg
     StripQuotes1%.:
            CMPB [%PtrReg],'"'
            JNE StripQuotes9%.:
            INC %PtrReg
            DEC %SizeReg
    StripQuotes9%.:
         %ENDIF
     %ENDMACRO StripQuotes

↑ StripApostrophes PtrReg, SizeReg, Unicode=%^UNICODE
  Remove leading and trailing single quote `'` from input field.
Input
  PtrReg is a register which points to the input field.
  SizeReg is register with size of the input field in bytes. Both arguments must be specified as general purpose 32bit registers.
  Unicode= is a logical parameter which tells whether the strings is ANSI or WIDE.
Output
  Both input registers are changed if the field begins and/or ends with apostrophe. If the input field only contains one or two apostrophes, the 2nd register will return 0.

    StripApostrophes %MACRO PtrReg, SizeReg, Unicode=%^UNICODE
          %IF TYPE#%PtrReg <> 'R' || TYPE#%SizeReg <> 'R'
            %ERROR ID=5917, "Both arguments of StripApostrophes must be GPR."
            %EXITMACRO StripApostrophes
          %ENDIF
          %IF %Unicode  ; WIDE variant.
            CMP %SizeReg,2*2
            JB StripApostrophes9%.:
            CMPW [%PtrReg+%SizeReg-2],"'"
            JNE StripApostrophes1%.:
            DEC %SizeReg,%SizeReg
     StripApostrophes1%.:
            CMPW [%PtrReg],"'"
            JNE StripApostrophes9%.:
            INC %PtrReg,%PtrReg
            DEC %SizeReg,%SizeReg
     StripApostrophes9%.:
          %ELSE  ; ANSI variant.
            CMP %SizeReg,2
            JC StripApostrophes9%.:
            CMPB [%PtrReg+%SizeReg-1],"'"
            JNE StripApostrophes1%.:
            DEC %SizeReg
     StripApostrophes1%.:
            CMPB [%PtrReg],"'"
            JNE StripApostrophes9%.:
            INC %PtrReg
            DEC %SizeReg
     StripApostrophes9%.:
          %ENDIF
     %ENDMACRO StripApostrophes

↑ StripSpaces PtrReg, SizeReg, Unicode=%^UNICODE
  Remove white spaces (characters equal or below ASCII 32) which surround the input field.
Input
  PtrReg is a register which points to the input field.
  SizeReg is a register with size of the input field in bytes. Both arguments must be specified as general purpose 32bit registers.
  Unicode= is a logical parameter which tells whether the strings is ANSI or WIDE.
Output
  Both input registers are changed if the field begins or ends with white spaces. If the input field contains nothing but spaces, the 2nd register will return 0.
Example
  Field: DB " some text ",13,10,0 MOV ESI,Field MOV ECX,SIZE#Field ; 14 StripSpaces ESI,ECX ; ESI=Field+1 ECX=9
Tested by
  tmac32.htm

    StripSpaces %MACRO PtrReg, SizeReg, Unicode=%^UNICODE
          %IF TYPE#%PtrReg <> 'R' || TYPE#%SizeReg <> 'R'
            %ERROR ID=5920, "Both arguments of StripSpaces must be GPR."
            %EXITMACRO StripSpaces
          %ENDIF
          %IF %Unicode ; WIDE variant.
     StripSpaces1%.:
            CMP %SizeReg,2
            JL StripSpaces9%.:
            CMPW [%PtrReg+%SizeReg-2]," "
            JA StripSpaces2%.:
            DEC %SizeReg,%SizeReg
            JMP StripSpaces1%.:
     StripSpaces2%.:
            CMPW [%PtrReg]," "
            JA StripSpaces9%.:
            INC %PtrReg,%PtrReg
            CMP %SizeReg,2
            JL StripSpaces9%.:
            DEC %SizeReg,%SizeReg
            JMP StripSpaces2%.:
     StripSpaces9%.:
          %ELSE  ; ANSI variant.
            TEST %SizeReg
            JZ StripSpaces9%.:
     StripSpaces1%.:
            CMPB [%PtrReg+%SizeReg-1]," "
            JA StripSpaces2%.:
            DEC %SizeReg
            JNG StripSpaces9%.:
            JMP StripSpaces1%.:
     StripSpaces2%.:
            CMPB [%PtrReg]," "
            JA StripSpaces9%.:
            INC %PtrReg
            DEC %SizeReg
            JMP StripSpaces2%.:
     StripSpaces9%.:
          %ENDIF
     %ENDMACRO StripSpaces

     ENDHEAD cpuext32

▲Back to the top▲