; ;---------------------------------------- ; DOSMON - DOS Activity Monitor ;---------------------------------------- ; ; This program will terminate and stay resident. It intercepts the ; DOS service interrupt and displays status information on the ; screen during DOS service execution periods. ; ; S.H.Smith, 15-may-86 ; converted to real assembly, sped up, and made smaller by ; jack velte 1301 441-2008 velte@mimsy.umd.edu ; RESLEN equ init - dosmon + 256 code segment byte public 'text' assume cs:code, ds:code org 100h ;---------------------------------------- ; startup entry point ;---------------------------------------- dosmon proc near jmp short init ;install dosmon endp ; segment address for display memory ; filled in by startup code display_seg dw ? twiddle_idx dw ? ; twiddle display index twiddle_char db 'Ä\³/' ; twiddle display characters ;---------------------------------------- ; new DOS service interrupt ;---------------------------------------- ; new21 proc far push ds push es push bx ; save entry registers push ax mov ax, cs:display_seg ; get display segment into es mov es, ax ; ;---------------------------------------- ; prepare display with blanks ; mov ax, 0f20h ;space with attribute of 15 mov es:[94h], ax mov es:[96h], ax ;set attribute of the function code locations mov es:[98h], ax ; ;---------------------------------------- ; display the rotating twiddle character ; mov bx, cs:twiddle_idx ;get twiddle index inc bx mov al, bl ;advance to next twiddle position and al, 3 ;bx=bx mod 4 to rotate through twiddles mov bl, al mov cs:twiddle_idx, bx ;save next twiddle index mov ah, cs:[twiddle_char + bx] ;get the next twiddle character mov es:[94h], ah ;put twiddle status on screen ; ;---------------------------------------- ; display the DOS service number in hex ; pop bx mov ax, bx ;get the dos function code into ah and ah, 0fh add ah, 30h ;convert low digit to hex cmp ah, 3ah ;handle A..F jb foo add ah, 7 foo: mov es:[98h], ah ;and set LSB on screen mov ax, bx ;get fresh copy of function code into ah shr ah, 1 ;move down bits for high digit shr ah, 1 shr ah, 1 shr ah, 1 ;make high byte hex and put on screen and ah, 0fh add ah, 30h cmp ah, 3ah ;handle A..F jb bar add ah, 7 bar: mov es:[96h], ah ;set MSB on screen ;---------------------------------------- ; perform the DOS service function ; mov ax, bx ; we've been saving it here. pop bx pop es ;restore initial entry registers pop ds ; db 0eah ; pass to original int21 code int21ofs dw ? ; *** self-modifying code: int21seg dw ? ; *** JMP FAR PTR xxxx:yyyy new21 endp ;---------------------------------------- ; startup code ;---------------------------------------- ; determine where the video ram is. this is done by putting a special ; character on the screen and then looking for it in the various video ; ram locations. ; init proc near push cs pop ds ; get cs in ds mov ah, 3 ;get cursor position int 10h ;video bios service push ax push bx push dx ;save it for later mov dx, 0 mov ah, 2 ;home the cursor int 10h mov ah, 0Ah mov al, 88h ;display a funny char at cursor mov cx, 1 int 10h ; ; move cursor back to original position ; pop dx pop bx pop ax mov ah, 2 int 10h ; ; look for MONO video ram ; mov dl, 88h mov ax, 0b000h mov es,ax cmp dl, es:[0] jz foundvideo ; ; look for COLOR video ram ; mov ax, 0b800h mov es, ax cmp dl, es:[0] jz foundvideo ; ; couldn't find video ram; display a message and abort ; lea dx, errormsg mov ah,9 int 21h ;display error message mov ah, 4ch ; terminate with error code mov al, 1 int 21h errormsg: db "ERROR: Can't find display memory$" foundvideo: mov cs:display_seg, ax ;set the display segment ; ;---------------------------------------- ; display the program signon message now that we are sure ; that we can be installed ; lea dx, signon_msg mov ah, 9 int 21h ;display signon message mov es, ds:[002Ch] mov ah, 49h ; free up our copy of the environment int 21h ;---------------------------------------- ; now install new interrupt handler ; mov ax,0 mov es,ax ; ; save old DOS service vector ; mov ax, 3521h int 21h mov int21ofs, bx ; save old int21 mov int21seg, es ; mov ax, 2521h ; install new vector lea dx, new21 ; ptr to our routine int 21h ; ; set last resident code offset ; and terminate-and-stay-resident ; mov dx, RESLEN ; size of our interrupt handler test dl,0Fh ; see if it's on a paragraph boundary sahf mov cl, 4 shr dx, cl ; convert bytes to paragraphs lahf ; paragraph aligned? jz gotsr ; yes, we're done inc dx ; round to next paragraph gotsr: mov ax, 3100h ; terminate and stay resident int 21h init endp ; a signature in bytes signon_msg: db 0ah, 0dh, "DOSMON - DOS Activity Monitor", 0ah, 0dh db "S.H.Smith, 15-May-86", 0ah, 0dh db "jack velte, may 89", 0ah, 0dh, "$" code ends end dosmon