Списки в оперативній пам'яті, операції над списками. Керування програмами. Керування таймером. Системні керуючі блоки. Управління пам’яттю: таблиця векторів переривань, страница 26

Оскільки адресація в файлі вказує на логічні адреса, то при завантажанні пограми в пам’ять відбувається налагодження адресації на реальний адрес за допомогою цієї таблиці елементами якої є  розміщення в файлі команди котра містить в собі  звернення до логічного адресу. Налагодження адресації відбувається шляхом додавання до адреса PID + 0x10. Програма для кожного елемнта знаходить слово, яке цей елемент адресує в опереативній пам’яті та в EXE файлі і виводить його на екран оба варіанти цього слова. В усіх випадках різниця між значеннями цього слова в пам’яті і в файлі повинна становити стартовий сегментний адрес програми.

Текст програми.

/*======== Обработка таблицы перемещений EXE-файла =====*/

#include <dos.h>

#include <string.h>

#include <stdlib.h>

#define byte unsigned char

#define word unsigned int

#define dword unsigned long

struct EXEH { /* заголовок EXE-файла */

  word ExeFlag, LastPag, PageCnt, ReloCnt, HdrSize, MinMem,

   MaxMem,ReloSS, ExeSP, ChkSum, ExeIP, ReloCS, TabOff,

   Overlay;  } exeh;

/* Элемент таблицы перемещений */

struct ReloItem {

  word offs;   /* смешение */

  word segm;   /* сегмент */

  } ri;

word psp,      /* сегм.адрес PSP */

     startseg, /* стартовый сегмент */

     reloseg,  /* сегмент модифицированного слова */

     d;        /* разность между памятью и файлом */

char fname[80],*fn; /* имя EXE-файла */

int exef;      /* дескриптор EXE-файла */

dword fileoff, /* адрес в файле начала модуля */

      itoff,   /* адрес в файле модиф.слова */

      seekoff; /* адрес в файле эл-та таблицы */

byte buff[10],         /* буфер в ОП */

     *s;

int i, ni;

union REGS rr;

struct SREGS sr;

main() {

  rr.h.ah=0x51; intdos(&rr,&rr); psp=rr.x.bx;

  for(fn=(char *)MK_FP(peek(psp,0x2C),0);*fn|*(fn+1);fn++);

  strcpy(fname,fn+4);

  if (strchr(fname,'.')==NULL) strcat(fname,".EXE");

  rr.h.ah=0x3d; rr.h.al=0; sr.ds=FP_SEG(fname);

  rr.x.dx=FP_OFF(fname); intdosx(&rr,&rr,&sr);

  if (rr.x.cflag) {

    printf("Невозможно открыть файл %s\n",fname); exit(0);

    }

  else exef=rr.x.ax;

  dread(&exeh,sizeof(struct EXEH));

  startseg=psp+0x10;

  printf("\nСтартовый сегмент = %04Xh\n",startseg);

  printf("Число элементов   = %d\n\n",exeh.ReloCnt);

  fileoff=exeh.HdrSize*16;

  for (seekoff=exeh.TabOff,ni=0; ni<exeh.ReloCnt; ni++) {

    dseek(seekoff);

    dread(&ri,sizeof(struct ReloItem));

    printf("Элемент перемещения #%d : %04X:%04X\n",

      ni+1,ri.segm,ri.offs);

    reloseg=startseg+ri.segm;

    s=(byte *)MK_FP(reloseg,ri.offs)-4;

    printf("      Память : %Fp -> ",s);

    d=*((word *)(s+4));

    prtmem(s);

    itoff=fileoff+ri.segm*16+ri.offs-4;

    dseek(itoff); 

    dread(buff,10);

    printf("      Файл   : %9ld -> ",itoff);

    d-=*((word *)(buff+4));

    prtmem(buff);

    printf("                           Разность = %04X\n",

      d);

    seekoff+=sizeof(struct ReloItem);

    if (getch()==27) exit(0);

    }

  }

dread(void *addr,int len) {

  rr.h.ah=0x3f; rr.x.bx=exef; rr.x.cx=len;

  sr.ds=FP_SEG(addr); rr.x.dx=FP_OFF(addr);

  intdosx(&rr,&rr,&sr);

  if (rr.x.cflag) { printf("Ошибка чтения %s\n"); exit(0); }

}

dseek(dword off) {

  rr.h.ah=0x42; rr.x.bx=exef; rr.h.al=0; rr.x.cx=off>>16;

  rr.x.dx=off&0xffff; intdos(&rr,&rr);

  if (rr.x.cflag) {  printf("Ошибка позиционирования\n");

     exit(0); }

}

prtmem(byte *a) {

 int i;

  for (i=0; i<10; i++) {

    if ((i==4)||(i==6)) printf("  "); printf("%02X",*(a++));

    }

  printf("\n");

 }

Результат виконання програми:

Стартовый сегмент = 055Fh

Число элементов   = 186

Элемент перемещения #1 : 0000:0001

      Память : 055F:FFFD -> 000000BA  3C08  2E891684

      Файл   :      1533 -> 000000BA  DD02  2E891684

                           Разность = 055F

Элемент перемещения #2 : 0000:005E

      Память : 055F:005A -> D22BEABF  3C08  8EC7268B

      Файл   :      1626 -> D22BEABF  DD02  8EC7268B

                           Разность = 055F