The Extra Echo Assembler Project

Extra Echo, a multi-functional batch enhancer under DOS and in Windows DOS boxes

|  Home  |
|  Download Extra Echo XE 1.33 (xe133.zip)  |

XE V1.33/2012 FREEWARE

XE is used in batch programs for DOS and in DOS windows of Windows 95/98/ME/NT/2000/XP. It works similar to the ECHO command, however, using replacement parameters it is possible to send specific characters to the screen. In addition, several new functions are introduced (see below). The output text can be re-directed into a file. The number sign # is used to start replacement parameters. % parameters can be used in the same way as with the ECHO command.

Invocation example

XE Comment 1 :Info -#3E Tiger#; Comment 2

Screen output

Info -> Tiger

The first colon starts the screen output,
#; stops the screen output
#00 to #FF serves as replacement for the hex value of a character to be output

#3E >
#3C <
#22 "
#7C |
#25 %
#26 &
#1B <ESC>
#09 <TAB>
#27 '
#0C FF  (Form Feed)
#07 BEL (Bell)
#40 @
#0D CR alone
#0A LF alone
#5E ^

#V additional new line output (CR+LF)
#P no CR+LF at the end of the line
## outputs # once
#G sends time and date stamp to the screen (German)
#$ sends time and date stamp to the screen (English)
#H sends only the time stamp to the screen
#; as of here the command line is no longer evaluated (comment)

Other functions

#=G Synchronization to the next full second (waits until the next new second),
    reaction on a key stroke: abortion and errorlevel 100
#=H Deletion of the keyboard buffer, generates errorlevel 0 or 1:
    Errorlevel 0, if the buffer was empty
    Errorlevel 1, if the buffer contained characters
#X  or
#=X Bell sound, output directly via BIOS,
    i.e. no redirection is possible as a character into a file
#U  Sound 880 Hz, short
#W  Sound 440 Hz, long
#=Y Clear Screen
#Z  or
#=Z No prompt on a key call (see next)
#_\ outputs current drive letter
#\  outputs current directory (with a \ at the end)

#[...] Key call

Between the brackets [ ] the characters A...Z, 0...9 and SPACE can be inserted. The program waits for an entry from the keyboard. If the entered character is equal to one of the characters inserted between the brackets, the program is continued and an errorlevel (1...n) is generated. The position of the character between the [ ] determines the value of the errorlevel produced. A...Z means the same as a...z. If SPACE is defined between the [ ], the entry of the ENTER key causes the same as the SPACE key. Instead of 0..9, the function keys F1..F10 can also be used (0=F10).

Example:  XE :#[d7T ]
Result:
D or d  produce errorlevel 1
7 or F7 produce errorlevel 2
T or t  produce errorlevel 3
SPACE or ENTER key produce errorlevel 4
ESC produces errorlevel 0 (fixed setting)

A maximum of 40 characters may be inserted between the brackets. If characters are used several times, only the first ones are valid.

Example:  XE :#[A 5 u a]
Result:
A or a produce errorlevel 1
SPACE or ENTER key produce errorlevel 2
5 or F5 produce errorlevel 3
U or u produce errorlevel 5
ESC produces errorlevel 0 (fixed setting)
Errorlevels 4, 6 and 7 can never be produced because
SPACE and 'a' are used several times.

If a preselected key is pressed, the entered character is output to the screen. Instead of ESC, SPACE or ENTER always a SPACE is output. If this sreen output is not desired, it can be suppressed by inserting #=Z (or #Z) at the beginning of the command line.

Example:  XE :#=ZTextText#[ABC123 ]More text
Output:   TextTextMore text
          (the keyboard entry has no effect to the screen output)

Special feature: If no character is inserted between [], any key is accepted and errorlevel 0 is generated (like with ESC).

#(...) Cursor control

Invocation of #(...) (Cursor control) results in changing shape and/or position of the cursor. Examples:

#(N) or #(ON)  Cursor is turned on  (VGA and higher)
#(F) or #(OFF) Cursor is turned off (VGA and higher)
#(V) or #(VGA) Standard setting for VGA and higher (also MCGA)
#(C) or #(CGA) Standard setting for CGA and higher
#(M) or #(MDA) Standard setting for MDA, HERCULES, EGA
#(B) or #(BIG) Big cursor
#(-)           Thin cursor
#(+)           Wide cursor
#(X46) Cursor jumps to the 46th column (counts from 1 to 80)
#(Y17) Cursor jumps to the 17th row (counts from 1 to 25)
#(R)   Stores (saves) current cursor position in memory 0
#(S)   Puts cursor to position stored in memory 0
#(T)   Stores (saves) current cursor position in memory 1
#(U)   Puts cursor to position stored in memory 1
#(W)   Shifts cursor one position up but not beyond the screen
#(E)   Shifts cursor one position down but not beyond the screen
#(P)   Shifts cursor one position to the left (but not beyond...)
#(Q)   Shifts cursor one position to the right (but not beyond...)

It is possible to specify several parameters within one command,
e.g. XE :#(FX53Y12R)Hello#(SN)

In the DOS box of Windows NT/2000/XP, the cursor control is limited. Only cursor movements as well as storing and recovering of cursor position work correctly.
Hiding the cursor or setting to display standards (VGA, CGA etc.) do not work with the emulated DOS box of Windows NT/2000/XP.

#=(...) Call upon an entry of a character string

Between the brackets of #=(...) a complete path name of a file must be entered. This function waits for a string entered via the key- board and terminated with <Enter>. The maximum length of the string is 128 characters. The string is then stored in the specified file. The last two characters in the file are CR/LF. If this file is exe- cutable as a batch program, it can be run from a just running batch program using the CALL command.

#{...} Insertion of a text string from a file

Between the brackets of #{...} the complete path name of that file must be inserted, from which the text string is to be taken in order to send it to the screen. From the file, only a maximum of 128 characters are considered. Possibly existing CTRL-Z or CR/LF characters are omitted.

Example: XE :#{C:\TEXTS\SPECIAL\WRITE.TXT}

File names and directory names must meet the DOS specifications. Long file names are not accepted. If the given file is not found, nothing will be sent to the screen (neither an error message).

#={...} Insertion of the contents of a file

Between the brackets of #={...} the complete path name of that file must be inserted, from which the contents is to be taken in order to send it to the screen. If the file contains TABs, these are re- placed by a suitable number of blanks. The file may be of any length.

Example: XE :#={C:\TEXTS\SPECIAL\WRITE.TXT}

File names and directory names must meet the DOS specifications. Long file names are not accepted. If the given file is not found, nothing will be sent to the screen (neither an error message).

#+...+ Wait (delay)

Between the two plus signs of #+...+ a number (1 to 65535) must be inserted. The wait function starts a delay (time base is seconds). If a key is pressed during the delay time, the wait function will be aborted and the errorlevel 100 will be set. Numbers greater than 65535 will cause undefined results.

Example: XE :#+25+

The plus sign at the end of the inserted number must not be forgotten. Otherwise the function will not work correctly.

#I...+ Wait (count-down)

Between the two characters I and + of #I...+ a number (1 to 65535) must be inserted. The wait function starts a delay (time base is seconds) as a visible count-down. If a key is pressed during the delay time, the wait function will be aborted and the errorlevel 100 will be set. Numbers greater than 65535 will cause undefined results.

Example: XE :#I25+

The plus sign at the end of the inserted number must not be forgotten. Otherwise the function will not work correctly.

#-...- Waiting for a given time (of day)

Between the two minus signs of #-...- a time (of day) (00:00 to 23:59) must be inserted. This function starts a delay, which expires at the given time. If a key is pressed during the delay time, the wait function will be aborted and the errorlevel 100 will be set.
Given time stamps, which are invalid, will cause undefined results. Please note, that hours and minutes must be given in two digits each.

Example: XE :#-00:09-
or:      XE :I am waiting until 09:05 #-09:05- #$

In the second example, the time stamp is sent to the screen after the time has elapsed (for checking the correct function). The minus sign at the end of the inserted time must not be forgotten. Otherwise the function will not work correctly.

Working with variables (mainly used with counters and timers)

The XE program works with two variables, which can have sizes of -32767...0...+32767 as signed integers. The two variables are addressed with #!.... (variable 1) and #:.... (variable 2).
The following examples show the possible applications. The numbers can be specified with or without sign, e.g. 200 or +200 (positive number) or -200 (negative number):

#!-200! Variable 1 is set to -200
#!N     Variable 1 is negated (sign - instead of + or vice versa)
#!=     Variable 1 is sent to the screen (with sign plus 5 digits)
#!D     Variable 1 is sent to the screen (only the digits needed)
#!_     Variable 1 is processed as an amount of seconds and displayed
        in the format HH:MM:SS (hours:minutes:seconds)
        (variable 1 must be a positive number here, 0...+32767)
#!6548? Variable 1 is compared to the number +6548. Result:
          Errorlevel 3 if variable 1 is greater than the number
          Errorlevel 2 if variable 1 is equal to the number
          Errorlevel 1 if variable 1 is less than the number
#!34+   Variable 1 is increased by 34
#!72-   Variable 1 is decreased by 72
#!-32*  Variable 1 is multiplied by -32
#!18/   Variable 1 is divided by 18, the result is rounded down
          to a signed integer
#!K     Variable 1 is entered on the keyboard.
          Example: XE :How many copies to print? #!K#!= copies
          After invocation with #!K a number of -32767...0...32767
          has to be entered on the keyboard. Other values cause errors.
          The entry is terminated by the ENTER key. After pressing
          the ENTER key, the cursor moves back to the first position
          of the entered number.
#!L     The internal errorlevel (while XE is running) is copied
          to variable 1.
#!M     An errorlevel (0...255) is created from variable 1.
          If variable 1 exceeds this range, the Lower Byte is used to
          create the errorlevel. Variable 1 is not changed by this action.
#!{...} Variable 1 is loaded from that file, whose name is inserted
          between the brackets {}. Example: XE :...#!{C:\XE\VAR1.VAR}
          The specified file must contain a valid number -32767...+32767.
          Examples for file contents: 5 -67 +00008 -056
          For more information read the file VAR_E.VAR.
#!(...) Variable 1 is copied to that file, whose name is inserted
          between the brackets (). Example: XE :...#!(C:\XE\VAR1.VAR)

#:200:  Variable 2 is set to +200
#:N     Variable 2 is negated (sign - instead of + or vice versa)
#:=     Variable 2 is sent to the screen (with sign plus 5 digits)
#:D     Variable 2 is sent to the screen (only the digits needed)
#:_     Variable 2 is processed as an amount of seconds and displayed
        in the format HH:MM:SS (hours:minutes:seconds)
        (variable 2 must be a positive number here, 0...+32767)
#:-548? Variable 2 is compared to the number -548. Result:
          Errorlevel 3 if variable 2 is greater than the number
          Errorlevel 2 if variable 2 is equal to the number
          Errorlevel 1 if variable 2 is less than the number
#:34+   Variable 2 is increased by 34
#:72-   Variable 2 is decreased by 72
#:50*   Variable 2 is multiplied by 50
#:-18/  Variable 2 is divided by -18, the result is rounded down
          to a signed integer
#:K     Variable 2 is entered on the keyboard.
          For further description see #!K
#:L     The internal errorlevel (while XE is running) is copied
          to variable 2.
#:M     An errorlevel (0...255) is created from variable 2.
          If variable 2 exceeds this range, the Lower Byte is used to
          create the errorlevel. Variable 2 is not changed by this action.
#:{...} Variable 2 is loaded from that file, whose name is inserted
          between the brackets {}. Example: XE :...#:{C:\XE\VAR2.VAR}
          For further description see #!{...}
#:(...) Variable 2 is copied to that file, whose name is inserted
          between the brackets (). Example: XE :...#:(C:\XE\VAR2.VAR)

#!:+  Variable 1 is increased by the value contained in variable 2
#!:-  Variable 1 is decreased by the value contained in variable 2
#!:*  Variable 1 is multiplied by the value contained in variable 2
#!:/  Variable 1 is divided by the value contained in variable 2,
        the result is rounded down to a signed integer
#!:!  Variable 1 is exchanged with variable 2
#!:?  Variable 1 is compared to variable 2. Result:
        Errorlevel 3 if variable 1 is greater than variable 2
        Errorlevel 2 if variable 1 is equal to variable 2
        Errorlevel 1 if variable 1 is less than variable 2
#!:_  Variable 1 copies the value from variable 2,
        variable 2 remains unchanged

#!:\  Variable 1 is divided by the value contained in variable 2.
        Results: variable 1 contains the result of division
                 variable 2 contains the undevided rest (modulo)

#:!+  Variable 2 is increased by the value contained in variable 1
#:!-  Variable 2 is decreased by the value contained in variable 1
#:!*  Variable 2 is multiplied by the value contained in variable 1
#:!/  Variable 2 is divided by the value contained in variable 1,
        the result is rounded down to a signed integer
#:!:  Variable 2 is exchanged with variable 1
#:!?  Variable 2 is compared to variable 1. Result:
        Errorlevel 3 if variable 2 is greater than variable 1
        Errorlevel 2 if variable 2 is equal to variable 1
        Errorlevel 1 if variable 2 is less than variable 1
#:!_  Variable 2 copies the value from variable 1,
        variable 1 remains unchanged

The contents of the variables are lost when the computer is rebooted or in case of warm or cold start. If the DOS box of WIN95/98/ME/NT/2000 is closed, the variables may also be destroyed. If variables are to be stored and reloaded, the functions #!{...} #!(...) #:{...} #:(...) may be used.

The variables use the RAM memory addresses of the so-called Intra Application Communication Area, ICA (40h:00F0h to 40h:00FFh) for their storage. If another program also uses these memory addresses, the variables may fail.
The tests, executed using the variables, were successful on all test computers (different computer types old and new, DOS and DOS boxes).

Remarks:
- All results can only be correct, if the value range does never exceed -32767...0...+32767.
- Division by 0 is not possible. This division does not perform anything.
- The number 0 cannot be negated (-0 and +0 are identical, so they are always displayed as +00000).

Creation of return codes (errorlevels)

Return codes can be produced at any position of the command line. If more than one return code are produced, the last one will be saved and can be evaluated by IF ERRORLEVEL then. Setting a return code: #R00 to #RFF (hex value causes the code of 0...255).

#,.., Special function: checking for a given drive letter

If a valid drive letter is inserted between the two commas, e.g. #,d:, an errorlevel is set, depending on the drive letter. A: causes errorlevel 1, Z: causes errorlevel 26.
If no valid drive letter is inserted between the two commas, error- level 0 is generated. Errorlevel 0 is also output in the following cases:

#,c, the colon is missing
#,C: the second comma is missing
#,c:\ this is a directory, not a drive
#, C:, the blank must not exist
#,C:x, undefined x

In batch files may be a line such as XE :#,%1,
If the first parameter of the command line is D: for example, %1 will be accepted as a valid drive letter.

Program details

The XE program was completely written in assembly language. Upper and lower case letters have the same meaning if used together with # parameters (#3a is identical to #3A). The program may be distributed free of charge (freeware). Never distribute the program without its documentation and the enclosed example batch files.

Used memory addresses of the ICA (40h:00F0h to 40h:00FFh):
----------------------------------------------------------
F0 F1  F2 F3    F4 F5 F6 F7 F8 F9 FA FB  FC FD  FE FF
#(rs)  #(tu)                             #:...  #!...
cursur position ------still unused-----  variables
The XE kernel

The kernel of XE was compiled into a separate program, called 'Send to screeN' (SN.COM). The assembler source code is Public Domain. The code was optimized for program size. It is easy to understand, so there are no comments at all. Compiled with TASM 2.01, Ideal mode.

 
        IDEAL
        MACRO   LOAD_A_BYTE
        LODSB
        CMP     AL,13
        JZ      TOEND
        ENDM
        MACRO   NEW_LINE
        MOV     DX,OFFSET CRLF
        MOV     AH,9
        INT     21H
        ENDM
        SEGMENT COM_SEG PARA PUBLIC USE16 'CODE'
        ASSUME  CS:COM_SEG,DS:COM_SEG,SS:COM_SEG
        ORG     100H
START:  MOV     CX,0404H
        CLD
        MOV     SI,81H
NO_CLN: LOAD_A_BYTE
        CMP     AL,':'
        JNZ     NO_CLN
AGAIN:  LOAD_A_BYTE
        CMP     AL,'#'
        JZ      HEX01
OUTPUT: MOV     AH,2
OUTPUX: MOV     DL,AL
        INT     21H
        JMP     SHORT AGAIN
HEX01:  LOAD_A_BYTE
        CMP     AL,';'
        JZ      TOEND
        CMP     AL,'#'
        JZ      OUTPUT
        CMP     AL,'0'
        JB      AGAIN
        CMP     AL,'9'
        JBE     HEX04
        AND     AL,NOT 20H
        CMP     AL,'A'
        JB      AGAIN
        CMP     AL,'F'
        JBE     HEX03
        CMP     AL,'P'
        JNZ     HEX02
        MOV     CH,'P'
HEX02:  CMP     AL,'V'
        JNZ     AGAIN
        NEW_LINE
        JMP     SHORT AGAIN
HEX03:  SUB     AL,55
HEX04:  SHL     AL,CL
        MOV     BL,AL
        LOAD_A_BYTE
        CMP     AL,'9'
        JA      HEX05
        AND     AL,NOT 30H
        JMP     SHORT HEX06
HEX05:  AND     AL,NOT 20H
        SUB     AL,55
HEX06:  ADD     AL,BL
        CMP     AL,9
        JNZ     OUTPUT
        MOV     AH,6
        JMP     SHORT OUTPUX
TOEND:  CMP     CH,CL
        JNZ     FINISH
        NEW_LINE
FINISH: MOV     AX,4C00H
        INT     21H
CRLF    DB      13,10,36
        ENDS    COM_SEG
        END     START
   

Valid-HTML401  Valid-CSS