This file can be included to 16bit programs written in Euro Assembler.
The library contains OS-independent macroinstructions for 16bit programs
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, CopyTo provide some string operations,
Lod* converts numbers from human-readable notation to a binary number,
Sto* does the opposite.
Similar macros with identical names for different program width are defined in cpuext32.htm and cpuext64.htm.
See also cpuext.htm for width-indepentent macros.
cpuext16 HEAD
; 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 BP frame. %Par4 %SET BP+24 %Par3 %SET BP+22 %Par2 %SET BP+20 %Par1 %SET BP+18 %ReturnAX %SET BP+14 %ReturnCX %SET BP+12 %ReturnDX %SET BP+10 %ReturnBX %SET BP+08 %ReturnSP %SET BP+06 %ReturnBP %SET BP+04 %ReturnSI %SET BP+02 %ReturnDI %SET BP+00
Align2Word %MACRO Variable ADDW %Variable, 1 ANDW %Variable, ~1 %ENDMACRO Align2Word
Align2Dword %MACRO Variable ADDW %Variable, 3 ANDW %Variable, ~3 %ENDMACRO Align2Dword
Align2Qword %MACRO Variable ADDW %Variable, 7 ANDW %Variable, ~7 %ENDMACRO Align2Qword
SIZE# Operand
.
Clear %MACRO Operand, Size=, Filler=0 PUSHW %Filler %IF "%Size" !=== "" PUSHW %Size %ELSE PUSHW SIZE# (%Operand) %ENDIF PUSHW %Operand CALL Clear@RT:: Clear@RT:: PROC1 PUSHAW MOV BP,SP MOV AX,[%Par3] ; Filler. MOV CX,[%Par2] ; Size. MOV DI,[%Par1] ; Operand. MOV AH,AL SHR CX,1 JNC .20 STOSB .20: JCXZ .90 REP:STOSW .90:POPAW RET 3*2 ENDP1 Clear@RT:: %ENDMACRO Clear
CopyTo %MACRO Destination, Source, Size= %IF "%Size" !=== "" PUSHW %Size %ELSE %IF TYPE# %Destination = 'R' %ERROR ID=5912, "CopyTo Size= is not specified." %EXITMACRO CopyTo %ELSE PUSHW SIZE# (%Destination) %ENDIF %ENDIF PUSHW %Source, %Destination CALL CopyTo@RT:: CopyTo@RT:: PROC1 PUSHAW MOV BP,SP MOV CX,[%Par3] ; %Size MOV SI,[%Par2] ; %Source MOV DI,[%Par1] ; %Destination CLD SHR CX,1 JNC .10: MOVSB .20: JCXZ .90 REP:MOVSW .90:POPAW RET 3*2 ENDPROC1 CopyTo@RT:: %ENDMACRO CopyTo
LodD %MACRO Source, Size= %IF "%Source" !== "" ; Explicit Source was specified. %LodDSource %SET %Source %ELSE %LodDSource %SET SI %ENDIF %IF "%Size" !== "" ; Explicit Size was specified. PUSHW %Size,%LodDSource %ELSE PUSHW -1,%LodDSource %ENDIF CALL LodD@RT:: LodD@RT:: PROC1 PUSHAW MOV BP,SP MOV DX,[%Par2] ; Size. MOV SI,[%Par1] ; Source. MOV CX,DX CLD ADD DX,SI ; Parse end limit. INC CX JNZ .00: MOV DX,-1 .00: SUB AX,AX SUB CX,CX ; Signum. SUB BX,BX ; Output value accumulator. MOV DI,10 ; Numeric base. .10: CMP SI,DX JNB .Error: LODSB CMP AL,' ' JBE .10: ; Skip leading white spaces. ; Sign or digit expected. CMP AL,'+' JE .20: CMP AL,'-' JNE .30: DEC CX .20: ; At least one digit expected behind the signum, otherwise error. CMP SI,DX JNB .Error: LODSB .30: SUB AL,'0' JB .Error: CMP AL,9 JA .Error: MOV BX,AX ; Most significant digit loaded. .40: ; Other digits or underscores expexted, otherwise the parsing stops. CMP SI,DX JNB .EndOfNumber: LODSB CMP AL,'_' JE .40: SUB AL,'0' JB .EndOfNumber1: CMP AL,9 JA .EndOfNumber1: XCHG AX,BX PUSH DX MUL DI POP DX JC .Error: ADD BX,AX JC .Error: SUB AX,AX JMP .40: .Error:DEC SI STC JMP .95: .EndOfNumber1:DEC SI .EndOfNumber: TEST CX ; Minus? JZ .90: NEG BX .90: CLC MOV [%ReturnAX],BX .95: MOV [%ReturnSI],SI POPAW RET 2*2 ENDPROC1 LodD@RT:: %ENDMACRO LodD
0x
is not supported (LodH would return AX=0 and SI 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" %IF "%Source" === "" %LodHSource %SET SI %ELSE %LodHSource %SET %Source %ENDIF %IF "%Size" !=== "" ; explicit Size was specified. %LodHSize %SET %Size %ELSE %LodHSize %SETA -1 %IF "%LodHSource" !== "SI" %LodHSize %SETA SIZE# (%LodHSource) %ENDIF %ENDIF PUSHW %LodHflags, %LodHSize, %LodHSource CALL LodH@RT:: LodH@RT:: PROC1 PUSHAW MOV BP,SP MOV SI,[%Par1] ; Source. MOV CX,[%Par2] ; Size. SUB AX,AX SUB BX,BX ; Accumulator of the result value. CLD JCXZ .20: TESTW [%Par3],%cpuextAlignL JNZ .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: ORW [%Par3],%cpuextMinus JMP .70: .50: LODSB ; Digit expected. .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 BX,4 ADD BX,AX ORW [%Par3],%cpuextLeading0 ; At least one digit was found. .70: LOOP .50: .80: TESTW [%Par3],%cpuextLeading0 JZ .20: TESTW [%Par3],%cpuextMinus JZ .90: NEG BX .90: CLC MOV [%ReturnAX],BX MOV [%ReturnSI],SI .95:POPAW RET 3*2 ENDP1 LodH@RT:: %ENDMACRO LodH
SIZE# %Destination
. Size is not limited if it cannot be determined from %Destination.
Size will never exceed 6 characters.
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 "%Destination"==="" %StoDDestination %SET DI ; Default destination if omitted. %ELSE %StoDDestination %SET %Destination %ENDIF %IF "%Size"!==="" %StoDSize %SET %Size %ELSE %StoDSize %SETA -1 ; Default size is unlimited if destination/size not specified. %IF "%StoDDestination" !== "DI" %StoDSize %SETA SIZE# (%Destination) %ENDIF %ENDIF %IF %StoDSize = -1 && "%Align[1]"!=="L" %ERROR ID=5913, "StoD cannot Align=right when Size is not specified." %StoDflags %SETA %StoDflags | %cpuextAlignL %ENDIF PUSHW %StoDflags, %StoDSize, %StoDDestination CALL StoD@RT:: StoD@RT:: PROC1 PUSHAW MOV BP,SP PUSH ES SUB SP,2+6 ; Word with string size + 6 bytes of temporary string. CLD MOV DX,AX ; Input value. MOV DI,SP ; Temporary destination field, 6 bytes. PUSH SS POP ES PUSHW 10,100,1000,10000 MOV SI,SP MOV CX,4 ; Number of pushed constants. TESTW [%Par3],%cpuextSigned JZ .10: TEST DX JNS .10: MOV AL,'-' NEG DX ORW [%Par3],%cpuextMinus STOSB .10: LODSW [SS:SI] ; 10^4, 10^3, 10^2, 10^1. CMP DX,AX JNB .20 LOOP .10: JMP .40: .20: XCHG BX,AX SUB AX,AX XCHG AX,DX DIV BX ADD AL,'0' STOSB LODSW [SS:SI] LOOP .20: SUB SI,2 .40: MOV AX,DX ADD AL,'0' STOSB ; The last digit. SUB DI,SI ; Number of significant digits. MOV [BP-4],DI ; Store the string size. MOV CX,[%Par2] ; Allocated string Size. SUB CX,DI ; Number of padding characters when Align=right. MOV DI,[%Par1] ; Destination. MOV ES,[BP-2] ; Pushed Destination segment. JB .95: ; If overflowed. TESTW [%Par3],%cpuextAlignL JNZ .80: CMPW [%Par2],-1 JE .80: ; If unspecified Size=. JCXZ .80: MOV AL,' ' TESTW [%Par3],%cpuextLeading0 JZ .70: TESTW [%Par3],%cpuextMinus JZ .60: DECW [BP-4] MOVSB [ES:DI],[SS:SI] ; Copy Minus sign. .60: MOV AL,'0' .70: REP STOSB ; Leading spaces or zeroes. .80: MOV CX,[BP-4] ; Size of string with significant digits. REP MOVSB [ES:DI],[SS:SI] ; Significant digits. CLC MOV [%ReturnDI],DI .95: MOV SP,BP POPAW RET 3*2 ENDP1 StoD@RT:: %ENDMACRO StoD
SIZE# %Destination
.
Size is not limited if it cannot be determined from %Destination
but it will never exceed 4 characters.
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 "%Destination"==="" %StoHDestination %SET DI ; Default destination if omitted. %ELSE %StoHDestination %SET %Destination %ENDIF %IF "%Size"!==="" %StoHSize %SET %Size %ELSE %StoHSize %SETA -1 ; Default size is unlimited if destination/size not specified. %IF "%StoHDestination" !== "DI" %StoHSize %SETA SIZE# (%Destination) %ENDIF %ENDIF %IF %StoHSize = -1 && "%Align[1]"!=="L" %ERROR ID=5915, "StoH cannot Align=right when Size= is not specified." %StoHflags %SETA %StoHflags | %cpuextAlignL %ENDIF PUSHW %StoHflags, %StoHSize, %StoHDestination CALL StoH@RT:: StoH@RT:: PROC1 PUSHAW MOV BP,SP SUB SP,4 ; Room for a temporary hexadecimal string. MOV DX,AX ; Input value. MOV DI,SP ; Temporary destination field. MOV SI,SP PUSH ES,SS POP ES SUB BX,BX TESTW [%Par3],%cpuextLowCase JZ .10: OR BL,'x'^'X' ; Convert 'A'..'Z' to 'a'..'z' when BL=0x20. .10: TEST DX MOV CX,3 JNS .20: MOV BH,0x0F ; Unsignificant nibble is 0x0, or 0xF when input is negative. .20: SHLD AX,DX,4 ; Copy MSNibble from DH to AL. ROL DX,4 ; Prepare input for the next nibble. AND AX,0x000F ; Only current nibble is kept in AL CMP AL,BH LOOPE .20: INC CX .30: ADD AL,0x90 ; Convert the nibble to a hexadigit. DAA ADC AL,0x40 DAA OR AX,BX ; Convert the digit to LowCase. STOSB SHLD AX,DX,4 ROL DX,4 AND AX,0x000F LOOP .30: ; The next nibble. ADD AL,0x90 ; Convert the last nibble to a hexadigit. DAA ADC AL,0x40 DAA OR AX,BX ; Convert the digit to LowCase. STOSB SUB DI,SI MOV DX,DI ; Length of the significant string. MOV CX,[%Par2]; Size=. MOV DI,[%Par1] MOV ES,[BP-6] ; Restore saved ES. SUB CX,DX ; Padding characters if Align=right. JB .90: ; If overflow. TESTW [%Par3],%cpuextAlignL JNZ .80: CMPW [%Par2],-1 JE .80: ; If unspecified Size=. JCXZ .80 ; Leading character is 'F' or 'f' or '0' or ' ' TEST BH MOV AL,'F' JZ .50: OR AL,BL ; Convert the leading digit to LowCase. JMP .70: .50: MOV AL,'0' TESTW [%Par3],%cpuextLeading0 JNZ .70: MOV AL,' ' .70: REP STOSB ; Leading spaces or zeroes or 'F's. .80: MOV CX,DX ; Length of the significant string. REP MOVSB [ES:DI],[SS:SI], ; Significant digits. CLC MOV [%ReturnDI],DI .90: MOV SP,BP POPAW RET 3*2 ENDP1 StoH@RT:: %ENDMACRO StoH
ENDHEAD cpuext16