Консультация № 105873
18.10.2007, 02:14
0.00 руб.
0 1 1
Уважаемые эксперты!!!
Помогите, пожалуйста, составить програму, которая бы выводила
на экран соджержимое всех ненулевых векторов прерываний. После
вызова пограма должна оставаться резидентной.
А вектор прерываний, которым инициализируется програма,
можно подобрать автоматически.
И если можно в коде програмы дайте небольшие объяснения насчёт
каких-либо функций или по ходу её решения.
Заранее благодарен!

Обсуждение

давно
Старший Модератор
31795
6196
22.10.2007, 21:13
общий
это ответ
Здравствуйте, Seryj!

Программа должна запускатся из командной строки.
Структуры MS-DOS использованые в программе:
-Таблица прерываний MS-DOS, занимает адреса от 0000:0000 до 0000:03FF,
на каждое прерывание отводится 4-е байта 1:2-смещение,3:4-сегмент прерывания.
Если это 9-е прерывание, ячейка памяти где находится адрес самого обработчика прерывания равна 0:36=4*9.
-0040:001А и 0040:001С -в этих ячейках записаны адреса начала и конца буфера клавиатуры, если значения записанные по этим адресам совпадают - клавиша не нажата.
-0040:0017 слово№ 1- состояния клавиатуры позволяют определить нажата ли спец-клавиша(CTRL, ALT или SHIFT), мы ищем CTRL.
-В строках: <font color=blue>c:=e^;
h:=ptr($40,c);
d:=h^;</font>
извлекается скан-код нажатой клавиши, для буквы "А" =1(после обработки ТР).
-программа будет сбоить под отладчиками, т.к. используется отдадочное преривание INT3(код:CCh)

Перед самым первым оператором программы выполняется загрузка подключаемых модулей. И первое, что делает модуль SYSTEM(загружаемый автоматически), это ставит свои обработчики прерываний, информацию о изменяемых прерываниях Вы найдете в помощи паскаля:SaveIntXX. Только по этой причине после нажатия <b>CTRL+A</b> и вывода информации появляется "^C".

Удачи!

Приложение:
program q105873;{&A-} Var b,c:word; d:char; e,f:^word;{указатели на переменную WORD} {перевод числа в 16-ю систему} function g(a:word):string; var b,c:integer; d:string; begin d:=‘‘; for b:=0 to 3 do begin c:=a mod 16; if c>9 then c:=c+39; d:=chr(c+48)+d; a:=a div 16; end; g:=d; end; {наш обработчик} procedure myInterrupt; interrupt; var h:^byte; d:byte; begin {прерывание INT3- один байт и без параметров, запускаем старый обработчик} InLine($cc); {получаем адрес начала и конца буфура клавиатуры} e:=ptr($40,$1a); f:=ptr($40,$1c); if e^<>f^ then begin {получаем состояние клавиатуры} h:=ptr($40,$17); d:=h^; {отделяем нажатие клавиши CTRL} d:=d mod 16; d:=d div 4; if d >0 then begin {получаем нажатую клавишу} c:=e^; h:=ptr($40,c); d:=h^; {нажата клавиша "А"} if d=1 then begin writeln; {перебираем все прерывания} for b:=0 to 255 do begin e:=ptr(0,4*b); f:=ptr(0,4*b+2); if(e^<>0)and(f^<>0)then write(‘ ‘,g(b),‘:=‘,g(f^),‘:‘,g(e^)); end; {записываем перевод строки} h^:=3;{команда перевода строки: ^C будет всегда в конце вывода} end; end; end; end; Begin {для процедуры Keep(), запоминаем сегмент стека и сегмент PSP} inline($1e/$16); {перебираем все прерывания} for b:=0 to 255 do begin {получаем смещение} f:=ptr(0,(b*4)); {получаем сегмент} e:=ptr(0,(b*4+2)); if (e^<>0)and(f^<>0)then write(‘ ‘,g(b),‘:=‘,g(e^),‘:‘,g(f^)); end; {GetIntVec(09)} {получаем обработчик клавиатуры} f:=ptr(0,36); b:=f^; {segment} f:=ptr(0,38); c:=f^; {SetIntVec(03)} {записываем старый обработчик на место прерывания INT3} f:=ptr(0,12); f^:=b; {segment} f:=ptr(0,14); f^:=c; {SetIntVec(09)} {записываем смещение нашего обработчика} c:=ofs(myInterrupt); f:=ptr(0,36); f^:=c; {и сегмент} c:=CSeg; f:=ptr(0,38); f^:=c; {аналог процедуры Keep(), но сделанный с помощью прерывания int 27 команды: 5A pop dx 58 pop ax 2B D0 sub dx,ax C1 E2 04 shl dx,4 81 C2 4000 add dx,4000h CD 27 int 27h и места меньше занимает} inline($5a/$58/$2b/$d0/$c1/$e2/$04/$81/$c2/0/$40/$cd/$27); end.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа