home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-03-28 | 78.1 KB | 2,223 lines |
-
-
-
-
-
-
-
-
-
- THE ASSEMBLY LANGUAGE "MAGAZINE" VOL 1 NUMBER 2
- March 1989
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ## #### #### ####### ## ## ###### #### ## ##
- #### ## ## ## ## ## # ### ### ## ## ## ## ##
- ## ## ### ### ## # ####### ## ## ## ## ##
- ## ## ### ### #### ####### ##### ## ####
- ###### ### ### ## # ## # ## ## ## ## # ##
- ## ## ## ## ## ## ## # ## ## ## ## ## ## ##
- ## ## #### #### ####### ## ## ###### ####### ####
-
- #### ## ## ## #### ## ## ## #### #######
- ## #### ### ## ## ## ## ## #### ## ## ## #
- ## ## ## #### ## ## ## ## ## ## ## ## #
- ## ## ## ## #### ## ## ## ## ## ## ####
- ## # ###### ## ### ## ### ## ## ###### ## ### ## #
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
- ####### ## ## ## ## ##### ###### ## ## ##### #######
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Written by and for assembly language programmers.
-
-
-
-
-
-
-
-
-
-
- March 1989 Contents
-
- Policy................................................... 3
-
- Editorial................................................ 4
-
- Beginners Corner......................................... 5
-
- What is SDN?............................................. 7
-
- FASTPRINT................................................ 8
- by Dennis Yelle
- The EXEC Function........................................ 11
- by Patrick O'Riva
- TSR's.................................................... 13
- by David O'Riva
- Book Reviews............................................. 17
-
- Program Spotlight........................................ 18
-
-
- Source listings in order of appearance
-
-
-
-
- It has been suggested that the source listings be placed
- at the end of the "Magazine" rather than following the
- associated article. If you prefer it one way or the other
- please advise the editor.
-
- Address of The Assembly Language "Magazine"
- AsmLang and CFS FidoNet 143/37 408-259-2223
- Patrick O'Riva
- 2726 Hostetter Rd.
- San Jose, CA 95132
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
-
-
-
-
-
-
- GUIDE LINES FOR CONTRIBUTORS AND 'ADVERTISERS'
-
-
- Name and address must be included with all articles and
- files. Executable file size and percent of assembly code
- (when available) should be included when a program is
- mentioned and is required from an author or publisher.
-
- Any article of interest to Assembly language programmers
- will be considered for inclusion. Quality of writing will not
- be a factor, but I reserve the right to try and correct
- spelling errors and minor mistakes in grammar. Non-exclusive
- copyright must be given. No monetary compensation will be
- made.
-
- Outlines of projects that might be undertaken jointly are
- welcome. For example: One person who is capable with hardware
- needs support from a user friendly programmer and a math whiz.
-
- Advertisements as such are not acceptable. Authors and
- publishers wishing to contribute reviews of their own products
- will be considered and included as space and time permit.
- These must include executable file size, percent of assembly
- code and time comparisons.
-
- Your editor would like information on math libraries, and
- reviews of such.
-
- Articles must be submitted in pclone readable format or
- sent E-mail.
-
-
- Money: Your editor has none. Therefore no compensation
- can be made for articles included. Subscription fees
- obviously don't exist. Publication costs I expect to be nil
- (NUL). Small contributions will be accepted to support the BBS
- where back issues are available as well as files and programs
- mentioned in articles(if PD or Shareware ONLY).
-
- Shareware-- Many of the programs mentioned in the
- "Magazine" are Shareware. Most of the readers are prospective
- authors of programs that can be successfully marketed as
- Shareware. If you make significant use of these programs the
- author is entitled to his registration fee or donation.
- Please help Shareware to continue to be a viable marketing
- method for all of us by urging everyone to register and by
- helping to distribute quality programs.
-
-
-
-
-
-
-
-
- 3
-
-
-
-
-
-
- Editorial
-
- This is the second monthly edition of the Assembly
- Language Magazine. I have been disappointed in the response
- to the first issue both in the number of comments I have
- received and in the lack of articles submitted for inclusion
- in this issue. I would like to give a special thank you to
- Richard Hendricks for his letter of suggestions and comments,
- most of which I hope to address in this issue. He felt that a
- less full look to the pages would improve the readability and
- appearance.
-
- My original idea was to fill the page as much as possible
- to reduce the amount of print out. Many of his other comments
- reflect my lack of experience as an editor, and I will try to
- improve.
-
- Without some articles being sent in this will be near the
- last issue. The time is not available for your editors to
- write the entire magazine every month, and even if it were,
- the quality would suffer from lack of variety. Please send
- those submissions.
-
- Please excuse the late publication this month.
-
- ERRATA
-
- The name of the Author of the A86 Assembler was
- misspelled. The correct spelling is: Eric Isaacson
-
- In the article about fast memory moves I repeatedly
- referred to the 8259 as the DMA processor. The 8259 is the
- interrupt controller and has nothing to do with DMA transfers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4
-
-
-
-
-
-
- Beginners Corner.
-
- Obviously the first requirement for learning any assembly
- language is to have a list of the instructions. This may
- sound easy and it is something that most novice level books
- claim to have, but it is one of the most difficult things to
- find.
-
- Every source I have found is very incomplete and/or
- unclear. The exact use of each command and the hundreds of
- variations on each forces even scarred veterans to look back
- at a reference now and again.
-
- At least one of your references must contain the clocks
- data for each instruction. For the 80XXX series of processors
- this is a very confusing table of adds for all occasions. The
- basic time for the instruction is given plus the number of
- accesses plus EA calculation. It is different for a
- conditional jump taken and when it is not. To make matters
- even worse we are dealing with not one processor, but with at
- least 5: 8088, 80286, 80386, V20, V30. Each of these works
- differently and thus each has its own timing. Because it is
- the worst case and because there are so many installed it is
- always best to use the timing for the 8088 unless you are
- writing for a particular application or system.
-
- A first glance at the EA calculation table will be very
- enlightening to those who have used a high level language.
- Most of the variables passed and most all of the structures
- addressed are done with pointers and offsets to pointers.
- These are VERY costly time wise. Even pushes and pops take
- far longer than one would think. A memory access (fetching
- the value of a variable) especially using the AX register pair
- is faster than a push and pop. Be familiar with your
- instructions and how long they take. Only use half of the
- register pair if that is all you need because it saves an
- additional fetch, cutting the time almost in half.
-
- A clear verbal description of each instructions including
- its peculiarities is essential. This is true for all, but the
- more complex instructions such as rep movsb make it mandatory.
-
- Each instruction should list the flags it can affect.
- These are not always what you want or need. For example: the
- INC instruction does not affect the carry flag. As silly as
- it may sound you have to use an instruction that affects the
- flag you want to test for.
-
- The Rotate and Shift group of instructions should be
- accompanied with diagrams showing their operation. A glance at
- the diagrams will show exactly which one to use where it could
- take reading pages to do the same thing.
-
-
-
-
- 5
-
-
-
-
-
- One final note of caution that seems to fit in here --
- unless you are doing signed arithmetic operations avoid the
- use of the JG and JL type instructions. They take the sign
- bit into account and can cause very hard to trace bugs. Use
- the JA and JB instructions instead.
-
- Your next most important reference is a description of
- the BIOS calls. Most of these are very straight forward and
- require little by way of explanation.
-
- Next comes a DOS reference. The critical ones of these
- are also quite simple to understand and use. Don't get
- involved with FCB's; the handle method of file access is the
- only way to go.
-
- For your BIOS and DOS references almost any will work,
- but your basic instruction description look long and hard. You
- will probably end up with several you use regularly.
-
- With all of your reference works stacked up around you,
- sitting at your computer, what next? You need to choose an
- assembler. There are at least 4 major packages available,
- each with its supporters and its weaknesses. The Microsoft
- MASM is complete and the de facto standard. It is also large
- and slow. TASM from Borland is faster, and is mostly
- compatible, but tricky for beginners. Optasm I am not very
- familiar with, though it sounds pretty good. It is much faster
- than MASM, and is a full 2 pass assembler. If you are not
- concerned with compatibility A86 is fast, small and simple to
- use, and the D86 debugger is adequate.
-
- The text editor you use must produce a pure ASCII file.
- Whatever you enjoy is the one to use. Qedit from Semware can
- be configured to act like almost any other, and is fast and
- small.
-
- Next month: Segmentation and Memory allocation.
-
- Useful Shareware:
- 1029ref DOS and Pc Tech Reference
- inter Complete interrupt listing
- @last200 Pop up tables
- LW86 Pop up instruction summary
- Qedit Text editor
- A86 Assembler
- D86 Symbolic Debugger
-
-
-
-
-
-
-
-
-
-
-
- 6
-
-
-
-
-
-
- What is SDN?
-
- SDN stands for Shareware Distribution Network. It is a
- relatively new organization operating largely within FidoNet
- but in no way affiliated with it. SDN receives software direct
- from the author on disk, compresses it using the PAK facility
- from No Gate and distributes it to affiliated BBS's throughout
- the country, in a highly traceable manner.
-
- This distribution method is advantageous for both the
- author and the user. It assures the author of quick and
- complete distribution nationwide, and it assure the user of
- complete and uncontaminated software.
-
- There is no charge to either the author or the user for
- this service, but the author must comply with the instructions
- for transmitting the software to the SDN home point.
-
- Complete information is available from your local SDN BBS
- or as a last resort you can get the informational files from
- AsmLang.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7
-
-
-
-
-
-
-
- FASTPRINT: The fix for one of PRINT's bugs
- by Dennis Yelle
-
-
- Does your printer slow down when you run LIST or your
- favorite editor, word processor, debugger, or other program
- that spends most of its time just waiting for you to type at
- it? Does this annoy you? It annoyed me! It annoyed me
- enough so that I did something about it.
-
- How to use it:
- --------------
- Just type FASTPRINT at the DOS prompt, either before or
- after you run PRINT. Or put the FASTPRINT command in your
- AUTOEXEC.BAT file, that's what I do. If you put FASTPRINT in
- your AUTOEXEC.BAT file, it should normally be placed AFTER any
- utility that increases the size of the keyboard type-ahead
- buffer.
-
- How it works, if you like grubby details:
- -----------------------------------------
- The PRINT command installs a TSR that prints files in the
- background. This allows you to run other programs on your
- computer while the file(s) print. The PRINT TSR "steals" some
- computer time from you, but usually not enough to bother you.
- The problem is that sometimes (usually) it doesn't steal
- enough to keep the printer running at anywhere near full
- speed. Fortunately, there is a way to "give" the PRINT TSR
- more time. And, it turns out that COMMAND.COM does just that
- when it is waiting for you to type a DOS command. The problem
- is that most programs that you run don't do this. And so the
- printer slows down. ugh! Now we get to the good part.
- FASTPRINT looks for some signs that indicate that the
- foreground program is waiting for something, like a keystroke,
- and tells PRINT to do some printing while we wait.
-
- How it works, only for those who like the REALLY grubby
- details:
- -------------------------------------------------------
-
- The way to "give" the PRINT TSR some computer time is to
- put 0080H in AX, and do an INT 2FH. What FASTPRINT does, is
- link itself into interrupts 15H and 16H. INT 16H is used to
- read the keyboard. When a program tries to read a key that
- the human has not typed yet, FASTPRINT gives PRINT a bit of
- computer time, and then checks to see if the human has typed
- the key yet. If not, then it gives PRINT some more time and
- checks the keyboard again...INT 15H function 90H is used on
- the AT only to tell other programs that we are waiting for
- something that may take some time. So, if this happens, then
- FASTPRINT gives some time to PRINT.
-
-
-
-
- 8
-
-
-
-
-
- To make FASTPRINT even more useful to those who like
- grubby details, I am including the A86 source code for the
- program.
-
- How to pay for it:
- ------------------
- 1. If it is before March 30, 1989 then just: Send a message
- to me reporting how well FASTPRINT worked for you, including:
-
- (A. the hardware you are running on;
- (B. the version of DOS you are using;
- (C. how well it works, that is, for example, how many seconds
- does it take to print a www byte xxx line file with a yyy
- printer with and without using FASTPRINT while inside program
- zzz; and
- (D. anything else you have discovered about it, including any
- incompatibility with other programs.
-
- You may send this message to my PO Box, or to me at any
- of these BBS'S:
- AsmLang and CFS (Opus 1:143/37) 408-259-2223
- HomeBase 408-988-4004
- PDSE 408-745-0880
-
- 2. Just send a check for about 1/4 of what you think it is
- worth to you to:
- Dennis Yelle
- P. O. Box 62276
- Sunnyvale, CA 94088
-
- If you want to donate, but don't know how much it is
- worth, then just send me $10.
-
- 3. FOR PROGRAMMERS ONLY: If you want to use any or all of the
- source code in the file FASTPRIN.8 in your own program(s), you
- may buy the right to do so for $25.
-
- Legal mumbo jumbo
- -----------------
- This document and the program files FASTPRIN.COM and
- FASTPRIN.8 are copyrighted by the author. The copyright owner
- hereby licenses you to: use the software; make as many copies
- of it as you wish; give the copies to anyone; and to post this
- .ARC file on BBS'S, if the BBS is free. There is no charge
- for any of the above.
- However, you are specifically prohibited from charging,
- or requesting donations, for any copies, however made; and
- from distributing this software and/or documentation with
- commercial products without prior permission.
- No copy of this software may be distributed or given away
- without this document; and this notice must not be removed.
- There is no warranty of any kind, and the copyright owner is
- not liable for damages of any kind. By using this software,
- you agree to this.
-
-
-
- 9
-
-
-
-
-
-
- --------------------------------------------------------------
- Editors note: This is the documentation for FASTPRINT and
- has been included in the magazine at the author's suggestion
- as it describes the operation, is written in assembly and
- includes the source.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 10
-
-
-
-
-
-
- The EXEC Function
- by
- Patrick O'Riva
-
- The EXEC function is one of the most powerful features of
- DOS. It allows shelling out of an application, and even going
- as far as invoking another command interpreter. It is also
- rather complex to use and there is no debugging help from DOS.
-
- The EXEC command comes in three basic flavors; Load and
- execute a file, Load and overlay, and the 3rd is an internal
- DOS function of load a file. Only the load and execute a file
- will be covered in detail this month.
-
- I freely admit I'm not an expert on the use of the EXEC
- function, but I have convinced it to work for me and done so
- recently enough I can remember most of the mistakes. If anyone
- reading this is better informed, I encourage them to write a
- supplementary article.
-
- DOS requires that you supply three separate pieces of
- information. The program <filename> fully qualified as to
- drive, path, filename and extension. My experience is that it
- will not make a path search, but this might be inaccurate and
- caused by a slight error in syntax. The second item is the
- command line arguments in DOS format, where the first byte
- specifies the length of the argument including the length
- byte. The third item is an environment block. For this one
- you are allowed to default to current block as passed to the
- program you are EXEC'ing out of. To execute a batch file or
- use the built-in DOS commands you must EXEC command.com itself
- and pass the program name in the arguments.
-
- For "load and execute" a program the syntax is as
- follows:
-
- AH=4Bh EXEC function number within INT 21h
- AL=0 specify "load and execute"
- DX points to program name,
- i.e. 'C:\MYSTUFF\RUNME.EXE'
- ES:BX points to the "EXEC control block", defined
- as follows:
- WORD segment of environment block to pass
- if 0 defaults to parent block.
- environment is assumed to be at offset 0
- within this segment
- DWORD pointer to command tail
- DWORD pointer to 1st FCB
- DWORD pointer to 2nd FCB
-
- "COMMAND TAIL" is defined as that portion of a command
- line following the program name, preceded by a one byte count
-
-
-
-
- 11
-
-
-
-
-
- of the length of the tail plus 1 for the terminating CR (0Dh),
- i.e. DB 12,'/h /Ox1.obj',0Dh
-
- The first job most any program should do is return to DOS
- any portion of memory that is not required. Without this
- operation there would be no place for DOS to load the new
- program. It is also best to do this to inform your program how
- much memory is available to it to use for data storage and
- other general uses. If FFFF paragraphs are requested from DOS
- naturally a fail will be returned, but more importantly the
- amount available will also be returned. After determining that
- there is sufficient to at least attempt the EXEC the program
- can continue.
-
- Let's use the terms parent and child for the two
- programs. Once the EXEC is called the parent has no further
- control over the operation of the child. All control must be
- exercised through the information passed in the parameter
- block. You can tailor the environment block, specify the
- command tail, and point the 2 FCB's if the program uses them.
- If the program doesn't use them you can just point them to 5CH
- and 6CH of the parent's PSP(The segment address is supplied by
- DOS in ES and DS after the parent is loaded).
-
- I am including a short program that does nothing except
- EXEC according to your instructions. With some playing around
- it should be a good introductory tool. A sample program name
- and command tail are included, but these you will want to
- change.
-
- Some of the code in there is unnecessary, but may make it
- easier to customize or illustrates some point. With relatively
- small changes this could be included in another program to
- serve as an exec subroutine. The source is compatible with
- both MASM and A86.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 12
-
-
-
-
-
-
- TSR's
- How to get user input, Part Two
- (along with lotsa other neat stuff)
- by David O'Riva
-
- This article is a multi-part package, all rolled into one
- month, mainly because a good deal of it comes in one chunk:
- How to write a well-behaved TSR. For those of you who aren't
- quite sure what a TSR really is, a short definition follows.
-
- TSR, n, 1. Terminate and Stay Resident. 2. A program or
- routine that, after being loaded, carves a niche of memory for
- itself and holes up there, only showing itself when a certain
- circumstance occurs. This is what is meant by"serially
- multitasking." You press a "hotkey", and for some length of
- time the program you were working on is subjugated to the
- background, and the TSR gets to use the computer.
- 3. A real pain to write.
-
- TSR'S have numerous uses: print spoolers, expanded
- keyboard buffers, text editors, directory manipulators,
- background disk formatters, display managers, background file
- transferors - anything you may want to do while you're in the
- middle of another application.
- TSR's usually have the following basic structure
- (depending on what they do):
-
- jump to initialization
-
- main body of resident code
-
- keyboard interrupt interceptor
-
- timer tick interceptor
-
- DOS console interceptor
-
- un-installation routine
-
- initialization code
-
-
- An explanation of each of these follows:
-
-
- Initialization Code
-
- The initialization code must check to see if the TSR is
- already resident in memory (aborting if so), hook all of the
- interrupt servers into their respective chains, perform any
- other tasks necessary to install the program, then deallocate
- all unused memory and exit to DOS with a TSR call.
-
-
-
-
- 13
-
-
-
-
-
- To determine whether or not a copy of the TSR is already
- resident, you could assign an unused interrupt to it. The
- example uses INT 69H, function ABCD hex. If the example is
- already installed, it returns with DCBA hex in AX.
-
- This "residency check" interrupt could also handle
- functions for the TSR: i.e. if the TSR was a print
- spooler,and there was no "hot key" code written for it (like
- the DOS PRINT command), then the program could call INT 69H
- with function AB00H to add a file to the print queue.
-
- To hook an interrupt into a chain, you must replace the
- appropriate vector with a pointer to your interrupt server,
- and your interrupt server must jump to or call the code that
- the vector used to point to. Failure to do this caused many
- early TSR's to refuse to co-habit with other TSR's,
- occasionally making the machine bomb, etc... Unless you have
- a very good reason, ALWAYS continue the interrupt chain.
-
- Two TSR exits are available: The first is INT 27H,which
- has some limitations (only 64K of your program can remain
- resident, which shouldn't be too onerous), and which Microsoft
- does not recommend for anything except DOS 1. The second is
- INT 21H function 31H, which allows up to a meg to remain
- resident (right) and allows you to send a return code back to
- the caller.
-
- The initialization code usually de-allocates itself upon
- exiting.
-
-
- Keyboard Interrupt Interceptor
-
- This is only required for programs that wish to pop up
- when the hot key is pressed or wish to monitor the keyboard
- for some other reason. Much of what they have to do was
- discussed last month, with two exceptions.
-
- The first is how to prevent a keystroke from reaching the
- BIOS code without leaving the keyboard locked up. To do this,
- you have to tell the keyboard that you received the character,
- then reset the interrupt controller and exit (without chaining
- to the next interrupt.) The keyboard is cleared by toggling
- bit 7 of port 61H on, then off. The interrupt controller is
- cleared by sending an EOI(End Of Interrupt) code 20H to the
- 8259 at port 20H (weird,huh?). At that point you should do an
- IRET.
-
- The second is the necessity of monitoring the InDOS flag.
- Note that YOU ONLY HAVE TO DO THIS IF YOUR TSR USES DOS
- FUNCTIONS. Also note that this flag is NOT documented by IBM
- OR Microsoft, and that it is not strictly "compatible."
-
-
-
-
-
- 14
-
-
-
-
-
- The address of the InDOS flag can be acquired by a call
- to INT 21H function 34H. The flag is non-zero if a DOS
- function is currently active. You need this flag because DOS
- is not re-entrant. That is, if you call DOS from your TSR,and
- DOS was active when the TSR gained control, the TSR will work
- fine, but when you return from it, the function in progress
- will have lost its entire stack and much of its data area.
- Nasty stuff.
-
- If the InDOS flag is set when the keyboard trap is
- activated, the keyboard trap should set a flag saying "I want
- to activate but I can't" and return.
-
-
- Timer Tick Interceptor
-
- These are always fun. 18.2 times per second, you get
- control of the machine. This is useful for print spoolers,
- resident screen clocks, and TSR'S that need to perform DOS
- functions.
-
- In the last case, the timer tick trap should check to see
- if the TSR wants to activate, and if so whether the InDOS flag
- is set. If the InDOS flag is clear, then the TSR can be
- activated.
-
-
- DOS Console Interceptor
-
- This interrupt (INT 28H) is called by DOS whenever a DOS
- console function is in progress. This is useful to have
- because during a console input, the InDOS flag is set, but it
- is actually safe to use any DOS function ABOVE 0CH.
-
- This trap should check to see if the TSR wants to
- activate, and if so then activate it.
-
-
- Main Body of the TSR
-
- The only requirement for this is that if you use more
- than two words (yes, this is an arbitrary measure that seems
- safe to me) of stack, you should use your internal stack
- instead of the one that you were called with. This is because
- you have no idea how large the stack you're working on is, and
- no way of telling how far you can go before you start to
- overwrite data...
-
-
- The Un-Installation routine
-
- This is a very nice thing to have. The only problem is
- that it needs to use a DOS call to de-allocate its memory.
-
-
-
-
- 15
-
-
-
-
-
- Unless, of course, you want to directly modify the memory
- control blocks... which could be very dangerous.
-
- The routine in the example TSR does check the memory
- control block immediately after it to make sure that there are
- no programs installed in memory after the TSR. DOS gets upset
- when there are "holes" in memory. At least, it's supposed to.
- The structure included for the MCB is complete as far as I
- know, but it is also *extremely* undocumented. Microsoft
- calls it an "arena header" and tells programmers to keep their
- hands off of it.
- All vectors must be unhooked.
-
- The DOS calls to de-allocate the memory are necessary.
-
-
- Neat tricks you can pull...
-
- The command line area in the PSP makes for a convenient
- 40 word internal stack. If you aren't using the FCBS, the FCB
- storage area can be commandeered as well.
-
- The environment segment's size can be checked (with a
- look at the MCB) and that can be used for stack, data or code
- as well.
-
-
- The Example TSR
-
- As far as actual use goes, the example TSR is a very
- simple beast. When resident, press LSHIFT-RSHIFT-T (it'll
- beep). Then press "Q" to return to normal processing, or
- press "N" to Nuke the TSR (remove it from memory). If it
- cannot remove itself, it will beep three times.
-
- Well, that's about all there is to it. With all these
- routines (or at least the ones you need) combined in one
- cohesive package, you have a full-fledged TSR skeleton. The
- example TSR includes most of these techniques. Use and enjoy.
- Comments on this article, or expansions on the subject matter
- are greatly appreciated and will be published in later issues
- of the magazine.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16
-
-
-
-
-
-
-
- Book Reviews by Patrick O'Riva
-
-
-
- PROGRAMMER'S TECHNICAL REFERENCE FOR MSDOS AND THE IBM PC
- By Dave Williams P.O. box 181, Jacksonville, AR 72087
-
- This is a first glance review that I wanted to get into
- this month's issue. It is a user supported book on disk. I
- haven't had the time to read through it, but it appears to be
- one of the best available in any format. In compressed form
- it is over 200k, and expands to over 500k. It is very
- complete and includes some hard to find tables and version
- histories. Requested $15 support includes 2 additional disks
- and updates. Probably one of the best buys around.
-
- It is available on various BBS's (AsmLang included)
- though its 200k+ size makes for slow distribution. The
- complete package direct from the author is probably best.
-
-
- IBM Technical Reference- Personal Computer XT
-
- This comes in the standard binder/box and is available
- from IBM corporation at a hefty $50. In addition to some
- information on port assignments and memory maps it contains
- two sets of information that I have found nowhere else.
-
- A complete listing of the ROM BIOS for the XT that is
- invaluable as both an example of programming each piece of
- hardware and clues as to how to optimize for a specific
- application.
-
- Complete schematics of the motherboard of the XT that can
- help to explain why something won't work if you are
- technically inclined.
-
- I have found it invaluable, but it is not for everyone.
- Similar publications are available for the other IBM
- products and for the PCDOS.
- For further information contact IBM at 1-800-426-7282
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 17
-
-
-
-
-
-
-
- Program Spotlight
- Exceptional Programs
-
- This is really a nonexistent column this month as nothing
- new has come to my notice that meets the qualifications of
- high speed and small size.
-
- There is a nice piece of source code available under the
- name of CRC16 that calculates and verifies 16 bit CRC values.
- If this meets a need of yours keep a look out for it.
-
- Although I haven't tried it out yet, a program called the
- Brand X symbolic debugger has been highly recommended to me.
- Other comments would be welcomed.
-
- QFILE31G handles copying, deleting and moving files, as
- well as maintaining and listing ARC's and ZIP's. Nicely done,
- but too slow and too large to really fit here, and hangs up on
- some error conditions.
-
- WHIZ1 a file finding program certainly qualifies in speed
- as a multi disk search with wild card only takes a few
- seconds. It is a bit larger than it might be, but at the
- least it is enhanced with assembly routines. It is a shareware
- offering and is widely available.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 18
-
-
-
- ;Ed -This is the source code on FASTPRINT
- jmp install ; This will be a .COM
-
- db cr, ' ', cr, lf ; On most displays, if this file is TYPEed,
- ; these 3 spaces will erase
- ; the 3 characters in the JMP instruction above.
- message0:
- db 'FASTPRIN 0.0 Copyright 1989 by Dennis Yelle,'
- db ' PO Box 62276, Sunnyvale CA 94088'
- db cr, lf
- message0_len = $ - message0
- db 'Last change: Mar 4, 1989', cr, lf
-
- db 26 ; This 26 is a control-Z, the DOS EOF character.
- ; I put it here so that if someone TYPEs this .COM file,
- ; only the characters before the 26 will be printed on the screen.
-
- id_size = $ - 0100
-
- ; To assemble this program, put the source in a file called
- ; FASTPRIN.8 and then type
- ; A86 FASTPRIN.8
- ; This will produce a file called FASTPRIN.COM directly,
- ; in about 2 seconds! No need to run a linker!
- ; The program A86.COM is available from many BBSs in an .ARC file
- ; that starts with A86.
- ; In particular, A86.COM is available from the "AsmLang and CFS" BBS
- ; (Opus 1:143/37) 408-259-2223 in the file A86V319A.ZIP.
- ; Or HomeBase 408-988-4004 in the file A86V309A.ARC.
- ; Or PDSE 408-745-0880 in the file A86V314A.ARC.
- ;
- ; FASTPRIN installs a TSR which speeds up the printing done by the
- ; DOS PRINT command by calling INT 02FH with AX = 0080H whenever the
- ; system is idle. We know the system is idle whenever:
- ;
- ; 1. INT 016 is called with AH = 0 and there are no characters in
- ; the keyboard buffer. or
- ; 2. INT 015 is called with AH = 090. This will only happen on an AT.
- ;
- ; Termination codes:
- ; 0 - Successfully installed.
- ; 1 - Unable to determine if already installed, installed anyway.
- ; 2 - Already installed.
- ;
- ; If this program has been helpful to you, then please send a
- ; small gift to the author, Dennis Yelle, PO Box 62276,
- ; Sunnyvale, CA 94088. A gift of $10 is suggested.
-
- cr = 0d
- lf = 0a
-
- even
- old_int_15 dw 2 dup (?)
- old_int_16 dw 2 dup (?)
-
- get_vect macro
- push es
- #rx1l
- mov ax, 03500 + 0#x
-
-
- int 021
- mov old_int_#x, bx
- mov old_int_#x[2], es
- #er
- pop es
- #em
-
- set_vect macro
- #rx1l
- mov dx, offset new_int_#x
- mov ax, 02500 + 0#x
- int 021
- #er
- #em
-
- new_int_16:
- pushf
- sti
- test ah,ah
- jz wait_16
- popf
- jmp cs: d old_int_16
-
- wait_16_loop:
- mov ax, 0080
- int 02f ; Do some printing.
- wait_16:
- mov ah, 1
- int 016 ; Are any chars ready?
- jz wait_16_loop ; Jump if not.
- mov ah, 0
- popf
- jmp cs: d old_int_16
-
- new_int_15:
- pushf
- sti
- cmp ah, 090
- je idle
- popf
- jmp cs: d old_int_15
-
- idle:
- push ax
- mov ax, 0080
- int 02f ; Do some printing.
- pop ax
- popf
- jmp cs:d old_int_15
-
- end_of_resident:
- ;---------------------------------------------------------
-
- install:
- mov ah, 040
- mov bx, 1 ; Write to stdout
- mov dx, message0
- mov cx, message0_len
- int 021
- mov ah, 052
-
-
- int 021
- mov ax, es:[bx-2]
- mov dx, ds
- dec dx
- cld
- find:
- cmp ax, dx
- je install_it
- ja mem_bad
- mov es, ax
- mov si, 0100
- mov di, 0110
- mov cx, id_size/2
- repe cmpsw
- je already_installed
- stc
- adc ax, es:[3]
- jnc find
- mem_bad:
- mov w installed_msg, mem_bad_msg
- inc b term_code
- install_it:
- get_vect 15, 16
- set_vect 15, 16
-
- mov ah, 049
- mov es, [02c]
- int 021 ; Free the ENV segment.
-
- mov dx, installed_msg
- mov ah, 9
- int 021 ; Print the INSTALLED message.
-
- mov ah, 031
- mov al, term_code
- mov dx, (end_of_resident+15)/16
- int 021 ; Terminate and stay resident.
- ;-------------------------------------------------------------
-
- already_installed:
- mov dx, ai_msg
- mov ah, 9
- int 021 ; Print the message.
- mov ax, 04c02
- int 021
-
- installed: db 'FASTPRIN is now installed.', cr, lf, '$'
-
- mem_bad_msg:
- db 'FASTPRIN was unable to determine if it was previously installed, or not,'
- db cr, lf,
- db 'so it installed itself anyway.', cr, lf, '$'
-
- ai_msg: db 'FASTPRIN was already installed.', cr, lf, '$'
-
- installed_msg dw installed
- term_code db 0
-
-
- ;THIS IS THE SOURCE CODE FOR THE EXEC FUNCTION ARTICLE
- ;
- ;THIS PROGRAM WITH FEW IF ANY SYNTAX CHANGES SHOULD BE COMPATIBLE WITH BOTH A86
- ;AND MASM.
- ;IT IS NOT DESIGNED TO BE A STAND ALONE PROGRAM OR EVEN USER FRIENDLY BUT A
- ;BARE SHELL WITH WHICH TO PLAY AROUND WITH IN LEARNING TO USE THE DOS EXEC
- ;FUNCTION
- ;THE PROGRAM NAME SHOULD BE ENTERED BETWEEN THE QUOTE MARKS AT THE VARIABLE
- ;-PROGRAM- AND ANY OTHER COMMAND LINE ARGUMENTS SHOULD BE ENTERED BETWEEN THE
- ;QUOTE MARKS AT THE VARIABLE -COMMAND- BEFORE ASSEMBLY. MANY IMPROVEMENTS ARE
- ;OBVIOUS, SUCH AS BEING ABLE TO ENTER THE NAMES AND ARGUMENTS FROM THE CONSOLE
- ;BUT THESE ARE LEFT TO EXPERIMENTER.
- ;THE ONE SOPHISTICATION IF YOU COULD CALL IT THAT IS THAT THE ERROR LEVEL OF
- ;THE EXEC'D PROGRAM IS FETCHED, BUT NOTHING IS DONE WITH IT.
- CODE SEGMENT 'CODE'
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
- org 0
- PROG_ORG LABEL BYTE
- org 0100
- ENTRY: JMP START
-
-
- db 32 DUP ('STACK ') ;THIS SETS ASIDE 256 BYTES-
- ;REQUIRED DOS STACK
- STAK LABEL BYTE ;THIS MARKS TOP OF STACK
-
- THIS_SEG DW 0 ;STORAGE FOR ADDRESS OF THIS SEGMENT
-
- CTL_LEN DW 0 ;THIS IS THE START OF THE *****
- PROGRAM DB 'c:\dos\list.com',0 ;ASCIIZ STRING OF PROGRAM TO
- EXEC
-
- CMDL LABEL BYTE ;BEG ADDRESS OF COMMAND TAIL
- CMDLEN DB 0 ;OFFSET CR - OFFSET COMMAND
- COMMAND DB 'exec.asm' ;THE COMMAND TAIL ITSELF
- CR DB 0DH ;TERMINATING CARRIAGE RETURN
-
- PARMS LABEL BYTE ;ADDRESS OF PARAMETER TABLE
- ENV DW 0 ;POINTER TO ENVIRONMENT BLOCK
- ;0 DEFAULTS TO PARENT
- CMDLNLOW DW 0 ;OFFSET OF COMMAND TAIL
- CMDLNHI DW 0 ;SEGMENT OF COMMAND TAIL
- FCB11 DW 0 ;OFFSET OF FCB1
- FCB12 DW 0 ;SEGMENT OF FCB1
- FCB21 DW 0 ;OFFSETT OF FCB2
- FCB22 DW 0 ;SEGMENT OF FCB2
- MS1 DB 'DEALLOCATION ERROR',0DH,'$' ;MESSAGE #1
- MS2 DB 'EXEC ERROR',0DH,'$' ;MESSAGE #2
- START:
- CLI ;TURN OFF INTERRUPTS WHILE SWITCHING
- ;STACK FRAMES
- MOV SP,OFFSET STAK ;POINT STACK WHERE WE WANT IT
- STI ;INTS OK NOW
- MOV AX,DS ;BEING A COM PROGRAM DS CONTAINS THIS
- ;SEGMENT
- MOV THIS_SEG,AX ;PUT IT WHERE WE CAN GET IT EASILY
- RESIZE:
- MOV BX,(OFFSET PROG_END - OFFSET PROG_ORG) ;FIND OUT
- ;HOW BIG THE PROGRAM IS
- MOV CL,4 ;TURN THIS VALUE INTO PARAGRAPHS
-
-
- SHR BX,CL
- ;
- INC BX ;NEEDS 1 MORE TO CATCH OVERFLOW
- MOV AH,04AH ;ASK FOR DEALLOCATION OF ALL BUT THIS
- INT 021H
- JNC S1 ;IF CARRY BAD PROBLEM
- MOV AX,OFFSET MS1 ;POINT AX AT MESSAGE 1
- JMP END_ERROR ;NOW LEAVE
- S1:
- ;AN ASSUMPTION IS MADE AT THIS POINT, THAT
- ;THERE IS ENOUGH MEMORY FOR THE PROGRAM TO BE
- ;EXEC'D TO OPERATE IN. IF NOT AN EXEC ERROR
- ;WILL BE RETURNED.
-
- MOV AX,OFFSET CR ;FIND LENGTH OF COMMAND TAIL
- SUB AX,OFFSET CMDL ;AND
- MOV CMDLEN,AL ;PUT IT IN CMDLEN
- MOV DX,OFFSET CMDL ;FILL IN THE COMMAND TAIL POINTER IN
- ;THE PARAMETER BLOCK
- MOV CMDLNLOW,DX
- MOV CMDLNHI,DS
- MOV DX,OFFSET PROGRAM ;POINT DX AT PROGRAM NAME
- MOV ES,THIS_SEG ;MAKE SURE ES IS POINTING AT THIS SEG
- MOV BX,OFFSET PARMS ;POINT BX AT PARAMETER BLOCK
- MOV AX,05CH ;THIS IS OFFSET OF PARENT FCB1 BUT
- ;COULD BE ANY INFO DESIRED TO PASS TO
- ;CHILD THAT WOULD BE LOOKED FOR AT PSP
- ;5CH
- MOV FCB11,AX ;PUT IT IN PARAMETER BLOCK
- MOV FCB12,ES ;DESIRED SEGMENT OF FCB1 DATA
- MOV AX,06CH ;FILL IN FCB2. ABOVE COMMENTS APPLY
- MOV FCB21,AX
- MOV FCB22,ES
- MOV AH,04BH ;THE EXEC FUNCTION
- MOV AL,0 ;LOAD AND EXECUTE
- PREX:
- INT 021H ;DOS
- JNC FINISHED ;ALL ACCORDING TO PLAN
- MOV AX,OFFSET MS2 ;SOMETHING WRONG IN EXEC
- JMP SHORT END_ERROR
- FINISHED:
- MOV AH,04DH ;TO REACH HERE THE CHILD MUST HAVE
- ;TERMINATED. THIS REQUESTS THE
- ;TERMINATION CODE
- INT 021H ;DOS TERMINATION CODE RETURNED IN AH
- ;CHILD'S AL PASSED THROUGH
- MOV AH,04CH ;TERMINATE THIS PROG
- INT 021H
- END_ERROR:
- MOV DX,AX ;SAVE THE MESSAGE ADDRESS TO DX
- MOV BX,1 ;DEVICE HANDLE IS CONSOLE
- MOV CX,20 ;20 BYTES IS ENOUGH FOR THE MESSAGE
- MOV AH,040H ;WRITE TO DEVICE (CONSOLE)
- INT 021H ;DOS
- MOV AH,04CH ;TERMINATE THIS PROGRAM
- INT 021H
-
- PROG_END LABEL BYTE
- CODE ENDS
- END ENTRY
-
-
- PAGE 60,132
- TITLE EXMPLTSR.ASM - An example of a TSR program
-
- COMMENT~*********************************************************************
- * --++**> This file is Copyright 1989 by David O'Riva <**++-- *
- *****************************************************************************
- * *
- * Written for the Microsoft Macro Assembler version 5.1, DOS v2.0 - 3.3 *
- * *
- * MUST BE CONVERTED INTO A .COM FILE BEFORE RUNNING!!! *
- * *
- * Anyone who wants to incorporate this code into their programs is *
- * welcome to, as long as they don't try to sell this file as it is or any *
- * unmodified piece of it, and leave this message in when distributing it. *
- * If you do not abide by the rules, poltergeists will invade your home *
- * and chain letters and junk mail will arrive by the ton. *
- * *
- * *
- * Short advertisement - use QEdit! *
- * Available on your local friendly Bulletin Board *
- * *
- ****************************************************************************~
- .XLIST
- ;
- ; Macros used by this program
- ;
-
- ?PLevel = 0
-
- PNPROC MACRO PNAME ;;declare near public procedure
- IF2
- %OUT Routine: &PNAME
- ENDIF
- PUBLIC &PNAME
- &PNAME PROC NEAR
- ?PLevel = ?PLevel+1 ;;next level of nesting
- @@SAVE_NAME &PNAME,%?PLevel
- ENDM
-
- PFPROC MACRO PNAME ;;declare near public procedure
- IF2
- %OUT Routine: &PNAME
- ENDIF
- PUBLIC &PNAME
- &PNAME PROC FAR
- ?PLevel = ?PLevel+1 ;;next level of nesting
- @@SAVE_NAME &PNAME,%?PLevel
- ENDM
-
- ENDPROC MACRO
- @@REC_NAME %?PLevel
- @@EP1 %@@TEMP
- ?PLevel = ?PLevel-1
- ENDM
-
- @@SAVE_NAME MACRO PNAME,LVL
- ?PN&LVL EQU <&PNAME>
- ENDM
-
-
-
- @@REC_NAME MACRO LVL
- @@TEMP EQU <?PN&LVL>
- ENDM
-
- @@EP1 MACRO PNAME
- &PNAME ENDP
- ENDM
-
- PUSHM MACRO LST
- IRP REG,<&LST&>
- PUSH REG
- ENDM
- ENDM
-
- POPM MACRO LST
- IRP REG,<&LST&>
- POP REG
- ENDM
- ENDM
-
- UPCASE MACRO REG
- LOCAL NOUP
- CMP REG,'a'
- JB NOUP
- CMP REG,'z'
- JA NOUP
- SUB REG,'a'-'A'
- NOUP:
- ENDM
-
- @CHANGE_VECT MACRO INUM,GARB,NEW,GARB2,SAVEAREA
- MOV AX,0
- MOV ES,AX
- MOV AX,ES:[INUM*4]
- MOV DX,ES:[INUM*4+2]
- MOV WPTR CS:[SAVEAREA],AX
- MOV WPTR CS:[SAVEAREA+2],DX
- MOV AX,OFFSET CS:NEW
- CLI
- MOV ES:[INUM*4],AX
- MOV ES:[INUM*4+2],CS
- STI
- ENDM
-
- @RESTORE_VECT MACRO INUM,GARB,SAVEAREA
- MOV AX,WPTR CS:[SAVEAREA]
- MOV DX,WPTR CS:[SAVEAREA+2]
- CLI
- MOV DS:[INUM*4],AX
- MOV DS:[INUM*4+2],DX
- STI
- ENDM
-
- BPTR EQU <BYTE PTR>
- WPTR EQU <WORD PTR>
- DPTR EQU <DWORD PTR>
- CR EQU <13>
- LF EQU <10>
- JR EQU <JMP SHORT>
-
-
- FALSE EQU <000H>
- TRUE EQU <0FFH>
-
- INT_CTRL EQU 020H ;Interrupt control port
- EOI EQU 020H ;Reset interrupt controller command
- KB_DATA EQU 060H ;Keyboard data port
- KB_CTRL EQU 061H ;Keyboard control port
- ;
- ;****************************************************************************
- ;
- BIOSDATA SEGMENT AT 00040H
-
- ;----------------------------------------------------------------------------
- ;Keyboard Data Area
- ;----------------------------------------------------------------------------
- ORG 00017H
- KB_FLAG LABEL BYTE
-
- ;----- Shift flag equates within KB_FLAG
-
- INS_STATE EQU 80H ;INSERT state is active
- CAPS_STATE EQU 40H ;CAPS LOCK state toggled
- NUM_STATE EQU 20H ;NUM LOCK state toggled
- SCROLL_STATE EQU 10H ;SCROLL LOCK state toggled
- ALT_SHIFT EQU 08H ;ALT key depressed
- CTRL_SHIFT EQU 04H ;CTRL key depressed
- LEFT_SHIFT EQU 02H ;left SHIFT key depressed
- RIGHT_SHIFT EQU 01H ;right SHIFT key depressed
-
- ORG 00018H
- KB_FLAG_1 LABEL BYTE
-
- ;----- Shift flag equates within KB_FLAG_1
-
- INS_SHIFT EQU 80H ;INSERT key depressed
- CAPS_SHIFT EQU 40H ;CAPS LOCK key depressed
- NUM_SHIFT EQU 20H ;NUM LOCK key depressed
- SCROLL_SHIFT EQU 10H ;SCROLL LOCK key depressed
- HOLD_STATE EQU 08H ;suspend key has been toggled
-
- ORG 00019H
- ALT_INPUT LABEL BYTE ;storage for alternate keypad entry
-
- ORG 0001AH
- BUFFER_HEAD LABEL WORD ;pointer to head of keyboard buffer
-
- ORG 0001CH
- BUFFER_TAIL LABEL WORD ;pointer to tail of keyboard buffer
-
- ORG 0001EH
- KB_BUFFER LABEL WORD ;keyboard buffer
-
- ORG 0003EH
- KB_BUFFER_END LABEL WORD
- ;
- ;----- HEAD = TAIL indicates that the buffer is empty
-
- NUM_KEY EQU 69 ;scan code for NUM LOCK
- SCROLL_KEY EQU 70 ;sc for SCROLL LOCK
-
-
- ALT_KEY EQU 56 ;sc for ALT key
-
- BIOSDATA ENDS
-
- .list
- .lall
- ;
- ;****************************************************************************
- ;
- CODE SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
-
- ORG 02CH
- ENVIRONMENTSEG LABEL WORD
-
- ORG 100H
- MAIN PROC FAR
-
- STACKTOP: ;allow the stack to overwrite the
- ;command line in the PSP
- ENTRY: JMP INSTALL
-
- ;============================================================================
- ;
- ; MY LOCAL DATA
- ;
-
- MCBOVL STRUC ;definition of DOS's memory control
- ; ;block structure
- MCB_KIND DB ' '
- MCB_PSP_ADDR DW 0
- MCB_LENGTH DW 0
- MCB_UNDEFINED DB 11 DUP(?)
- ;
- MCBOVL ENDS
-
- m@BLOCK EQU <'M'> ;possible entries in the MCB_TYPE field
- m@LAST EQU <'Z'>
-
- OLD9 DD ? ;old INT 09H vector
- OLD08 DD ?
- OLD28 DD ?
- OLD69 DD ?
-
- InDOS DD ? ;address of the InDOS flag
- CODSEG DW ? ;code segment
-
- AllowPop DB FALSE ;TRUE = the INT 09H server is allowed
- ; to try to run the TSR.
-
- TryPop DB FALSE ;TRUE = The INT 09H server couldn't
- ; run the TSR because DOS was
- ; processing a command at the
- ; time.
- ;
- InPop DB FALSE ;TRUE = the popped-up code is running
- ; at the moment.
-
- OLDSS DW ? ;storage for stack frame information
- OLDSP DW ?
-
-
-
- PopShifts DB LEFT_SHIFT+RIGHT_SHIFT ;shift state necessary for
- ; pop-up
-
- PopKey DB 14H ;key # to press to pop up ('T')
-
- ;============================================================================
-
-
- PAGE
- ;****************************************************************************
- ; START - main program loop
- ;
- ;
- ; ENTRY: from hot key
- ;
- ; EXIT: nothing
- ;
- ; DESTROYED: none
- ;
- ;----------------------------------------------------------------------------
- PNPROC START
-
- ;------------------------------------------------------------------------------
- ; set up my stack frame
- ;------------------------------------------------------------------------------
- MOV CS:OLDSS,SS
- MOV CS:OLDSP,SP
- CLI
- MOV SS,CS:CODSEG
- MOV SP,OFFSET STACKTOP
- STI
- PUSH AX
-
- ;------------------------------------------------------------------------------
- ; MAIN LOOP
- ;------------------------------------------------------------------------------
- CALL BEEP
- GETAKEY:
- MOV AH,0 ;get a key
- INT 016H
- UPCASE AL
-
- CMP AL,'N' ;'N' for NUKE THE TSR!
- JNE NOT_NUKE
-
- CALL UNLOAD ;try to unload myself
- JNC LEAVE
- CALL BEEP ;string of beeps if I can't
- CALL BEEP
- CALL BEEP
- JMP GETAKEY
-
- NOT_NUKE: CMP AL,'Q' ;'Q' for quit TSR
- JE LEAVE
- ;
- CALL BEEP ;unrecognized key, complain
- JMP GETAKEY ;... and get another
-
- LEAVE: POP AX ;recover * ALL * modified registers
-
-
- ; -------
- ;------------------------------------------------------------------------------
- ; recover original stack frame
- ;------------------------------------------------------------------------------
- CLI
- MOV SS,CS:OLDSS
- MOV SP,CS:OLDSP
- STI
-
- RET
- ENDPROC
-
-
- PAGE
- ;******************************************************************************
- ; BEEP - Beeps the speaker
- ;
- ;
- ; ENTRY: nothing
- ;
- ; EXIT: nothing
- ;
- ; DESTROYED: none
- ;
- ;------------------------------------------------------------------------------
- PNPROC BEEP
-
- PUSH AX
- PUSH CX
- MOV AL,10110110B
- OUT 043H,AL
- MOV AX,1000
- OUT 042H,AL
- MOV AL,AH
- OUT 042H,AL
-
- IN AL,061H
- MOV AH,AL
- OR AL,3
- OUT 061H,AL
- SUB CX,CX
- LOOP $
- MOV AL,AH
- OUT 061H,AL
- POP CX
- POP AX
- RET
- ENDPROC
-
-
- ; PAGE
- ;;****************************************************************************
- ;; REGISTERTOTEXT - Converts AL into ASCII hex digits in CS:[SI]
- ;;
- ;; For debugging - uncomment this routine if you need it.
- ;; ;
- ;; ENTRY: AL = register to translate
- ;; SI = place to put translated digits
- ;;
- ;; EXIT: AX = hex digits
-
-
- ;;
- ;; DESTROYED: AX
- ;;
- ;;----------------------------------------------------------------------------
- ;ASSUME ds:NOTHING,es:NOTHING
- ;PNPROC REGISTERTOTEXT
- ;;----------------------------------------------------------------------------
- ;; split AL into two nibbles
- ;;----------------------------------------------------------------------------
- ; MOV AH,AL
- ; SHR AH,1
- ; SHR AH,1
- ; SHR AH,1
- ; SHR AH,1
- ; AND AL,0FH
- ;;----------------------------------------------------------------------------
- ;; convert AL into a hex digit
- ;;----------------------------------------------------------------------------
- ; ADD AL,'0' ;AL = actual digit
- ; CMP AL,'9'
- ; JBE R_1
- ; ADD AL,'A'-'0'-10
- ;;----------------------------------------------------------------------------
- ;; convert AH into a hex digit
- ;;----------------------------------------------------------------------------
- ;R_1: ADD AH,'0' ;AH = actual digit
- ; CMP AH,'9'
- ; JBE R_2
- ; ADD AH,'A'-'0'-10
- ;;----------------------------------------------------------------------------
- ;; store hex number in [SI]
- ;;----------------------------------------------------------------------------
- ;R_2: MOV CS:[SI],AH
- ; MOV CS:[SI+1],AL
- ; RET
- ;ENDPROC
- ;
-
- PAGE
- ;****************************************************************************
- ; TRAPPER9 - Intercepts the incoming keyboard scan code
- ;
- ; Looks for the hot key in the incoming scan codes. If found, it
- ; check the InDOS flag to see if DOS is currently in the middle of something.
- ; If not, the TSR code (at START) is invoked. Otherwise, a flag is set and
- ; control is passed back to DOS.
- ;
- ; ENTRY: from IRQ 1, machine state is ???
- ;
- ; EXIT: continues KB interrupt chain
- ;
- ; DESTROYED: ALL PRESERVED
- ;
- ;----------------------------------------------------------------------------
- ASSUME ds:BIOSDATA,es:NOTHING
- PFPROC TRAPPER9
- PUSHM <AX,BX,DS,ES> ;save everthing I use
-
- MOV AX,SEG BIOSDATA ;DS-> BIOS's data seg
- MOV DS,AX
-
-
- ;----------------------------------------------------------------------------
- ; are we in the correct shift state?
- ;----------------------------------------------------------------------------
- MOV AL,KB_FLAG ;get current shift states
- AND AL,00FH ;clean up the byte
- CMP AL,CS:PopShifts ;is it the right shift?
- JNE T_chainon ;no, go to next handler
-
- IN AL,KB_DATA ;Poll keyboard controller
- MOV BH,AL ;save keypress
- AND AL,07FH ;strip off the MAKE/BREAK bit
- CMP AL,CS:PopKey ;is this our key?
- JNE T_ChainOn ;If it's not our code, ignore it...
- ;----------------------------------------------------------------------------
- ; reset the keyboard controller
- ;----------------------------------------------------------------------------
- IN AL,KB_CTRL ;get multi-purpose control byte
- MOV AH,AL ;save original value
- OR AL,080H ;set "character recieved" bit
- OUT KB_CTRL,AL ;send it
- MOV AL,AH ;get original value back
- OUT KB_CTRL,AL ;send it
- ;------------------------------------------------------------------------------
- ; what do we do with this key?
- ;------------------------------------------------------------------------------
- CMP CS:AllowPop,FALSE ;Are we allowed to pop up now?
- JE T_ResetLeave ;if not, exit here...
-
- TEST BH,080H ;was it the BREAK code?
- JZ T_WasMake ;no, go run the pop-up
- JMP T_ResetLeave ;otherwise, ignore this code
-
- T_WasMake: MOV CS:AllowPop,FALSE ;can't pop up again
-
- PUSHM <ES,BX> ;check the InDOS flag...
- LES BX,CS:InDOS
- CMP BPTR ES:[BX],0
- POPM <BX,ES>
-
- JNZ T_InDOSnow ;if in DOS, don't invoke TSR
-
- MOV AL,EOI ;otherwise, set interrupts on...
- OUT INT_CTRL,AL
- MOV CS:InPop,TRUE ;...set a flag...
- STI
- CALL START ;...and run the TSR.
- CLI
- MOV CS:AllowPop,TRUE
- MOV CS:InPop,FALSE
- JMP T_Leave
-
- T_InDOSnow: MOV CS:TryPop,TRUE ;DOS call in progress, try later...
- ;
- T_ResetLeave: MOV AL,EOI ;enable the KB interrupt again
- OUT 020H,AL
- T_Leave: POPM <ES,DS,BX,AX> ;throw away this key code
- IRET
- ;----------------------------------------------------------------------------
- ; Continue down the KB handler chain...
- ;----------------------------------------------------------------------------
-
-
- T_chainon: POPM <ES,DS,BX,AX>
- JMP DWORD PTR CS:OLD9
- ENDPROC
-
-
-
- PAGE
- ;******************************************************************************
- ; TRAPPER08 - Intercepts the timer tick to try to pop up the TSR
- ;
- ; Upon being called, this routine determines whether:
- ; a) the TSR wants to pop up, and
- ; b) there is no DOS call in progress
- ; If these are BOTH true, then the TSR is invoked from here.
- ;
- ; NOTE: Technically, you are supposed to trap vector 1CH for timer
- ; ticks instead of INT 08, but some BIOSes do not issue an EOI for the timer
- ; until AFTER 1C is called, and you don't want to mess up the system clock...
- ;
- ; ENTRY: on timer tick
- ;
- ; EXIT: nothing
- ;
- ; DESTROYED: ALL PRESERVED
- ;
- ;------------------------------------------------------------------------------
- PFPROC TRAPPER08
- ASSUME ds:NOTHING,es:NOTHING
-
- PUSHF
- CALL DWORD PTR CS:[OLD08]
-
- CLI
-
- CMP CS:TryPop,FALSE ;Are we trying to pop up?
- JE C_OUT ;if not, leave now
-
- PUSHM <ES,BX> ;Is a DOS call in progress?
- LES BX,CS:InDOS
- CMP BPTR ES:[BX],0
- POPM <BX,ES>
-
- JE C_Invoke ;if not, then fire it up...
-
- C_OUT: IRET
-
- C_Invoke: MOV CS:TryPop,FALSE ;set the right flags...
- MOV CS:InPop,TRUE
- STI
- CALL START ;run the TSR...
- MOV CS:InPop,FALSE ;set some more flags...
- MOV CS:AllowPop,TRUE
- ;
- IRET ;and leave.
- ENDPROC
-
-
- PAGE
- ;******************************************************************************
- ; TRAPPER28 - Intercepts the DOS "console wait" loop
-
-
- ;
- ; This routine allows the TSR to be invoked during DOS console operations
- ; where the InDOS flag is set but it is actually safe to use any DOS function
- ; above 0CH.
- ;
- ; ENTRY: During DOS console operations
- ;
- ; EXIT: nothing
- ;
- ; DESTROYED: ALL PRESERVED
- ;
- ;------------------------------------------------------------------------------
- ASSUME ds:NOTHING,es:NOTHING
- PFPROC TRAPPER28
-
- CMP CS:TryPop,FALSE ;does the TSR want to pop up?
- JE C1_OUT ;if not, get out of here now
- MOV CS:TryPop,FALSE ;prevent re-entrant interrupts
- MOV CS:InPop,TRUE ;set the "in TSR" flag
- STI
- CALL START ;run it!
- CLI
- MOV CS:AllowPop,TRUE;finished, we can pop up again
- MOV CS:InPop,FALSE ;no longer running the TSR
- C1_OUT: JMP DWORD PTR CS:OLD28 ;continue down the console chain
- ENDPROC
-
-
- PAGE
- ;******************************************************************************
- ; TRAPPER69 - Chains to INT 69H so we can determine if the TSR's already here
- ;
- ; This routine provides a method of checking to see whether a copy of
- ; this TSR already exists in memory. This entry could also be used to
- ; reconfigure the resident portion of the program (i.e. to reset a clock,
- ; to add a file to a print queue... etc.)
- ;
- ; ENTRY: AX = 0ABCDH
- ;
- ; EXIT: If the TSR is already resident:
- ; AX = 0DCBAH
- ;
- ; If the TSR is NOT resident:
- ; AX = 0ABCDH
- ;
- ; DESTROYED: AX if resident
- ;
- ;------------------------------------------------------------------------------
- ASSUME ds:NOTHING,es:NOTHING
- PFPROC TRAPPER69
- ;
- CMP AX,0ABCDH ;Is it the correct function?
- JE CK_OURS ;yes, respond to it
- JMP DWORD PTR CS:OLD69
- CK_OURS: MOV AX,0DCBAH ;set return code
- IRET
- ENDPROC
-
-
- PAGE
-
-
- ;****************************************************************************
- ; UNLOAD - Unhooks all vectors and exits
- ;
- ; This routine removes the TSR from memory, if possible. The sequence
- ; of events is:
- ; a) a check is made to be sure that we are the LAST program in memory
- ; b) all vectors are unhooked
- ; c) the environment segment that DOS gave me is deallocated
- ; d) the current code segment is deallocated
- ; e) control is returned to whatever program was running before
- ;
- ; ENTRY: nothing
- ;
- ; EXIT: nothing
- ;
- ; DESTROYED: this program, hopefully
- ;
- ;----------------------------------------------------------------------------
- ASSUME ds:CODE,es:CODE
- PNPROC UNLOAD
-
- ;------------------------------------------------------------------------------
- ; see if there are active memory control blocks after mine
- ;------------------------------------------------------------------------------
- PUSH AX
- PUSH ES
- MOV AX,CS ;my MCB starts 1 seg before
- DEC AX ; my code seg
- MOV ES,AX
- ADD AX,ES:[0].MCB_LENGTH ;find out how long it is
- INC AX ;fiddle the value
- MOV ES,AX
- MOV AL,ES:[0].MCB_KIND ;what kind is the next MCB?
- CMP AL,m@LAST ;if it's not the last...
- POP ES
- POP AX
- JNZ BAD_UNLOAD ;...then leave now
- ;------------------------------------------------------------------------------
- ; unhook all the vectors
- ;------------------------------------------------------------------------------
- PUSH AX
- PUSH DX
- PUSH ES
- PUSH DS
- MOV AX,0
- MOV DS,AX
- @RESTORE_VECT 009H FROM OLD9 ;Restore keyboard vector
- @RESTORE_VECT 008H FROM OLD08 ;Restore timer vector
- @RESTORE_VECT 028H FROM OLD28 ;Restore console vector
- @RESTORE_VECT 069H FROM OLD69 ;Restore my TSR vector
- ;------------------------------------------------------------------------------
- ; deallocate everything
- ;------------------------------------------------------------------------------
- MOV ES,CS:ENVIRONMENTSEG
- MOV AH,049H ;de-allocate the environment
- INT 021H ; block
- PUSH CS
- POP ES
- MOV AH,049H ;de-allocate the code block
- INT 021H
-
-
- POP DS
- POP ES
- POP DX
- POP AX
- CLC
- RET
- ;------------------------------------------------------------------------------
- ;can't unload: memory control blocks after mine...
- ;------------------------------------------------------------------------------
- BAD_UNLOAD: STC
- RET
-
- ENDPROC
-
-
- PAGE
- ;****************************************************************************
- ; INSTALL - Installs traps, then runs the program.
- ;
- ; ENTRY: called on entry to the program
- ;
- ; EXIT: TSR's the main program and exits to DOS
- ;
- ; DESTROYED: ALL
- ;
- ;----------------------------------------------------------------------------
- ASSUME ds:CODE,es:CODE
- PNPROC INSTALL
- PUSH CS
- PUSH CS
- POP DS
- POP ES
- MOV CS:CODSEG,CS
- ;------------------------------------------------------------------------------
- ; see if this program is already in memory
- ;------------------------------------------------------------------------------
- MOV AX,0ABCDH
- INT 069H
- CMP AX,0DCBAH
- JNE NOT_THERE
- JMP ALREADY_THERE
- ;----------------------------------------------------------------------------
- ; install our keyboard hardware interrupt trap
- ;----------------------------------------------------------------------------
- NOT_THERE: MOV AllowPop,FALSE
- MOV TryPop,FALSE
- MOV AX,03400H ;get the InDOS flag's address
- INT 21H
- MOV WPTR CS:InDOS,BX ;...and save it
- MOV WPTR CS:InDOS[2],ES
- @CHANGE_VECT 009H TO TRAPPER9 SAVEIN OLD9
- @CHANGE_VECT 008H TO TRAPPER08 SAVEIN OLD08
- @CHANGE_VECT 028H TO TRAPPER28 SAVEIN OLD28
- @CHANGE_VECT 069H TO TRAPPER69 SAVEIN OLD69
- ;----------------------------------------------------------------------------
- ; print copyright notice
- ;----------------------------------------------------------------------------
- MOV AH,9
- MOV DX,OFFSET NOTICE
- INT 021H
-
-
- MOV CS:AllowPop,TRUE
- ;------------------------------------------------------------------------------
- ; calculate total program size and leave
- ;------------------------------------------------------------------------------
- TSR_OUT: MOV AX,03100H
- MOV DX,OFFSET INSTALL
- SHR DX,1
- SHR DX,1
- SHR DX,1
- SHR DX,1
- INC DX
- INT 021H
- ;------------------------------------------------------------------------------
- ; ERROR: program is already resident!
- ;------------------------------------------------------------------------------
- ALREADY_THERE: MOV AH,9
- MOV DX,OFFSET ALREADY
- INT 021H
- MOV AX,04C01H
- INT 021H
- ENDPROC
-
- ;==============================================================================
- ; DATA THAT'S ONLY USED DURING INSTALLATION
- ;
- ;
-
- NOTICE LABEL BYTE
- DB CR,LF
- DB 'Example TSR v1.0 Sun 03-19-1989',CR,LF
- DB 'Copyright (C) 1988 ORivation',CR,LF
- DB CR,LF
- DB 'Press LSHIFT-RSHIFT-T to execute',CR,LF,'$'
- ALREADY LABEL BYTE
- DB CR,LF,'The Example TSR is already installed!',7,CR,LF,'$'
-
- MAIN ENDP
- ;
- ;****************************************************************************
- ;
- CODE ENDS
- END ENTRY