home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-05-21 | 45.4 KB | 1,170 lines |
-
-
-
-
-
- THE ASSEMBLY LANGUAGE "MAGAZINE" VOL 1 NUMBER 3
- May, 1989
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ## #### #### ####### ## ## ###### #### ## ##
- #### ## ## ## ## ## # ### ### ## ## ## ## ##
- ## ## ### ### ## # ####### ## ## ## ## ##
- ## ## ### ### #### ####### ##### ## ####
- ###### ### ### ## # ## # ## ## ## ## # ##
- ## ## ## ## ## ## ## # ## ## ## ## ## ## ##
- ## ## #### #### ####### ## ## ###### ####### ####
-
- #### ## ## ## #### ## ## ## #### #######
- ## #### ### ## ## ## ## ## #### ## ## ## #
- ## ## ## #### ## ## ## ## ## ## ## ## #
- ## ## ## ## #### ## ## ## ## ## ## ####
- ## # ###### ## ### ## ### ## ## ###### ## ### ## #
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
- ####### ## ## ## ## ##### ###### ## ## ##### #######
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Written by and for assembly language programmers.
-
-
-
-
-
-
- Table of Contents
-
- Table of Contents. . . . . . . . . . . . . . . . . . . . . . 2
-
- Editorial. . . . . . . . . . . . . . . . . . . . . . . . . . 3
-
- GUIDE LINES FOR CONTRIBUTORS . . . . . . . . . . . . . . . . 4
-
- Beginners'Corner . . . . . . . . . . . . . . . . . . . . . . 5
- Segmentation . . . . . . . . . . . . . . . . . . . . . . . 5
-
- Keyboard driven TSR programs.. . . . . . . . . . . . . . . . 7
-
- Hex Conversion Routines . . . . . . . . . . . . . . . . . . 12
-
- Book Reviews. . . . . . . . . . . . . . . . . . . . . . . . 14
-
- Source Code for Keyboard TSR. . . . . . . . . . . . . . . . 15
-
- Source for Soft Breakout. . . . . . . . . . . . . . . . . . 18
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 2
-
-
-
-
- Editorial
-
- This is the third issue of the Magazine, and the first with a
- major article from an outside contributor. Our thanks to Garrett
- Nievin.
-
- It is amazing how few programmers really appreciate
- the benefits of assembly language programming. Most of them under-
- stand that for certain parts of programs it can increase performance,
- but they have no real conception of the amount of improvement that it
- can make.
-
- As a common example of this-- The case of sprite
- manipulation. Some of the more speed conscious programmers are
- aware that to do clean writes to the CGA screen you need to wait
- for the retrace periods, but a C programmer cannot chase the
- electron beam around the screen to update it in areas that will
- not be affected until it again goes over it. This multiplies the
- time available to manipulate areas of the screen without flicker.
-
- Much of the time in executing a higher level routine is
- spent in calling it and returning from it. The indexed with of-
- fset stack operations are very costly in time. This is why even
- speedup assembly routines in high level code don't show the full
- capabilities as they are still called using the same conventions.
-
- One of the most touted buzz words today is "structured".
- This translates into using small easily controlled and understood
- subroutines with a single entry point and a single exit point
- having sharply limited function. This makes for a program that is
- quick and easy to write (regardless of the language) and quick to
- debug. These are all valuable attributes in a program, and if
- done right these same routines can be included in a large variety
- of dissimilar programs.
-
- There are those who say that any programmer who does not
- keep to "structured" programming is a bad programmer. At least in
- assembly language programming there are times and reasons for
- throwing this whole concept away. In doing so you create a
- program that is almost impossible to modify, totally unreadable,
- insane to debug, and a nightmare to try and document----BUT----you
- can also come close to cutting your size (already tiny compared to
- anything else) in half and have a good chance of a thirty percent
- increase in speed if you do it right. A program like that is not
- the product of a "bad" programmer, but of a very dedicated one.
- In such a program you don't have the time to waste making a lot of
- CALLS or doing variable storage or register adjustments. The num-
- ber of items that you must keep track of, mostly in your head,
- while writing makes it a project for only the best of programmers.
- I gave it up years ago, but still envy those who are able to make
- use of a powerful tool.
-
-
-
-
-
-
-
-
-
- ;page 3
-
-
-
- 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 re-
- quired 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, and to
- remove sections.
-
- Non-exclusive copyright must be given. No monetary compensa-
- tion 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 ex-
- ist. 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.
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 4
-
-
-
- Beginners'Corner
-
- Segmentation
-
- Segments are largely a carry over from the days when
- processors were all limited to a 16 bit address buss, but we still
- live with them today. They are not without some benefits however.
- The way they are treated in most of the books I am familiar with
- can leave the novice fear struck over the complexities and this is
- not necessary. They are nothing more ( to the assembly program-
- mer) than a tool that can either be used or discarded almost at
- will.
-
- The 8088 has 4 segment registers; CS, DS, ES, and SS. The
- complete address of a memory reference is the sum of the segment
- register (shifted 1 hex place to the left) and another register.
- Thus each location in memory can be accessed by many (up to 4096)
- combinations of segment and offset. For example segment 1000h,
- offset 1000 (generally written as 1000:1000) can also be addressed
- as 1001:0ff0, as the sum of both of these add up to 11000h. Each
- of the segment registers has another register that is hardware as-
- sociated with it but that can sometimes be overridden in the in-
- struction. The IP (instruction pointer) is firmly attached to the
- CS segment. The SP (stack pointer) always points to a location in
- the SS (stack segment). DI refers mainly to a location in ES
- as SI does to DS.
- In standard programming parlance there is the code
- segment, the stack segment, and the data segment written in
- various ways such as code_seg. High level language compilers
- insist on this division and MASM forces you to at least define
- them, but you should keep in mind that they are only conveniences
- and should be discarded when they cease to be convenient.
- In the following discussion I want to make a distinction
- between two types of data. The first is data that the program
- contains or uses as intermediate storage. This would include
- variables addressed in the code, messages to the user, and data
- buffers that operated on. The second type is external to the
- program. An example of this is a text file that your program will
- edit. Let me call the first type program data and the second type
- external data. The dividing line is very loose and often ceases
- to exist but it is a convenient fiction for now.
- The one unchangeable fact that we have to deal with is the
- way DOS loads the programs. There are two formats it can
- follow: the .COM format and the .EXE format. The COM format loads
- quickly because it is simply an image of the machine code and
- needs no processing by DOS in order to execute. It is limited in
- size to 64k, but I have never seen an assembly language program
- that was that large so it is really not much of a limit. All
- segment registers are set to the same value on loading (this
- value is the address of the PSP) and the IP
- is set at 100h.
- The EXE format is not limited to size but it requires post
- processing by DOS in order to work. This makes it slower to begin
- execution. This is also the format that is compatible with the
- source level debuggers. During linking the linker assigns segment
- offset values to each of the segments you define in your code.
- After loading DOS adds this offset value to each location in your
-
- ;page 5
-
-
- code that addresses a segment. This information is contained in a
- relocation table that the linker prepends to the file. Then DOS
- sets the CS register to the start of your code segment and the SS
- register to the start of your stack segment, and DS and ES to the
- start of the PSP. The IP is set to the offset specified in the END
- statement as the start of execution.
- Using either format you are still left with a mess to
- attend to. Your program data area is not defined or addressed,
- your stack is out of control (if .COM), and your program owns the entire
- address space in the computer from the start of your program to
- the end of memory. The first responsibility of any program is to
- clean this up. The methods of doing this are very simple and can
- be s standard header to all of your programs. I won't go into them
- now, but will try to cover them next issue. For now let's assume
- that you have attended to that and your whole program with code,
- stack and program data occupy a few thousand bytes above the
- PSP,and you have returned everything else to DOS. This is the
- ideal starting point for any program. Whatever other memory you
- need for external data can be requested from DOS and it knows how
- much is there and unused which your program doesn't. It will
- return to you the segment address of the block you requested. This
- then you can subdivide into as many segments as you like. For
- example: you are keeping a database of 10,000 names. Each name
- could be considered to be 2 segments long (32 characters) so you
- could move from name to name by adding 2 to the segment register
- you are using to address this space. Doing it this way frees you
- from the 64k limit you would have if instead you used one of the
- index registers and added 32 to it.
- This is a complex subject to try and explain, especially
- in a short column. More techniques will be discussed next issue.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 6
-
-
-
- A fool rambles about Keyboard driven TSR programs.
- by
- Garrett P. Nievin 4518 Valley Brook Dr. San Antonio, TX 78238
-
- o Introduction
-
- First of all, let me describe exactly how a keyboard driven TSR
- SHOULD work, to be a friendly inhabitant of your system. To me,
- there are two kinds of such programs: those which modify keyboard
- functioning (as in the case of Superkey), and those which merely
- check for keystrokes to activate a resident function (such as
- Sidekick). I will focus my discussion on the latter, but the
- basic principles apply to any keyboard TSR.
-
- o Narrative of how a friendly TSR handles the keyboard.
-
- To reliably and safely monitor the keyboard for a keypress, a
- program must install an interrupt handler for interrupt 9, which
- is hardware generated every time a key is pressed or released.
- For now let's assume we have a routine in memory and is the active
- interrupt 9 handler. Every time a key is pressed or released, our
- program automagically wakes up. The only affected registers are
- CS:IP, which point to where our program is executing of course.
- Our program should IN a byte from the keyboard port; this is the
- scancode which we have been summoned to service. Since the TSR
- program is only checking for a certain keyboard condition (such as
- an Alt-Q being hit), all other conditions should be ignored. If
- it is not "our" key, then we want to do nothing more. To relin-
- quish control, we do a long JMP to the old interrupt 9 handler
- (which may be BIOS ROM, or it may be another TSR. In this friend-
- ly manner, any number of TSR's may happily coexist). If it IS our
- key, we perform whatever action is appropriate, and terminate by
- one of two methods: jump to the old int handler, which allows the
- rest of the TSR's and/or BIOS to get at the same keypress; or,
- terminate the interrupt ourselves. This second method involves 3
- basic steps: 1) Tell the keyboard we have serviced his keypress
- 2) Tell the hardware interrupt controller we have serviced the
- hardware interrupt to completion and 3) perform and IRET (return
- from interrupt) instruction to continue with system processing.
-
- o How to read the keyboard
-
- The keyboard is driven by an 8048 chip, which is tied logically to
- the 8259A Peripheral Interrupt Controller (as level 1; only the
- timer interrupt at level 0 has more priority) and to the port A
- and port B of the 8255A-5 Programmable Peripheral Interface chip.
- I only give you these numbers to impress people with; that, and to
- get a little better understanding of what all happens. The scan
- code of a keypress gets placed in port A of the 8255, which is
- mapped to I/O port 60h of the CPU. All keypress scancodes will be
- in the range 01 (Escape) to 53h (Delete). If the high bit is set
- on, then it is not a keypress scancode, but a key release scan-
- code. These are usually ignored, but must be processed non-
- etheless.
-
-
-
- ;page 7
-
-
- Port A can be safely IN'd from any number of times before the
- keyboard is cleared; this is done by getting port B (IN AL,61h),
- set the hi bit on (OR AL,80h) and outing it back to port B. Once
- the keyboard is cleared, you usually want to tell the 8259 PIC
- that the interrupt you've been servicing has been completed by
- outing 20h to port 20h. The 8259 prioritizes all interrupts, and
- this command tells it that the highest priority interrupt is
- finished; this is neat because all the interrupt handlers don't
- have to know what level interrupt they are.
-
- Now comes the obvious question: How are we going to check for 2
- keys, as in the case of say Alt Q? BIOS makes this one easy. In
- the BIOS/DOS data area (segment 40), at bytes 17h and 18h, we find
- information on which special keys are being pressed. The sig-
- nificant bits are:
-
- 17h xxxxXXXX 18h XXXXxxxx 1 Alt is being pressed 1 Insert
- is being pressed 1 Ctrl 1 Caps Lock 1 Left shift 1 Num
- Lock 1 Right shift 1 Scroll Lock
-
- All we do is wait for the scancode of Q to come up. Then we check
- the appropriate bit in the appropriate flag byte (in the case of
- alt, we would test 0040:0017h for 08h). If the bit is on, we do
- our thing. Otherwise we just pass control on to the next in-
- terrupt handler in the string with our long JMP. NOTE: always
- use a "normal" key as a "wakeup call"; that is, don't check for
- combos like ALT-Rshift. There are too many programs already that
- do this, and programs employing these keys are difficult to chan-
- ge, thereby ensuring incompatibilities. In fact, if you dis-
- tribute your program and don't offer some means of "hot key" con-
- figuration, you may want to tell your users where your scan codes
- are located in the program so they may patch them themselves to
- avoid incompatibilities. Hint: use a CMP and not a TEST to check
- this byte, or if you are looking for ctrl-A then ctrl-alt-A,
- ctrl-shift-A, etc. will all mistakenly trigger your interrupt.
-
- o How to install the TSR
-
- The installation program will consist of 3 parts really: the jump
- around the interrupt handler code to the install code, and the in-
- terrupt and install code areas. The install code should do basi-
- cally two things: install the interrupt handler using service 25h
- of interrupt 21h (DOS call), and of course
- terminate and-stay-resident. To do the install, load AX with 2509h
- (AL has the interrupt number) and DS:DX with the address of the
- interrupt handler code, and do an int 21h. Your program is RIGHT
- NOW the new interrupt 9 handler. Then, load AX with 3100h and do
- an int 21h again (Terminate and stay res and return an err code of
- 00 to parent). At this point the handler is working, in memory,
- and control is released back to the parent program (in most cases
- Command.com).
-
- Here is our opportunity to start getting fancy. To keep memory
- usage to a minimum, we should do a DOS service 4Ah to release all
- unneeded memory.
-
-
-
- ;page 8
-
-
- /* UPDATE: I don't know what I was thinking here, but
- that's wrong. You don't use service 4Ah in a TSR; it
- would do nothing. What you DO do is load the number of
- paragraphs you need to keep into the DX register when you do
- your service 31h call. The way I get that is to use:
- ((last_address-first_address)/16)+1 (to div by 16 just shift
- right 4 bits) And don't forget to allow room for your PSP! */
-
- To REALLY cut down on the memory, we can relocate our program
- backwards into the unused PSP area, saving something like 164
- bytes. Also, we can leave a memory signature so that the user is
- not allowed to install the TSR more than once. My usual method of
- this is pretty simplistic. I put 4 unique bytes into the TSR it-
- self, and then upon installation check if those bytes are there.
- If so, the installation aborts and the user is told. The flaw
- here is that it only prevents the same program being installed
- after itself. If such a TSR is loaded and takes int 9, another
- one is later loaded and takes int 9 also, the program could then
- be installed for the second time. I know how my system is con-
- figured, so this is no problem. To a novice user getting hold of
- one of my programs, this will at best just waste a little memory.
- At worst, the system can get a little weird. To more securely
- guard against re-installation, you may take another interrupt vec-
- tor (there are 256, after all, and only a couple dozen are used in
- a basic PC). The way that works is: search for an empty in-
- terrupt vector (one which has all zeros), and take one when you
- find it. Save a memory signature there. When the program in-
- stalls the TSR code, search the interrupt vectors for your memory
- signature. If you find it, you know your program is there al-
- ready. Much safer. (Aside: For my personal use, I combine all
- my TSR's into one program. This saves memory, time, and trouble.
- It also keeps me from installing TSR's in between one another!)
-
- o What you can get away with in a TSR
-
- If you have read this far, I assume you don't already know all
- this. So, I will not go into all the undocumented MS-DOS services
- for TSR writers. If you are interested in them, I suggest you
- check back issues of magazines like Programmer's Journal and Dr.
- Dobb's. Anyway, you are restricted as to what can happen inside a
- TSR. It all boils down to one thing: MS-DOS is not reentrant.
- It is not meant to be multitasking (under programs like DoubleDos,
- there are copies of DOS for each task running), and so a routine
- can not be called while it is already executing for somebody else.
- Here is a scenario: You are saving a document from your word
- processor, and during the wait call up a TSR to find a phone num-
- ber or something. The TSR does a disk read of your phone # file.
- The TSR finishes and exits back to the word processor. Now, the
- WP's disk write has been interrupted, losing vital information
- like where on the disk he was writing, etc. MS-DOS goes awry. It
- is time for the big red switch, and kiss your document adios.
- Hope your disk is not messed up as well.
-
- There is the why of all this, now here is the what. A TSR may not
- use any DOS int 21h services higher than 0Ch. It is restricted to
- console and printer I/O services. (Now, this is of course not
- TOTALLY true, but how to do disk I/O etc. are beyond the scope of
- this little rambling. Maybe some other time.)
-
- ;page 9
-
-
- /* UPDATE Okay, here's how to do anything you please from
- within a TSR, including disk I/O. The BEST way is to install
- interrupt "front-end" handlers for int 13h (BIOS disk I/O),
- int 21h (DOS), int 25h (absolute disk read), int 26h (absolute
- disk write), and I think that's all. In these front-end hand-
- lers, set a flag (or semaphore or TS byte or whatever you want
- to call it) whenever anyone is in the middle of a disk I/O.
- Then, in your TSR, don't do a disk I/O if any of these flags
- are set. You will also need to steal the user timer tick in-
- terrupt (1Ch) to periodically check for when those interrupts
- are free for use. Or, you can use the cheater way (which is
- used by DOS itself): Whenever DOS is waiting for a keypress,
- it calls int 28h (undocumented). The only program I know of
- "legally" using this is the PRINT command. Whenever int 28h
- is called, you should be free to do whatever you want. If you
- want more immediate access to the disk, though, you'll need to
- use the timer int (1Ch) again. ONCE, at initialization time,
- do an int 21h ah=34h. In ES:BX, you will have the address of
- a byte called INDOS by most folks. This is an undocumented
- function which has been officially declared off-limits by
- Microsoft, but nobody pays attention to them anyway. As far
- as I know, it works fine in all versions of MS-DOS as of today
- (April 1988). In your timer interrupt servicer, read the byte
- at the address you got from service 34h. If it's not zero,
- don't do anything over service 0ch; if it's zero, go crazy.
- What this byte is (I'm told) is a count of how many calls deep
- DOS is into itself. The actual value is of no relevance to
- us, just if it is zero or not. Now, I don't see this helping
- much if the program is doing BIOS I/O, but I don't use any
- software I know of which uses BIOS for disk I/O. Also, if the
- application is doing direct-to-the-hardware disk I/O, I don't
- think you probably want to be messing with this stuff. Again,
- I don't use anything that I know of doing this.
-
- I've written several programs using the int 28h/service 34h combo
- to do TSR disk I/O and have never had a single problem, and I
- tested them in the middle of all kinds of disk accesses. This
- does not mean it's always cool, though. If you can help it, al-
- ways avoid undocumented stuff. In my opinion, Microsoft won't
- change it because so much software relies on it now, but I've
- learned not to trust them.
-
- o Example program complete with flimsy excuses
-
- The Sperry PC has a high-res graphics screen which is treated as a
- logically different display from the normal text screen, and uses
- different display memory banks. The text bank, called screen A,
- can be superimposed over the graphics (called screen B) on the
- screen simultaneously. This program switches between screen A on-
- ly, screen B only, and screen A superimposed on screen B. This
- program is for example only, and you should not attempt to run it
- on a CGA. If something gets fried, it's not my fault. It looks
- for a keypress of Alt-Esc, goes into action, and then quits.
-
-
- I hope this has been helped you understand how a basic keyboard
- driven TSR works. If you have any more questions, feel free to
- contact me with them, and I will find you an answer. Most ad-
- vanced TSR functions (almost all are undocumented by Microsoft and
-
- ;page 10
-
-
- IBM!) have been discussed in Byte, PC Tech Journal, and Dr.
- Dobb's Journal, but have been thoroughly discussed in Programmer's
- Journal. I highly recommend this publication, and hope more
- people will subscribe, so it does not fold up and deprive me of
- all the information it provides.
-
-
- Call the Telstar BBS: (512)822-8882 for a good time
-
-
-
-
- Garrett P. Nievin has also contributed a piece of code to service a
- soft breakout switch for Symdeb and Debug. Please see the listing in
- the source code section. Both of these are extremely well commented
- and should be quite useful.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 11
-
-
-
- Hex Conversion Routines
-
- Just a little "quicky" to fill out this issue. These are a
- couple of routines that I use regularly in a variety of ways. They are
- both fast and fairly tightly coded and they work. I hope you find them
- of some use.
-
- The first, DECHEX, takes an ASCII number pointed to by SI and
- returns a hex number in AX. The other just reverses the process, and
- when used with the little MOV_ASCII puts it where you tell it to.
-
- ;~
- DECHEX: ;THIS ROUTINE WILL TAKE A [CL] (MAX 5) DIGIT
- ;ASCII DECIMAL NUMBER POINTED TO BY SI AND
- ;RETURN A 4 DIGIT HEX NUMBER IN AX.*
- XOR DH,DH
- XOR AX,AX
- TRY: CMP CL,1
- JBE LASTA
- MOV DL,[SI]
- SUB DL,"0"
- ADD AX,DX
- MOV BX,AX
- SHL AX,1
- SHL AX,1
- SHL AX,1
- ADD AX,BX
- ADD AX,BX
- INC SI
- LOOP TRY
- LASTA: MOV DL,[SI]
- SUB DX,"0"
- ADD AX,DX
- RET
-
-
- HEXDEC: ;THIS ROUTINE WILL TAKE A 4DIGIT HEXADECIMAL NUMBER IN AX AND
- ;RETURNS A 5 DIGIT ASCII IN BH,BL,DH,DL,AL.
- ;TIME AVERAGES ABOUT 140 CLOCKS PER DIGIT
- ;LEADING 0'S ARE SUPRESSED
- MOV BX,0
- MOV CX,0
- MOV DX,0
- A10K: CMP AX,10000
- JB A1K
- SUB AX,10000
- INC BH
- JMP A10K
- A1K: CMP AX,1000
- JB HUNDREDS
- SUB AX,1000
- INC BL
- JMP A1K
- HUNDREDS: CMP AX,100
- JB TENS
- SUB AX,100
- INC DH
- JMP HUNDREDS
- ;page 12
-
-
- TENS: CMP AX,10
- JB UNITS
- SUB AX,10
- INC DL
- JMP TENS
- UNITS:
- MOV AH,'0'
- ADD BH,AH
- ADD BL,AH
- ADD DH,AH
- ADD DL,AH
- ADD AL,AH
- CMP BH,AH
- JNZ UEND
- MOV BH,020H
- U1:
- CMP BL,AH
- JNZ UEND
- CMP BH,020H
- JNZ UEND
- MOV BL,020H
- CMP DH,AH
- JNZ UEND
- CMP BL,020
- JNZ UEND
- MOV DH,020H
- CMP DL,AH
- JNZ UEND
- CMP DH,020
- JNZ UEND
- MOV DL,020H
- UEND:
- RET
-
- MOV_ASCII: ;THIS TAKES THE DIGITS PRODUCED BY
- ;HEXDEC AND PUTS THEM AT DS:SI
- MOV [SI],BH
- INC SI
- MOV [SI],BL
- INC SI
- MOV [SI],DH
- INC SI
- MOV [SI],DL
- INC SI
- MOV [SI],AL
- RET
- ;~
-
-
-
-
-
-
-
-
-
-
-
- ;page 13
-
-
- Book Reviews
-
- The Programmers' Reference
-
- I made a quick review of this last month, but I have since
- gone over it thoroughly and received the extended package from the
- author. This is NOT an instruction book for beginners. It is
- just what it names itself- a reference manual.
- The shareware version is 10 chapters (about 600k bytes) of
- solid information and a table of contents. Much of the information
- is very difficult to find elsewhere. The first chapter is a quick
- history of DOS from 1.0 to 4.0. Chapter 2 has the Port addresses
- and the Interrupts up to 0fh. Chapter 3 has the true Bios
- interrupts 10h to 1fh and it throws in INT 20h for some strange
- reason. This isn't just a listing that you might find in many
- places, but a detailed description with calling conventions and
- special things to watch out for. It includes semi-documented
- functions such as all of the Desqview and Topview int patches that
- go into this area. Each interrupt lists what machines it is
- included in from Tandy to PCjr to PS-2 model 80. I haven't counted
- them, but there must be thousands.
- The DOS interrupts 20h through 4fh are covered in similar
- detail, with many notes and application information.
- Further chapters contain information on file structures,
- EMS memory, and many other topics.
- The registered version gives another disk full of
- miscellaneous data that is rare and useful.
- The $15 price is one of the greatest bargains to be found.
- Available on many BBS's as ####ref.??? such as 1029ref.zip. This
- says that it is the October 29th release, and the extension is up
- to the Sysop.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 14
-
-
- Source Code for Keyboard TSR
-
-
- ; High Res screen A/B toggler for Sperry PC, the best PC around
- ; Written for MASM 4.0
- code segment para public 'code'
- assume cs:code,ds:code,es:code
- org 0100h ; .COM format
- start proc far
-
- ; Equates - ports, locations, values
- ; Using equates makes the program much easier to change later;
- ; to use a different scancode here, for example, you would just
- ; change the equate for "esc".
- if1 ; only assemble equates on pass 1
- portB equ 61h ; 8259 port B - used to clear scancode
- keyport equ 60h ; 8259 port A - keyboard scan codes
- esc equ 01h ; scan code for Escape key
- hibiton equ 80h ; hi bit on for keybreak scan code & reset
- hibitof equ 7fh ; hi bit off for keybd reset
- DOS_area equ 40h ; segment of BIOS/DOS data area
- shftstat equ 17h ; keybd shft status flag in DOS area
- shift equ 00000011b ; value for shftstat meaning either shift is on
- eoi equ 20h ; end of interrupt flag
- comdport equ 20h ; 8259 command port
- endif
-
- begcode:
- jmp implant ; jump around interrupt handler code
- begres: ; area to remain core resident
-
- rescode proc ; keystroke causes jump to resident code here
-
- jmp oversign ; jump over memory signature
- db 'abGN' ; program signature in memory
- ; I use my initials in uppercase and a 2-byte program ID in lowercase
-
- ; Variables
-
- mode db 0 ; superimpose mode: 0-A,1-B,2-Both,3-None
- oldint9 dw 0,0 ; doubleword value of old int9 vector
-
- oversign: ; start of code for new interrupt 09h handler
-
- push ax ; save that register
- push ds ; save DS.
- mov ax,DOS_area ; DOS data segment
- mov ds,ax ; now covered by DS
- test byte ptr ds:[shftstat],shift ; is a shift being held now?
- jz normal ; nope, not a hot key, pass it on to old int
- in al,keyport ; yes, get keyboard scan code
- cmp al,esc+hibiton ; was it release of escape?
- je abnorm ; yes, lose that scan code
- cmp al,esc ; was it an escape?
- jne normal ; nope, skip the important stuff
- ;
- mov al,mode ; get mode
- cmp al,2h ; both screens on?
-
- ;page 15
-
-
- je aonly ; yes, go back to first
- add al,1h ; add 1 to hi nybble to go B to A to AB
- jmp nextmode ; and go put it back
- aonly: ; start back with screen A only
- xor al,al ; turn off
- nextmode: ; put in new mode and quit
- mov mode,al ; move in new mode
- mov ah,15h ; set superimpose mode function of int 10h
- int 10h ; and go change mode
- jmp abnorm ; lose scan code
- ;
-
- abnorm: ; abnormal handling of scan code. to the bit bucket with it.
- in al,portB ; get portB
- or al,hibiton ; set acknowledge / clear keyboard bit
- out portB,al ; and out it again
- and al,hibitof ; clear ack bit
- out portB,al ; out that, enabling keyboard again
- cli ; no interruptions please, Mrs. a-Whiggins
- mov al,eoi ; end-of-interrupt command
- out comdport,al ; send it to the 8259
- pop ds ; restore
- pop ax ; registers
- sti ; interruptable again
- iret ; quit without performing normal interrupt
-
- normal: ; not hot key, pass scan code on to normal (maybe) int9
- pop ds ; restore all
- pop ax ; registers I messed with
- jmp dword ptr cs:oldint9 ; goto old int9 handler
-
-
- ; all code from here out is based on Norton's guide, and I use it in
- ; all my TSR's.
-
- reslen equ endres - begres ; length of new resident code
- strtres equ begres - begcode + 100h ; start of resident code
- psplen equ 5ch ; length of necessary PSP
-
- implant: ; code to put new int 9 front end in core
- mov ax,3509h ; get int vector function
- int 21h ; get vector of interrupt 9 handler
- cmp es:[bx+3],'ba' ; am I already loaded?
- jne fresh ; nope, go install
- cmp es:[bx+5],'NG' ; make sure I'm not already in
- jne fresh ; naaah, go install
- lea dx,cs:stalemsg ; DX points to already installed message
- mov ah,09h ; DOS display string func
- int 21h ; go display message
- int 20h ; and quit
-
- fresh:
- lea dx,cs:instlmsg ; DX points to installation message
- mov ah,09h ; display string function
- int 21h ; give the user the poop
- mov ax,3509h ; get int vector function
- int 21h ; get vector of old interrupt 9 handler
- mov oldint9,bx ; int location in ES:BX, save it
- ;page 16
-
-
- mov oldint9+2,es ; "
- mov ax,2509h ; set new interrupt 9 vector to me
- mov dx,offset rescode ; address of which is in DX
- int 21h ; go do it
- push cs ; DS and ES both end
- pop es ; up pointing at
- push cs ; code area
- pop ds ; "
- mov di,psplen ; where program will end up
- mov si,strtres ; start of resident code
- mov cx,reslen ; amount of resident code to move
- cld ; go forward in move
- rep movsb ; move code back in mem
- mov dx,psplen + reslen ; DX pointing to next free paragraph
- mov ax,3100h ; keep, return code of 0
- int 21h ; terminate
-
- stalemsg db 'Screen A/B toggle is already installed and active!',13,10,7,7
- instlmsg db 'High Res Screen A/B toggle',13,10
- db 'Shift/Escape toggles screen A only, then B only, then A/B.'
- db 13,10,'$'
-
- start endp
- code ends
- end start
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ;page 17
-
-
- Source for Soft Breakout
-
-
- ; BUGOUT.COM
- ; Program to add wimpy "soft" breakout key to DEBUG and SYMDEB
- ;
- ; MASM compatible source code
- ;
- ; Hitting the '5' on keypad forces an int 3 (debug breakpoint)
- ; After breakpoint, add 1 to IP register and trace through IRET
- ;
- ; By Garrett P. Nievin
- ;
- ; (BTW, to add a hardware breakout switch just put a switch between
- ; pins 17 (NMI) and 40 (+5V) on your 8088 chip, and a switch between
- ; pins 21 (RESET) and 40 will do a system reset/reboot.)
-
-
- code segment para public 'code'
- assume cs:code,ds:nothing,es:nothing
- org 0100h
-
- hotkey equ 4ch ; scan code for hot key = "5" on keypad
- portA equ 60h ; 8255A port A, usually keybd scan code
- portB equ 61h ; 8255A port B, various switches
- release equ 80h ; hi bit in scan code means key release
- hibiton equ 80h ; hi bit in byte for or'ing in
- hbitoff equ 7fh ; hi bit in byte for and'ing out
-
- start proc far
- begcode:
- jmp implant ; jump around interrupt handler code
- begres: ; area to remain core resident
- rescode proc ; keystroke causes jump to here
- jmp over ; jump over memory signature
- db 'bcGN' ; program signature in memory
- over: ;
- sti ; allow interrupts
- push ax ; save that register
- in al,portA ; get keyboard scan code
- cmp al,hotkey ; hotkey?
- jne normal ; yes, go hanlit
- push dx ; save register
- mov dx,0020h ; port 20h = PIC port to send EOI to
- mov al,dl ; 20h turns on EOI bit
- out dx,al ; tell interrupt controller we be done
- pop dx ; restore register
- in al,portB ; get portB
- or al,hibiton ; set acknowledge / clear keyboard bit
- out portB,al ; and out it again
- and al,hbitoff ; clear ack bit
- out portB,al ; out that, enabling keyboard again
- pop ax ; restore original register
- int 3 ;
- iret ;
-
- ;page 18
-
-
- normal: ;
- pop ax ; restore that register
- jmp dword ptr cs:oldint9 ; goto old int9 handler
- oldint9 dw 0,0 ; doubleword value of old int9 vector
- rescode endp
-
- endres: ; end of core res area
-
- reslen equ endres - begres ; length of new resident code
- strtres equ begres - begcode + 100h ; start of resident code
- psplen equ 5ch ; length of necessary PSP
-
- implant: ; code to put new int 9 front end in core
- mov ax,3509h ; get int vector function
- int 21h ; get vector of interrupt 9 handler
- cmp es:[bx+3],'cb' ; already loaded?
- jne fresh ; nope, go install
- cmp es:[bx+5],'NG' ; make sure
- jne fresh ; naaah, go install
- lea dx,cs:stalemsg ; DX points to already installed message
- mov ah,09h ; DOS display string func
- int 21h ; go display message
- mov ax,4cffh ; terminate with code = 0xff
- int 21h ;
-
- fresh:
- lea dx,cs:instlmsg ; DX points to installation message
- mov ah,09h ; display string function
- int 21h ; give the user the poop
- mov ax,3509h ; get int vector function
- int 21h ; get vector of old interrupt 9 handler
- mov oldint9,bx ; int location in ES:BX, save it
- mov oldint9+2,es ; "
- mov ax,2509h ; set new interrupt 9 vector to me
- mov dx,offset rescode ; address of which is in DX
- int 21h ; go do it
- push cs ; DS and ES both end
- pop es ; up pointing at
- push cs ; code area
- pop ds ; "
- mov di,psplen ; where program will end up
- mov si,strtres ; start of resident code
- mov cx,reslen ; amount of resident code to move
- cld ; go forward in move
- rep movsb ; move code back in mem
- mov dx,psplen + reslen ; DX pointing to next free paragraph
- mov ax,3100h ; keep, return code of 0
- int 21h ; terminate
- stalemsg db 'Bugout already resident.',10,13,7,'$'
- instlmsg db 'Bugout loaded and active, keypad-5 is break key.',10,13,'$'
- start endp
- code ends
- end start
-
-
-
-
-
- ;page 19
-
-