Sunteți pe pagina 1din 17

INDEX

1. INTRODUCTION
2. INTRODUCTION TO TSR.
3. MEMORY MODEL
4. THE C COMPILATION MODEL
5 PROGRAMS

Program 1 Write a TSR to trap the timer interrupt.


Program 2 Write a TSR which would change the colors of the screen in every 10 seconds
Program 3 Write a TSR for given condition: Picks up characters at random from the screen and
makes them fall down to the bottom of the screen
Program 4 Write a TSR to display the current time on the screen.
Program 5 Write TSR to display the name of every file that is opened when TSR is active
Program 6 Write a TSR which makes sure that anything that gets printed on the printer always comes
in capitals.
1. INTRODUCTION

TSR which give programming in C and C++ a Big and Wide Diversion and opens a new world of
Hackers and Crackers and normal programmers.

What are Hackers and what are Crackers.

1. Hackers are Programmers which are sitting on Pc's for a long time in trying to give world some
new and amazing. They are not like the one who destroys something but they are the one's who
invent new languages and utilities.Like Brian W kernighan and Denis M Ritiche were hackers
who invented C language in Bell Laborataries.
2. Crackers are the one whose sole intention is to enter in to some on'e security and delete files or
do some destructive works.
3. Normal Programmers are persons who just wanna know what are TSR and how to make a
normal TSR.
2. Introduction to TSR :

Programs which remain running and resident in memory while other programs are running are the
most exciting line of programming for many PC developers. This type of program is known as a
"Terminate and Stay Resident" or "TSR" program. eg. (Operating Doskey, etc.)

In theory a TSR is quite simple. It is an ordinary program which terminates not through the usual DOS
terminate function, but through the DOS "keep" function - interrupt 27h. This function reserves an
area of memory, used by the program so that no other programs will overwrite it. This in itself is not a
very difficult task, excepting that the program needs to tell DOS how much memory to leave it!

Basically to make a TSR program we have to decide which interrupt to catch. Poping a TSR means
that the code executes from the ashes ie. the code portion which we make resident and was not
responding is now to be executed.

In our TSR code first we have to capture the interrupt ie we have to get it's address where in the
memory it is stored then we have to replace the address with the address of our code and then within
our code we have to call the actual procedure after or before executing our code.

The difficulties in programming TSRs comes from the limitations of DOS which is not a multi-tasking
operating system, and does not react well to re-enterant code. That is it's own functions (interrupts)
calling themselves. The problems stem mainly from not being able to use DOS function calls within
the TSR program once it has "gone resident".

There are a few basic rules which help to clarify the problems encountered in programming TSRs:

1. Avoid DOS function calls

2. Monitor the DOS busy flag, when this flag is nonzero, DOS is executing an interrupt 21h function
and MUST NOT be disturbed!

3. Monitor interrupt 28h. This reveals when DOS is busy waiting for console input. At this time you
can disturb DOS regardless of the DOS busy flag setting.
4. Provide some way of checking whether the TSR is already loaded to prevent multiple copies
occuring in memory.

5. Remember that other TSR programs may be chained to interrupts, and so you must chain any
interrupt vectors that your program needs.

6. Your TSR program must use its own stack, and NOT that of the running process.

7. TSR programs must be compiled in a small memory model with stack checking turned off.

8. When control passes to your TSR program, it must tell DOS that the active process has changed.
3 MEMORY MODEL

Four registers are used to refer to four segments on the 16-bit x86 segmented memory architecture. DS
(data segment), CS (code segment), SS (stack segment), and ES (extra segment). A logical address on
this platform is written segment:offset, in hexadecimal. In real mode, in order to calculate the physical
address of a byte of memory, one left-shifts the contents of the appropriate register 4 bits, and then
adds the offset.

For example the logical address 7522:F139 yields the 20-bit physical address:

75220 + F139 = 84359

Note that this process leads to aliasing of memory, such that any given physical address may have
multiple logical representations. This makes comparison of pointers difficult.

Actually there are 3 types of pointers:


1) near
2) far
3) huge

Near Pointers: These pointers are 2 bytes long always i.e. any pointer that you declared normally they
are 2 bytes long. This permits only 2^16 values which implies that you can access only the code which
is in your data segment (since 1 segment is 64KB = 2^16). Any attempt to access data will result in
segment protection error from the OS.

Far and Huge Pointers: We take both these two since they are common and differ only when some
arithmetic is performed using these pointers.
Far and Huge pointers are both 4 bytes long. This means they can handle about 2^32= 2GB of memory
locations. Now since we don’t have that much amount of memory when we are real mode (when
computer starts up) we are safe since only 1MB is available (only 20 address lines available instead of
32 present address lines). We can access the whole of memory when we are in protected mode. This
mode gives the whole 2GB memory as a flat i.e. no segments are available when in protected mode.
But since we are in real mode our max memory limit is 1MB and our memory is fragmented into
different segments of 64Kb each in size.

To access any memory location in the 1MB limit we first find the starting address of the segment then
to this address (base address of segment) an offset of 16 bits is added. The way these addresses are
added is a bit tricky. First the segment’s address is left shifted by 4 bits (padded with 4 zeros in the
end) and then the offset is added to it. Now this is a full 20 bit address and processor use this address
to locate a memory location in the 1MB limit. The shifting need not be done by us since processor
does that for us we just need to supply the segment’s base address and an offset within that segment.

All segments starts at some multiple of 16 also called a paragraph boundary. This is because for each
16 bit segment address it is first left shifted by 4 bits ( 2^4=16 bytes).

One more thing where these pointers differ from each other is in the way they are stored. Far pointers
are not normalized while huge pointers are normalized. Normalization means that they have most part
of the address in the segment. This is not a problem if you will perform logical / arithmetic operations
on such pointers but if you do then using huge will benefit you since the results will be same as
expected while with far pointers you may get strange results. Huge pointer arithmetic is therefore more
complex which requires macros and thus slows down the performance.

Declaring far /huge pointers


The Turbo C provides us the keywords far and huge to declare such pointers. Just add these keywords
and declare these pointers like you normally do.

Example int far *ptr; (this ptr is a far pointer to an int)


int huge *ptr(this ptr is huge pointer to an int)

The Booting process of PC

When we push the start button of the PC many things are done. First a POST is done which checks the
computer for its resources after the check is performed the BIOS (Basic Input Output System) is given
the control. The earlier versions of BIOS used to come with BASIC loaded on them so in case an OS
is not found the BASIC used to run on the computer now this doesn’t happen and that’s why we see
Disk Error message when no OS is found.

The purpose of the BIOS is to make computer ready to support the OS so that is can start up. Its
purpose is to load the interrupt routines and start video output in text mode. The interrupt routines used
by BIOS are very basic and they don’t interpret the data its up to the OS getting loading to make use of
that data.

The interrupt service is loaded through an IVT (Interrupt Vector Table) this is done so that if any other
routine is required for some interrupt instead of the one provided by BIOS we just need to change the
values present in the vector table. This makes interrupt handling robust.

Interrupt Handling Process

Whenever an interrupt occurs the processor stops whatever it was doing and handles the interrupt.
Each interrupt (256 in total supported by Intel’s processors) has an entry in the IVT which is made by
BIOS. Each entry is 4 bytes long. Therefore whenever an interrupt occurs its number is multiplied by 4
to access the ISR location. These locations are located in the low memory area of the memory, thus to
have access to code outside of our segment we need to use far /huge pointers.

An ISR is just a module which replaces the entry currently in the IVT to itself. Since these modules
already present in the memory don’t have any names therefore the only way to access them is by use
of pointers to functions.
TC provides the keyword interrupt for writing ISR s. This keyword may be different on different
compilers and the code that we will compile is for REAL MODE only (16 bit code). For 32 bit code
we have to switch into protected mode which I don’t know myself yet. Also the IVT thing works only
in REAL MODE in protected mode this changes to IDT (Interrupt Descriptor Table) this is way 2
advanced to handle here.

Things that we need


TC 16 bit compiler (that IDE one)
Functions setvect() and getvect()
The functions setvect() and getvect() are both defined in dos.h. They provide a neat way to set the IVT
for an interrupt to our ISR.

Memory models

The memory models are:

Model Data Code


Tiny* near
small near** near
Medium near far
Compact far near
Large far far
Huge Huge Huge

* In the Tiny model, all four segment registers point to the same segment.

** In all models with near data pointers, SS equals DS.


4. The C Compilation Model
We will briefly highlight key features of the C Compilation model here.
Program 1

Write a TSR to trap the timer interrupt.

#include<dos.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<conio.h>
void interrupt our();
void interrupt (*prev)();
char far *scr=(char far*)0xB0008000L;
int ticks;
int i=67;
int j=0;
char str[]="BHAGYASHREE ";

void main()
{
prev=getvect(8);/*get the timer ISR address*/
setvect(8,our);/*set our function address*/
keep(0,500);
}
void interrupt our()
{
ticks++;
if(ticks==18)
{
*(scr+5*2)=str[j];
*(scr+72*2)=str[j];
*(scr+24*80*2+5*2)=str[j];
*(scr+24*80*2+72*2)=str[j++];
if(j==13)
j=0;
ticks=1;
}
(*prev)();/*call the actual ISR*/
}

OUTPUT:

Displays name starting from 'B' to 'E' and then again starting from 'B' at the top of screen at fifth
position
Program 2

Write a TSR which would change the colors of the screen in every 10 seconds.

#include<dos.h>
void interrupt our();
void interrupt (*prev)();
char far *scr=(char far*)0xB8000000L;
int ticks;
unsigned char color;
void main()
{
prev=getvect(8);/*get the timer ISR address*/
setvect(8,our);/*set our function address*/
keep(0,500);
}
void interrupt our()
{
int i;
ticks++;
if(ticks==182)
{
for(i=1;i<=3999;i=i+2)
*(scr+i)=color;
color++;
ticks=0;
}
(*prev)();
}

OUTPUT:
Color of screen changing in 10 second.
Program 3

Write a TSR for given condition: Picks up characters at random from the screen and makes
them fall down to the bottom of the screen.

#include<dos.h>
#include<stdlib.h>
#include<conio.h>
#include<stdio.h>
void interrupt our();
void interrupt (*prev)();
char far *scr=(char far*)0xB8000000L;
int ticks;
void main()
{
prev=getvect(8);/*get the timer ISR address*/
setvect(8,our);/*set our function address*/
keep(0,1000);
}
void interrupt our()
{
int col,row;
char far *v,ch;
ticks++;
if(ticks==91)
{
col=random(79);
row=random(24);
ch=*(scr+row*1600+col*20);
for(;row<=50;row++)
{
v=scr+row*160+col*2;
*(v-160)='b';
*v=ch;
delay(200);
}
ticks=0;
}
(*prev)();

}
Program 4

Write a TSR to display the current time on the screen.

#include<dos.h>
void interrupt(*prevtimer)();
void interrupt mytimer();
int running=0;
unsigned long far *time=(unsigned long far *)0x46C;
char far *scr;
char far *mode;
void main()
{
if((*mode & 0x30)==0x30)
scr=(char far *)0xB0000000;
else
scr=(char far *)0xB8000000;
prevtimer=getvect(8);
setvect(8,mytimer);
keep(0,1000);
}
void interrupt mytimer()
{
unsigned char hours,sec,min;
if(running==0)
{
running=1;
hours=(*time/65520);
min=(*time-hours*65520-min*1092)*10/182;
if(sec>=60)
{
sec-=60;
min++;
if(min==60)
{
min=0;
hours++;
if(hours==24)
hours=0;
}

}
writechar(48+hours/10,0,72,112);
writechar(48+hours%10,0,73,112);
writechar(':',0,74,112);
writechar(48+min/10,0,75,112);
writechar(48+min%10,0,76,112);
writechar(':',0,77,112);
writechar(48+sec/10,0,78,112);
writechar(48+sec%10,0,79,112);
running=0;
}
(*prevtimer)();
}
Program 5

Write TSR to display the name of every file that is opened when TSR is active.

#pragma inline
#include “dos.h”
Struct INTERRUPT
{
Unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,fi ;
};
Void interrupt(*prev)() ;
Void interrupt our(struct INTERRUPT);
Char filename[127];
char far *fname,far *scr=(char far *)0xB8000000L;
int i;
Main()
{
Prev = getvect(0x21);
Setvect(0x21,our);
Keep(0,1000);
}
Void interrupt our(struct INTERRUPT r)
{
If(_AH==0x3C || _AH==0x3D || _AH==0x4B)
{
Fname=MK_FP(r.ds,r.dx);
i=0;
while(filename[i++]=*fname++);
writestring(filename,10,10,240);
}
asm.pop bp;
asm.pop di;
asm.pop si;
asm.pop ds;
asm.pop es;
asm.pop dx;
asm.pop cx;
asm.pop bx;
asm.pop ax
asm jmp cs:_prev
}
Writestring(char *str,int row,int col,int attb)
{
While(*str)
{
Writechar(*str,row,col,attb);
Str++;
Col++;}
}
Writechar(char ch,int row,int col,int attb)
{
*(scr+row*160+col*2)=ch;
*(scr+row*160+col*2+1)=attb;
}
Program 6

Write a TSR which makes sure that anything that gets printed on the printer always comes in
capitals.

#include<dos.h>
Void interrupt(*prev)();
Void interrupt our();
Void main()
{
Prev = getvect(23);
Setvect(23,our);
Keep(0,1000);
}
Void interrupt our()
{
If(_AH==0)
{
if(_AL>=’a’ && _AL<=’z’)
_AL- = 32;
}
(*prev)();
}

S-ar putea să vă placă și