home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
emit
/
emit.a86
next >
Wrap
Text File
|
1994-06-17
|
9KB
|
296 lines
;EMIT.A - Unix-style utility to output control characters
;Author: John Lene-Comeau, Industrial Control Technology, jcomeau@world.std.com
;Specialists in utilities and device drivers under RSX, VMS, and MS-DOS.
;PO Box 100632, Ft. Lauderdale, FL 33310-0632 * (305)966-0162
;
;Uncopyrighted (U) 1994 John Lene Comeau. Public Domain software.
;
;To use: emit 0x1b "[7mThis is a test",27,"[m" ;comment
; note that whitespace or commas can be separators
; text may be in single or double quotes
; numbers beginning with 0x are hexadecimal, with 0 are octal, otherwise decimal
; comment may follow, preceded by semicolon
; default output to screen may be overridden by using redirection
;
dos equ 21h
;set up for stack variables
_byte equ -1
_word equ -2
_dword equ -4
;
stackv macro ;set up variables on stack, index to using BP
##if !stktop
stktop = 0
##endif
#1 equ stktop + #2
stktop = #1
#em
;
newstate macro ;set new processing state
mov cx,offset #1 ;move memory to memory using CX
mov state[bp],cx
#em
;
error macro ;output message to STDERR and exit with specified errorlevel
##if #s2 ;if there's a string supplied
mov cx,#s2-2 ;number of bytes in message
##else
xor cx,cx ;else don't print anything
##endif
mov bx,2 ;STDERR
mov dx,offset >m1
mov ah,40h ;dos WRITE function
int dos ;do it
mov ax,4c00h+#1 ;set errorlevel
int dos ;and exit
m1: db #2
#em
;
;the variables themselves...
;
stackv state,_word
stackv delimiter,_word
;
mov bp,sp ;get current stack pointer
add sp,stktop ;initialize variable space on stack
newstate start ;initialize state
mov bx,80h ;point to input character count
mov dl,[bx] ;get count byte
add bl,dl ;point to end...
inc bx ;now it does
mov byte ptr [bx],0 ;zero-terminate it
mov si,81h ;point DS:SI to arg string
emitloop:
lodsb ;get next byte
jmp state[bp] ;jump to routine corresponding to state
;
start:
mov bx,offset >s1 ;load table
call bounds ;get appropriate subroutine
jmp >s2[bx] ;and jump to it
s1: db 1,0,1,';',2,' ',0
s2: dw >s3,>s4,>s5,>s6
s3: error 1,'Usage: emit nn [nn...] ;nn is value of ASCII character'
s4: error 0 ;exit normally
s5: newstate waiting ;else now waiting for an arg
jmp emitloop ;so go back and find one
s6: error 2,'EMIT -- Error - Invalid character found'
;
waiting:
mov bx,offset >s1 ;load table
call bounds ;get appropriate subroutine
jmp >s2[bx] ;and jump to it
s1: db 1,0,1,';',1,"'",1,'"',2,' ',1,',',8,'0'-1,1,'0',2,'9',0
s2: dw >s3,>s3,>s4,>s4,emitloop,emitloop,>s5,>s6,>s7,>s5
s3: error 0 ;normal exit on null or comment
s4: newstate string ;switch to string storage state
mov delimiter[bp],al ;store delimiter
jmp emitloop ;loop around
s5: error 3,'EMIT -- Error - expecting string or number'
s6: newstate number ;start of hex or octal number
xor dx,dx ;clear result register
jmp emitloop ;loop back for more
s7: newstate decimal ;start of decimal number
xor dx,dx ;clear result register
jmp decimal ;go straight to it with this digit
;
string:
or al,al ;end of command line?
je >s1 ;error if so
cmp al,delimiter[bp] ;otherwise, same as starting delimiter?
je >s2 ;end of string mode if so
mov dl,al ;else send char
mov ah,2 ;DOS function
int dos ;do it
jmp emitloop
s1: error 4,'EMIT -- Error - Unexpected termination within string'
s2: newstate waiting ;done with string processing
jmp emitloop ;back for more input
;
number:
mov bx,offset >s1 ;load table
call bounds ;get subroutine offset
jmp >s2[bx] ;jump to it
s1: db 1,0,2,' ',1,',',1,';',1,'X',1,'x',8,'0'-1,2,'7',0
s2: dw >s3,>s4,>s4,>s3,>s5,>s5,>s6,>s7,>s6
s3: call numout ;output number as is (must be zero)
error 0 ;and exit
s4: call numout ;output the null
jmp emitloop ;loop back for more
s5: newstate hexadecimal ;switch to HEX processing state
jmp emitloop ;go get the rest
s6: error 5,'EMIT -- Error - Invalid octal digit found'
s7: newstate octal ;switch to OCTAL processing state
jmp octal ;and go straight to it from here
;
decimal:
mov bx,offset >s1 ;load table
call bounds ;get subroutine offset
jmp >s2[bx] ;jump to it
s1: db 1,0,2,' ',1,',',1,';',8,'0'-1,2,'9',0
s2: dw >s3,>s4,>s4,>s3,>s5,>s6,>s5
s3: call numout ;output what we have so far
error 0 ;exit
s4: call numout ;output what we have
newstate waiting ;back to fishing mode
jmp emitloop ;go get rest of command line
s5: error 6,'EMIT -- Error - Invalid decimal digit found'
s6: aam 10h ;split so AL contains decimal digit
xchg ax,dx ;switch with result register
mov cl,10
mul cl ;shift current result one decimal place over
add al,dl ;and merge in current digit
xchg ax,dx ;switch back
jmp emitloop ;go back for more
;
hexadecimal:
mov bx,offset >s1 ;load table
call bounds ;get subroutine offset
jmp >s2[bx] ;jump to it
s1: db 1,0,2,' ',1,',',1,';',8,'0'-1,2,'9',8,'A'-1,2,'F'
db 8,'a'-1,2,'f',0
s2: dw >s3,>s4,>s4,>s3,>s5,>s6,>s5,>s7,>s5,>s7,>s5
s3: call numout ;output what we have so far
error 0 ;exit
s4: call numout ;output what we have
newstate waiting ;no longer in HEX mode
jmp emitloop ;go get rest of command line
s5: error 7,'EMIT -- Error - Invalid hexadecimal digit found'
s6: aam 10h ;split so AL contains decimal digit
mov cl,4 ;8088 won't accept SHL DX,4
shl dx,cl ;shift current result one nybble over
add dl,al ;and merge in current digit
jmp emitloop ;go back for more
s7: aam 10h ;split so AL contains 1 thru 6
add al,9 ;now make it 0xa-0xf
mov cl,4 ;in case running on 8086/88
shl dx,cl ;shift current result one nybble over
add dl,al ;and merge in current digit
jmp emitloop ;go back for more
octal:
mov bx,offset >s1 ;load table
call bounds ;get subroutine offset
jmp >s2[bx] ;jump to it
s1: db 1,0,2,' ',1,',',1,';',8,'0'-1,2,'7',0
s2: dw >s3,>s4,>s4,>s3,>s5,>s6,>s5
s3: call numout ;output what we have so far
error 0 ;exit
s4: call numout ;output what we have
newstate waiting
jmp emitloop ;go get rest of command line
s5: error 8,'EMIT -- Error - Invalid octal digit found'
s6: aam 10h ;split so AL contains octal digit
mov cl,3 ;in case running on 8088
shl dx,cl ;shift current result one octal place over
add dl,al ;and merge in current digit
jmp emitloop ;go back for more
;
numout:
mov ah,2 ;DOS function for character output
int dos ;do it (send DL)
ret ;and return
;
bounds:
;This routine is passed a character in AL and a table address in
;BX. The table consists of word entries, each with the low byte
;containing an action code and the high byte a character code. The
;action codes are:
; 0 - end of table
; 1 - char is legal
; 2 - chars less than or equal to this is legal
; 3 - chars greater than this are legal
; 4 - char is ignored
; 5 - chars <= are ignored
; 6 - chars > are ignored
; 7 - char is illegal
; 8 - chars <= are illegal
; 9 - chars > are illegal
;returns S set if char is illegal
;Z set if char is legal
;C set if passed bad parameters (program error) or reached end of table
;no flags if char is to be ignored
;doesn't change AX, but BX is returned as word offset to entry where
;match occurred. All other regs are saved.
push dx ;save aux register
push ax ;save character
push bx ;save start of table
mov ah,10 ;highest legal action code is 9
jmp b2 ;skip cleanup routine on first entry
b1: xchg bx,dx ;swap regs back where they belong
inc bx ;and point to next word entry
b2: cmp [bx],ah ;past highest legal action code?
jnc b96 ;if so, quit
mov dl,[bx] ;else get the action code
xor dh,dh ;make word pointer
shl dx,1
inc bx ;point to character code
cmp al,[bx] ;compare current character to it
xchg bx,dx ;must be in BX to use indirectly
jmp b4[bx] ;jump to appropriate action routine
b4: dw b96 ;end of table is error, shouldn't happen
dw b10
dw b20
dw b30
dw b40
dw b50
dw b60
dw b70
dw b80
dw b90
b10: je b97 ;char is legal, finish up
jmp b1 ;else loop back and try again
b20: jbe b97
jmp b1
b30: ja b97
jmp b1
b40: je b95
jmp b1
b50: jbe b95
jmp b1
b60: ja b95
jmp b1
b70: je b98
jmp b1
b80: jbe b98
jmp b1
b90: ja b98
jmp b1
b95: xchg bx,dx ;get final address
dec bx ;make word
pop dx ;now get start of table
sub bx,dx ;and make offset
mov al,1 ;reset all the flags
or al,al ;like this
pop ax ;now restore the registers
pop dx
ret
b96: xchg bx,dx ;same except for carry flag set before RET
dec bx
pop dx
sub bx,dx
stc ;error indicator set here
pop ax
pop dx
ret
b97: xchg bx,dx
dec bx
pop dx
sub bx,dx
xor al,al ;set Z flag
pop ax
pop dx
ret
b98: xchg bx,dx
dec bx
pop dx
sub bx,dx
or al,80h ;set S flag
pop ax
pop dx
ret