Информатика и технология программирования


Реентерабельность и проблемы резидентных программ в DOS - часть 7


if (sx[0]!='y') WAITDISK=-1;
printf("Синхронизация BIOS(y/n):"); scanf("%s",sx);
if (sx[0]!='y') WAITBIOS=-1;


SP+=NSTACK-10; //Вычисляем значение указателя внутреннего стека.


DS=SS=_DS; //Запоминаем значения сегментных регистров.


SIZE=(DS-_CS+0x10)+((unsigned)(malloc(200)) &#62&#62 4);
//Вычисляем размер резидента


printf("Объем резидента %d KB\n\r",SIZE &#62&#62 6);
rg.x.ax=0x5100; //Получить у DOS адрес PSP программы


intdos(&#38rg,&#38rg);
PSP=rg.x.bx;
rg.x.ax=0x3400; //Спросить у DOS адрес флага занятости DOS,


intdos(&#38rg,&#38rg); //который лежит в сегменте DOS.


DOSSEG=_ES; //Попутно запомнить адрес этого сегмента


DOSBUSY=rg.x.bx; //и адрес этого флага


PDOSBUSY=(char far*)MK_FP(DOSSEG,DOSBUSY);
//Собрать far указатели на флаг занятости DOS,


PSPADR=(unsigned far*)MK_FP(DOSSEG,0);
// и свой собственный PSP


while(1) //В этом цикле находим в сегменте DOS адрес


{ // идентификатора процесса (проще говоря,


// где DOS хранит адрес PSP текущего процесса).


if (*PSPADR==PSP)
{
rg.x.ax=0x5000;
rg.x.bx=PSP+1;
intdos(&#38rg,&#38rg);
i=(*PSPADR==(PSP+1));
rg.x.ax=0x5000;
rg.x.bx=PSP;
intdos(&#38rg,&#38rg);
if(i) break;
}
PSPADR++;
}
DTA=getdta(); //Читаем и запоминаем адрес своего DTA


KBSAV=getvect(0x9); //Переустанавливаем вектор прерывания


setvect(0x9,(void interrupt (far*)(...))KB);
TIMSAV=getvect(0x1C);
setvect(0x1C,(void interrupt (far*)(...))TIMER);
DOSOKSAV=getvect(0x28);
setvect(0x28,(void interrupt (far*)(...))DOSOK );
DISKSAV=getvect(0x13);
setvect(0x13,(void interrupt (far*)(...))BIOSDISK);
b=(unsigned far*)MK_FP(_psp,0x2C);
_ES=*b; //Освободить в памяти ENVIROMENT.


_AH=0x49;
geninterrupt(0x21);
keep(0,SIZE); // Выйти и остаться резидентным.


fatal: printf("Не хватает памяти\n");
} // А если были ошибки, то резидентным не оставаться




Начало  Назад  Вперед



Книжный магазин