![]() |
HW15 TSR HelpOverviewYou are writing a TSR. Normally, when a program finishes executing, the OS reclaims ("cleans up") the memory it was using. With a TSR, when you quit the program, you leave part (or all) of the code in memory, usually so it can listen for certain events. You are also changing the vector table. The vector table is basically an index of pointers to software functions that handle certain events. So, for example, every time the clock timer ticks, it looks up 1Ch in the vector table to find a segment:offset address. The computer goes to that address in memory and runs whatever code it finds there each time the timer ticks. You are going to change the 09h vector to point to the TSR code you left in memory. Everytime there is a keypress, the computer will look up 09h in the vector table, go the address it finds there, and execute that code--which will be your resident TSR code. In that resident TSR code, you will check to see if it was a function key was pressed and respond accordingly. To find out more about TSRs, you can have a look in your book--Section 15.4, I think. Some of the features you need are documented in the Notes ("Additional Assembler instructions involved" -- addtn Assembler.doc) and HW ("Hmw" -- hotkey.doc) files on Pager's site. (Bold words are how I refer to these files below.) The CodeYour code will have two parts/sections--the Setup code and the Resident code. You can follow the book's example and make these two PROCs, or you can follow the greet.asm example and just use labels for the two sections. You will also have to calculate how many paragraphs (16 byte chunks) of code to leave resident. If you want to get fancy, like the book, you can leave only the necessary code (the Resident section) in memory. Or you can follow greet.asm's example and leave all the code in memory (Resident and Setup). Part 1: The Setup codeFirst, you need to save the original 09h vector. You need this later so you can call it from your Resident code. [See HW for how to setup the variables to store the saved segment and offset and later make the call. See Notes for int 21h, fn. 35h]. Then, you need to replace the 09h vector with the segment and offset of your Resident code/function. [See greet.asm. (Notes for int 21h, fn. 25h are currently incorrect--seg:offset should be in ds:dx, not "ex":bx.)] Finally, you quit the program, leaving behind the Resident code and data (or, if you follow the greet.asm example, leaving behind all the code and data). [See Notes for int 21h, fn. 31h] Part 2: The Resident codeIf your Setup code worked properly, now everytime there is a keypress, your Resident code will be executed. First thing you need to do is call the saved vector. This original 09h vector actually processes keypresses and puts the contents into the buffer. You can't read any scan codes (or ASCII codes) until this has been done! If you try it, int 16h fn. 01h will simply return with the zero flag--no keys found.
Then check the scan code. [See Notes for int 16h, fn. 1. You cannot use fn. 2 to do this. And the function number goes in If it is one of the 3 function keys you're interested in, print the appropriate message or disable/enable printing. (I recommend using a simple variable that's either 1 or 0. If it's 0, F1 and F2 print nothing. When you press F3, change this variable to 0 if it is 1, or to 1 if it is 0.) Print with int 10h, fn. 13h. [See Notes or greet.asm] A Code SkeletonThis follows the book's example: using PROCs and leaving only the necessary code resident. To do this, all the Setup code must come at the end. Feel free to change any of the names. .MODEL SMALL .586 .STACK 100 .CODE ;No separate DATA seg for TSR ;*** BEGIN Resident code (including data)*** RES_BEGIN EQU $ ;put your data here: message contents, etc. KbdHandler LABEL DWORD ;where to save the old keyboard handler kbdh_offset DW ? kbdh_seg DW ? Resident PROC ;call the old handler first! pushf call KbdHandler sti ;allow other interrupts pushad ;save state ;use int 16h, fn. 01h to look at the inputted key ;match the scan codes to find out if it was a function key ;use int 10h, fn. 13h to print out the message (see greet.asm) popad ;restore state iret Resident ENDP RES_SIZE EQU $ - RES_BEGIN ;*** END Resident code *** Setup PROC push cs ;no .DATA, so setting ds to cs pop ds ;use int21h, fn. 35h to save the 09h vector in KbdHandler ;use int21h, fn. 25h to replace the 09h vector with Resident ;use int21h, fn. 31h to terminate but leave the Resident code behind ;here's how to calculate the needed number of paragraphs ;(see the book for the details) mov dx, (RES_SIZE + 15)/16 + 16 ;# of paragraphs, +16 for PSP Setup ENDP END Setup Filling in the CodeI recommend the following order of things:
|
~ztomasze Index :
TA Details : ICS312 : TSR Help http://www2.hawaii.edu/~ztomasze |
Last Edited: 06 Mar 2006 ©2006 by Z. Tomaszewski. |