page 77,132 CSeg Segment Para Public 'CODE' Assume CS:CSeg,DS:CSeg,ES:CSeg ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ NoScroll.Asm v.1.3 ³ ;³ ³ ;³ A program to restrict the scrolling of output to the screen. ³ ;³ ³ ;³ by R. P. Byrne - 5/22/90 ³ ;³ ³ ;³ Syntax: NoScroll [n] ³ ;³ ³ ;³ where n represents the first row on the screen that will be allowed to ³ ;³ scroll (if not specified, defaults to line 4) ³ ;³ ³ ;³ First call installs this utility, second call de-installs it ³ ;³ ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ;============ *** PSP DATA LABELS *** ========================================== org 80h ;INTERESTING PSP STUFF STARTS HERE Parm_Length db ? ;LENGTH OF CMD LINE PARAMETERS Parameters label byte ;THE COMMAND PARAMETERS ARE HERE ;=============================================================================== org 100h Entry_Point: jmp EntryPt ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Data Storage Area ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ MaxRow equ 24 FirstRow db 3 ;(first scrollable row on screen) - 1 ProgramID db 'NoScroll v1.3 by R. P. Byrne 5/22/90','$' PgmIDLen equ $-ProgramID OldInt10 dd ? ;the "real" bios video isr OldInt21 dd ? ;the "real" dos function call isr DummyReturn dw ? ;just a dummy variable used for stack adjustment ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Commonly called subroutines ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ UseOldInt10 Proc Near push bp ;save bp just in case machine has old bios bug pushf ;push flags to simulate an int instruction call dword ptr cs:OldInt10 ;call bios video service pop bp ;restore base pointer ret ;return to caller UseOldInt10 EndP ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Interrupt service routine (ISR) for Bios Video interrupt ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Entry10 Proc far assume ds:nothing, es:nothing, ss:nothing sti Chk0E: cmp ah,0Eh ;TTY write request? jnz Chk06 ;no, go check for scroll request cmp al,0Ah ;yes. is character a linefeed? jnz AllOther ;nope ... no special treatment call ChkTTY ;yup ... go take care of it jmp short AllDone Chk06: cmp ah,06h ;scroll page request? jnz Chk02 ;no, go check for cursor move request call ChkScroll ;yes, go take care of it jmp short AllDone Chk02: cmp ah,02h ;set pos request? jnz AllOther ;no ... no special treatment cmp dh,FirstRow ;request outside of window? jae AllOther ;nope ... call ChkCursor ;yup ... go fix it jmp short AllDone AllOther: call UseOldInt10 ;call the "real" int 10h for service AllDone: IRet ;Return to requestor of video service Entry10 EndP ;ÄÄÄÄÄÄ[ Int 10h, function 0Eh - TTY write request ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkTTY Proc near push ax push bx push cx push dx push si push di push ds push es push bp push ax ;save ax mov bh,0 ;video page 0 mov ah,03h ;call Bios to get the current call UseOldInt10 ; cursor position into DX pop ax ;restore ax ChkNewRow: inc dh ;adjust row number for LF cmp dh,MaxRow ;outside the window? ja ScrollIt ;yes ... scroll the window call UseOldInt10 ;no, let "real" bios handle it jmp TTY_GoBack ScrollIt: mov ah,06h ;video scroll up function mov al,1 ;only scroll 1 line mov ch,FirstRow ; xor cl,cl ;upper left corner = FirstRow,0 mov dh,MaxRow ; mov dl,4Fh ;lower right corner = MaxRow,79 mov bh,07h ;use white on black attribute call UseOldInt10 ;Call Int 10h MovCursor: mov bh,0 ;video page 0 mov ah,2 ;set cursor function mov dh,MaxRow ;1st col of last row mov dl,0 ; ie. MaxRow,0 call UseOldInt10 ;move the cursor TTY_GoBack: pop bp pop es pop ds pop di pop si pop dx pop cx pop bx pop ax ret ChkTTY EndP ;ÄÄÄÄÄÄ[ Int 10h, function 6 - scroll page up request ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkScroll Proc near cmp ch,FirstRow ;row of UL corner <= max? jae ULisOK ;yes, go check LR corner mov ch,FirstRow ;no, adjust it ULisOK: cmp dh,MaxRow ;row of LR corner <= max? jbe LRisOK ;yes, no adjustment needed mov dh,MaxRow ;no, adjust it LRisOK: call UseOldInt10 ;let old ISR do the scroll ret ChkScroll EndP ;ÄÄÄÄÄÄ[ Int 10h, function 2 - set cursor position request ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkCursor Proc near mov dh,FirstRow ;fix the 1st row to be scrolled CursorOk: call UseOldInt10 ;Let "real" bios move cursor ret ChkCursor EndP ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Interrupt service routine (ISR) for Dos function request interrupt ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Entry21 Proc far assume ds:nothing, es:nothing, ss:nothing sti Chk09D: cmp ah,9 jnz Chk02D call ChkString jmp short AlldoneD Chk02D: cmp ah,2 ;console output request? jnz Chk40D ;no, go check for file/device write cmp dl,0Ah ;yes. is character a linefeed? jnz AllOtherD ;nope ... no special treatment call ChkConOut ;yup ... go take care of it jmp short AllDoneD Chk40D: cmp ah,40h ;device output request? jnz AllOtherD ;no ... no special treatment cmp bx,1 ;standard output device? jne ChkStdErr ;no, see if std err jcxz AllOtherD ;if char count 0, no special treatment push ax push dx mov ax,4400h ;test stdout via IOCTL call int 21h test dl,80h ;stdout redirected to file? pop dx pop ax jz ChkStdErr ;yes, let DOS handle this one call ChkWrite ;no, go watch for linefeeds ... jmp short AllDoneD ; and then exit ChkStderr: cmp bx,2 ;standard error device? jne AllOtherD ;no, no special treatment call Chkwrite ;yup ... go handle the request jmp short AllDoneD AllOtherD: jmp dword ptr cs:OldInt21 ;jump into dos AllDoneD: Retf 2 ;Return to requestor of service Entry21 EndP ;ÄÄÄÄÄÄ[ Int 21h, function 09h - write string to console ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkString Proc near ; ; Calling program has requested a write to either the standard output device or ; the standard error device ; push bx ;preserve all registers that don't push cx ; return status information push dx ; for the call push si ; push di ; CF acts as an error flag push ds ; AX returns number of bytes written push es ; push bp ; mov si,dx ;ds:si --> string to display OneChar: lodsb ;get a byte to display cmp al,'$' ;end of string? jz NoMore ;yes...time to quit mov dl,al ;load dl for dos call mov ah,02h ;dos console output function int 21h ;display one character jmp short OneChar ;repeat for all characters in buffer NoMore: pop bp pop es pop ds pop di pop si pop dx pop cx pop bx clc ;clear CF for return ret ChkString EndP ;ÄÄÄÄÄÄ[ Int 21h, function 40h - write to file/device ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkWrite Proc near ; ; Calling program has requested a write to either the standard output device or ; the standard error device ; push bx ;preserve all registers that don't push cx ; return status information push dx ; for the call push si ; push di ; CF acts as an error flag push ds ; AX returns number of bytes written push es ; push bp ; mov si,dx ;ds:si --> string to display DisplayOne: lodsb ;get a byte to display mov dl,al ; mov ah,02h ;dos console output function int 21h ;display one character loop DisplayOne ;repeat for all characters in buffer pop bp pop es pop ds pop di pop si pop dx pop cx pop bx clc ;clear CF for return mov ax,cx ;set byte count for return ret ChkWrite EndP ;ÄÄÄÄÄÄ[ Int 21h, function 02h - write to console ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ChkConOut Proc near ; calling program has requested a linefeed be sent to either ; the standard output or standard error device. Use int 10h ; to satisfy the request while checking for scroll out of ; window push ax push bx push cx push dx push si push di push ds push es push bp mov ax,0E0Ah int 10h pop bp pop es pop ds pop di pop si pop dx pop cx pop bx pop ax clc ;clear carry for return ret ChkConOut EndP ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Program installation section ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ EntryPt: assume cs:CSeg, ds:CSeg, es:CSeg, ss:CSeg mov ah,35h ;function 35h retrieves interrupt vector mov al,10h ;we're interested in interrupt 10h int 21h ;get int 10 vector into es:bx mov di,offset ProgramID ;es:di --> program id area of mov si,di ; current int 10h isr, ds:si --> mov cx,PgmIDLen ; pgm id area of this pgm. repe cmpsb ;check for matching pgm id's je Uninstall ;program ID string found in int 10 ISR jmp FirstTime ;go install this program Uninstall: ;on entry, es contains seg. of isr to be removed (put there ;by call to dos function 35h) push ds ;save our data seg for final message lds dx,es:OldInt10 ;load addr of original isr into ds:dx mov ah,25h ;set interrupt vector mov al,10h ;reset int 10h isr back to where it was ... int 21h ; before user installed NoScroll ; lds dx,es:OldInt21 ;load addr of original isr into ds:dx mov ah,25h ;set interrupt vector mov al,21h ;reset int 21h isr back to where it was ... int 21h ; before user installed NoScroll ; push es ;save seg of isr mov ax,es ;transfer isr's code segment addr ... mov ds,ax ; to the data seg reg mov si,2Ch ;ds:si --> segment addr of isr's environment lodsw ;get env seg of tsr process ... mov es,ax ; load into es for dos call ... mov ah,49h ; and deallocate it int 21h ; pop es ;restore code seg of isr ... mov ah,49h ; and deallocate it int 21h ; pop ds ;restore our data segment register mov ah,9 mov dx,offset ProgramId int 21h ;start explaining mov ah,9 mov dx,offset RemovMsg int 21h ;explain int 20h ;we're done ... exit to dos FirstTime: assume es:nothing xor ch,ch mov cl,Parm_Length ;length of command line parameters mov si,offset Parameters jcxz Defaults ;if no parameters, then use default maxrow Strip_L: lodsb cmp al,' ' ;skip all leading spaces ... jz IgnoreCh cmp al,09 ; ... and tab characters jz IgnoreCh jmp short GetParm IgnoreCh: dec cx jmp short Strip_L GetParm: jcxz Defaults ;nothing there but white space dec si ;ds:si ---> 1st non-blank char in cmd line ; cx = length of command line call Ascii_To_Bin ;should return a valid binary number in bx jnc ChkRange ;CF --> non-numeric data jmp Syntax ; Show Syntax msg and exit w/out install ChkRange: cmp bx,25 ;check row num. for valid range ja BadRow ;if invalid, show error msg and exit w/out install cmp bx,1 jb BadRow dec bx ;Ok, valid rownum entered ... adjust to zero mov FirstRow,bl ; relative coordinate and store for use Defaults: mov ah,35h ;Get vector mov al,10h ; for int 10h int 21h mov word ptr [OldInt10],bx ;and store in memory for later mov word ptr [OldInt10+2],es ;store in OldInt10 mov ah,25h ;set new vector for ... mov al,10h ; int 10h to use the routine at Entry10 mov dx,offset Entry10 ;ds:dx ---> new int 10 isr int 21h mov ah,35h ;Get vector mov al,21h ; for int 21h int 21h mov word ptr [OldInt21],bx ;and store in memory for later mov word ptr [OldInt21+2],es ;store in OldInt10 mov ah,25h ;set new vector for ... mov al,21h ; int 21h to use the routine at Entry10 mov dx,offset Entry21 ;ds:dx ---> new int 21 isr int 21h ShowMsg: mov ah,9 mov dx,offset ProgramId int 21h ;start explaining mov ah,9 mov dx,offset InstMsg ;explain int 21h mov dx,offset EntryPt ;last resident byte int 27h ;go memory resident BadRow: mov dx,offset ProgramId mov ah,9 int 21h mov dx,offset BadRowMsg mov ah,9 int 21h int 20h Syntax: mov dx,offset ProgramId mov ah,9 int 21h mov dx,offset SyntaxMsg mov ah,9 int 21h int 20h ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Proc to convert ascii to binary for command line parsing ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Ascii_To_Bin Proc near ; ; This procedure will convert a string of numbers in ASCII form to a ; binary number. Upon entry, SI points at the string and CX contains ; the length of that string. ; The resulting binary number is returned to the calling procedure via ; the BX register. ; Validation of the string is performed by this procedure. If an error ; is encountered (eg. an ASCII code representing a non-numeric character), ; the procedure will exit with the carry flag set. It is the ; responsibility of the calling procedure to issue error messages to ; the user. ; Strings are converted as follows: ; As each character in the string is fetched, it is converted to a ; binary number. The partial sum (kept in BX) is multiplied by 10. ; the fetched and converted digit is added to the partial sum. ; PUSH AX PUSH CX PUSH SI CMP CX,0 ;BE SURE THERE IS DATA TO PROCESS JE A2B_ERROR ;IF NO DATA, EXIT WITH ERROR XOR BX,BX ;INITIALIZE BX REGISTER TO ZERO A2B_LOOP: XOR AX,AX ;INIT AX TO ZERO LODSB ;GET 1 CHARACTER FROM THE STRING CMP AL,30H ;LOWER LIMIT FOR NUM. CHAR. JB A2B_ERROR CMP AL,39H ;UPPER LIMIT FOR NUM. CHAR. JA A2B_ERROR SUB AL,30H ;CONVERT 1 DIGIT TO BINARY XCHG AX,BX ;SWITCH REGISTERS PUSH CX ;SAVE CHARS REMAINING MOV CX,10 ;PARTIAL SUM MULTIPLIER MUL CX ;MULTIPLY PARTIAL SUM BY 10 POP CX ;RESTORE CHARS REMAINING JC A2B_ERROR ;CHECK FOR CARRY OUT OF AX ADD BX,AX ;ADD PARTIAL SUM TO THE LAST DIGIT JC A2B_ERROR ;CHECK FOR CARRY OUT OF BX LOOP A2B_LOOP ;LOOP FOR ALL CHARS IN STRING A2B_END: CLC ;CLEAR CARRY FLAG --> NO ERRORS JMP A2B_EXIT ;AND EXIT A2B_ERROR: STC ;SET CARRY FLAG --> ERROR FOUND A2B_EXIT: POP SI POP CX POP AX RET ASCII_TO_BIN ENDP ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ Additional, non-resident storage ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ InstMsg db ' installed.',0Dh,0Ah,0Dh,0Ah,'$' RemovMsg db ' removed.',0Dh,0Ah,0Dh,0Ah,'$' BadRowMsg db 0Dh,0Ah db 'Row number out of range! Min=1, Max=25.' db 0Dh,0Ah,'$' SyntaxMsg db 0Dh,0Ah db 'Usage: NoScroll [rownum]',0Dh,0Ah,0Dh,0Ah db 'Where rownum specifies the number of the first rown on the screen that will',0Dh,0Ah db 'be allowed to scroll.' db 0Dh,0Ah db ' 1 <= rownum <= 25' db 0Dh,0Ah db ' If rownum is not specified, it will default to 4.' db 0Dh,0Ah,'$' ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ;³ That's all folks! ³ ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CSeg EndS end Entry_Point