Оскільки адресація в файлі вказує на логічні адреса, то при завантажанні пограми в пам’ять відбувається налагодження адресації на реальний адрес за допомогою цієї таблиці елементами якої є розміщення в файлі команди котра містить в собі звернення до логічного адресу. Налагодження адресації відбувається шляхом додавання до адреса 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
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.