home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
sysutl
/
busy1.arc
/
BUSY1.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-11-08
|
9KB
|
414 lines
Comment ~
BUSY symbol display for assembly language programs.
The original idea came from BUSY.C (credits below).
/*
** This program demonstrates several "busy indicators", and also
** serves as a example of using the BIOS clock tick timer at 40:40
** Written in 1989 by Otto Makela, Jyvaskyla, Finland.
** Permission is granted to copy this code freely, though a small
** mention of the source would be appreciated... :-)
*/
However, his demo wasn't really practical .. a REAL busy symbol
should be a "background" process, so your own program can gleefully
go about its business, knowing the user is being entertained at the
console.
Plus .. he used a funny clock. The one at 40:40 is for floppy disk
timeout, and isn't a REAL clock!
We'll make our busy signal a background process by sitting on the user-defined
clock tick interrupt (1CH).
Rather than mess with clocks (since we have a guaranteed 18.2 ticks-per-
second interrupt), we'll just maintain our own internal clocks.
I've arbitrarily decided to blink about every 1/4 of a second.
Since this is only a stubbed demo, we're gonna use the Inter-Application
Communications Area (IAC)
(1) to determine when the "busy" time is over,
and (2) as two internal byte-sized clocks.
Actually, this would probably work ok in a real program .. so long as
you didn't have your own uses for the IAC. We don't REALLY have to
do this .. there are other ways .. just showing off, and demonstrating
how we don't have to worry about code or data segments by putting
variables entirely outside the program's world!
Some notes from an IAC display program I tweaked:
The IAC is 16 bytes beginning at addr 0040:00F0h. Any program can
write information to the IAC for another program to read. Please
note: unless the first program directly invokes the second program,
it cannot protect the IAC from being altered by an intervening program.
The IAC can be used, for instance, to pass an address from one program
to the next.
This demo (as BUSY.C did) shows all sorts of likely (?) busy indicators.
Pick the one you like and discard the code for the rest. (An exercise
for the student.)
David Kirschbaum
Toad Hall
kirsch@arsocomvax.socom.mil
Comment ends ~
CR EQU 0DH
LF EQU 0AH
PAGE0 SEGMENT AT 0
org 46CH ;BIOS clock
clock db ?
org 4F0H
iac db ?
tick db ? ;1st Busy internal clock
tick1 db ? ;2d internal clock
db 13 DUP(?)
PAGE0 ENDS
CSEG SEGMENT PUBLIC PARA 'CODE'
ASSUME CS:CSEG, DS:CSEG, ES:CSEG
org 100H
Busy_Demo PROC NEAR
jmp Start
EVEN ;make it easier for snarfing
s2_1 db '▄▀' ;[i&1]
s2_2 db '▌▐' ;[i&1]
s4_1 db '/|\-' ;[i&3]
s4_2 db ' -÷:' ;[i&3]
s4_3 db '-=≡=' ;[i&3]
s4_4 db 30,16,31,17 ;[i&3]
s4_5 db '▄▐▀▌' ;[i&3]
s8_1 db '║╗═╔║╚═╝' ;[i&7]
s8_2 db ' ░▒▓█▓▒░' ;[i&7]
s8_3 db ' ·∙',9,'O',9,'∙·' ;[i&7]
old_Int1C dd 0 ;save orig Int 1CH clock vector
scr_vec label dword ;screen seg:ofs for writing busy chars
dw 0 ;this'll be posted during installation
dw 0B000H ;default is monochrome screen
cursize dw 0 ;save cursor size
Busy_Demo ENDP
Busy PROC FAR
sti ;ints back on
push ax ;save caller's AX
push DS ; and DS
xor ax,ax
mov DS,ax
ASSUME DS:PAGE0
cmp iac,al ;is busy flag turned on?
jz Not_Busy ;nope, no work to do
cmp tick,al ;internal clock 0?
jz Ticked ;yep, go to work
dec tick ;decrement internal clock
jz Ticked ;0, go to work
Not_Busy:
jmp Old_Clock
Ticked:
mov al,8 ;handy constant
mov tick,al ;refresh tick counter
mov ah,tick1 ;pick up 2d clock
inc ah ;bump 2d clock
cmp ah,al ;< 8? (7 is max)
jb Ticked1 ;not 8 yet
xor ah,ah ;> 7, reinit to 0
Ticked1:
mov tick1,ah ;update 2d clock
push bx ;save regs
push dx
push si
push di
push ES
mov dx,CS
mov DS,dx
ASSUME DS:CSEG
mov dl,ah ;keep 2d clock in DL
cld ;insure forward
xor bh,bh ;clear msb
les di,scr_vec ;screen offset and seg
ASSUME ES:NOTHING
mov ah,7 ;likely attribute
;2 2-char symbols
mov bl,dl ;i
and bl,1 ;mask for 2-char symbols
mov si,offset s2_1 ;from first busy char (1 of 2)
call Stuff_Busy ;snarf, stuff, bump to next scr psn
mov si,offset s2_2 ;from 2d busy char (1 of 2)
call Stuff_Busy
;5 4-char symbols
mov bl,dl ;get i back
and bl,3 ;mask for 4-char symbols
mov si,offset s4_1 ;1st 4-char table
call Stuff_Busy
mov si,offset s4_2 ;2nd 4-char table
call Stuff_Busy
mov si,offset s4_3 ;3rd 4-char table
call Stuff_Busy
mov si,offset s4_4 ;4th 4-char table
call Stuff_Busy
mov si,offset s4_5 ;5th 4-char table
call Stuff_Busy
;3 8-char tables
mov bl,dl ;get i back
and bl,7 ;mask
mov si,offset s8_1 ;1st 8-char table
call Stuff_Busy
mov si,offset s8_2 ;2nd 8-char table
call Stuff_Busy
mov si,offset s8_3 ;3rd 8-char table
mov al,[si][bx] ;snarf char
stosw
pop ES ;restore caller's regs
pop di
pop si
pop dx
pop bx
Old_Clock:
pop DS
pop ax
jmp CS:old_Int1C ;on to old Int 1CH, IRET from there
Busy ENDP
;Common subroutine for Busy
Stuff_Busy PROC NEAR
mov al,[si][bx] ;snarf char
stosw
inc di ;bump a space over
inc di
ret
Stuff_Busy ENDP
;Necessary setup routines for "background" busy routine.
;Just call once.
Busy_Setup PROC NEAR
ASSUME DS:CSEG
mov ax,351CH ;get Int 1CH clock tick vector
int 21H
mov word ptr old_Int1C,bx ;save offset
mov word ptr old_Int1C+2,ES ;and segment
mov dx,DS ;save DS a sec
xor ax,ax
mov DS,ax
ASSUME DS:PAGE0
mov iac,al ;0 ;insure IAC busy flag is off
mov DS,dx ;restore DS
ASSUME DS:CSEG
mov dx,offset Busy ;new Int 1CH clock procedure
mov ax,251CH ;set new Int 1CH vector
int 21H
ret
Busy_Setup ENDP
;Signals Busy via IAC to show busy symbols
Busy_On PROC NEAR
mov dx,DS ;save DS
xor ax,ax
mov DS,ax
ASSUME DS:PAGE0
mov word ptr tick,ax ;init 2 internal clocks
not al ;0FFH
mov iac,al ;Turn busy flag on
mov DS,dx ;restore DS
ASSUME DS:CSEG
mov ah,0FH ;get current video mode
int 10H ;via BIOS
;AL=current video mode
;AH=nr chars per line
;BH=display page
;We're only handling Mono or CGA for now
;Anything will probably go out to lunch!
cmp al,7 ;assume mono (default)
jz Is_Mono ;yep
mov byte ptr scr_vec+3,0B8H ;nope, CGA, make seg 0B800H
Is_Mono:
push ax ;save chars per line in AH
mov ah,3 ;get current cursor psn
int 10H
;DH=row, DL=col
;CX=current cursor size
mov cursize,cx ;save cursor size
or ch,20H ;make cursor disappear
mov ah,1 ;set cursor size
int 10H ;via BIOS
mov al,dh ;current row
xor ah,ah ;clear msb
pop cx ;CH=chars per line
mul ch ;row*(chars per row)
xor dh,dh ;clear msb, DX = curr col
add ax,dx ;row offset + col offset
; = screen offset
shl ax,1 ;*2 for words
mov word ptr scr_vec,ax ;save screen offset
ret
Busy_On ENDP
;Signals Busy via IAC to not show busy symbols
Busy_Off PROC NEAR
mov dx,DS ;save DS
xor ax,ax
mov DS,ax
ASSUME DS:PAGE0
mov iac,al ;0 ;Turn busy flag off
mov DS,dx ;restore DS
ASSUME DS:CSEG
Cursor_On:
mov ah,1 ;set cursor size
mov cx,cursize ;back to old size
int 10H ;via BIOS
ret
Busy_Off ENDP
;Call once when you're done with Busy.
;This will uninstall the stolen Int 1CH vector
Busy_Uninstall PROC NEAR
ASSUME DS:CSEG
mov bx,DS ;save
xor ax,ax
mov DS,ax
ASSUME DS:PAGE0
cli ;be sure clock tick doesn't get us
mov iac,al ;0 ;turn busy flag off
sti ;ints back on
lds dx,CS:old_Int1C ;DS:DX = old Int 1CH vector
mov ax,251CH ;restore Int 1CH vector
int 21H
mov DS,bx ;restore DS
jmp Cursor_On ;turn cursor back on, return
Busy_Uninstall ENDP
;********* Your program would go here.
msg1 db 'Faking busy.',CR,LF
db 'Press any key to be "non-busy": $'
msg2 db CR,LF,'Faking busy again.',CR,LF
db 'Press any key to be "non-busy": $'
Start PROC NEAR
call Busy_Setup ;Some necessary Busy setups
;Just call once
mov dx,offset msg1 ;'First busy test'
mov ah,9 ;display msg
int 21H
call Busy_On ;signal Busy, cursor off
Busy_Tst1:
mov ah,1 ;check kbd status
int 16H ;via BIOS
jz Busy_Tst1 ;no key
call Busy_Off ;signal Busy, cursor on
xor ah,ah ;read that key
int 16H ;via BIOS
mov dx,offset msg2 ;'Second busy test'
mov ah,9 ;display msg
int 21H
call Busy_On ;signal Busy, cursor off
Busy_Tst2:
mov ah,1 ;check kbd status
int 16H ;via BIOS
jz Busy_Tst2 ;no key
call Busy_Uninstall ;done, turn off Busy,
;cursor on,
;restore stolen vector
xor ah,ah ;read that key
int 16H ;via BIOS
mov ax,4C00H ;terminate
int 21H
Start ENDP
CSEG ENDS
END Busy_Demo