home *** CD-ROM | disk | FTP | other *** search
- 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