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 %MACRO Variable ADDD %Variable, 3 ANDD %Variable, ~3 %ENDMACRO Align2Dword
Align2Qword %MACRO Variable ADDD %Variable, 7 ANDD %Variable, ~7 %ENDMACRO Align2Qword
Align2Oword %MACRO Variable ADDD %Variable, 15 ANDD %Variable, ~15 %ENDMACRO Align2Oword
SIZE# Operand
.
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 %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 %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 %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
ESI
is assumed.
SIZE# %Source
. Size is not limited if it cannot be determined from %Source.
Align=right
.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
0x
is not supported (LodH would return EAX=0 and ESI behind the 0x
.
SIZE# %Source
is assumed.
Size is not limited if it cannot be determined from %Source.
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
0x
is not supported (LodQH would return EDX:EAX=0 and ESI behind the
0x
.SIZE# %Source
is assumed.
Size is not limited if it cannot be determined from %Source.
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
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).
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
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).
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
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).
ABCDEF
and abcdef
digits.
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
SIZE# %Destination
.
ABCDEF
and abcdef
.
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 %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 %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 %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 %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