ЕЩЕ РАЗ О НАБОЛЕВШЕМ Я уже писал подобную статью раньше, но, к сожалению, отправил ее в фидошную эху ZX.SPECTRUM, откуда получил только критику и никакого позитивного результата. Теперь я повторюсь, но уже на экранах этого e-zina. Надеюсь, его авторитетные экраны и авторы добавят убедительности моим советам. Многим эти советы показались и снова покажутся неактуальными или неважными, но суть в том, чтобы выслушать и по возможности воспринять их. Пункт 1 -> Проблема вектора прерываний Всем известно, что для эффективного создания любой программы нужно использовать прерывание IM2, но иногда используют не совсем верный способ установки этих прерываний. Заранее прошу извинения за повторение прописных истин, но для некоторых эти истины не до конца прописаны. Так вот, в классическом виде установка прерываний IM2 происходит следующим путём: а) создание таблицы прерываний; б) установка указателя на подпрограмму прерывания; в) запрещение текущих прерываний; г) установка нового вектора таблицы прерываний; д) переход в режим IM2; е) разрешение уже вновь установленных прерываний IM2. В этом месте, конечно, многие скажут: "Да, все верно, так это и происходит" - но некоторые "экономы" сразу заметят то, что они пропускают один или несколько из вышеперечисленных шагов. Сразу проясню, что же происходит, если не совсем корректно установить прерывания IM2. Все достаточно просто: в момент возникновения самого прерывания, переход программы происходит не совсем в ту подпрограмму, которая задумана, и даже вовсе в случайное место памяти. Главный нюанс всей проблемы в том, что это происходит далеко не на всех компьютерах и не всегда одинаково. А суть этого кроется в не совсем отлаженной плате компьютера, как правило, самопального. Решение же этой проблемы заключается в правильном способе установки в своей программе прерывания IM2, и тогда на любом, самом трухлявом Пентагоне, все будет нормально работать. Приведу для примера кусок программы, правильно ставящей IM2, и если кто-то не хочет углубляться далее в эту проблему, просто скопируйте этот участок себе в код. LD HL,#BE00 LD DE,#BE01 LD BC,#1BF LD A,H LD (HL),C LDIR LD (HL),#C3 LD HL,MY_INT_ROUTINE LD (#BFC0),HL DI LD I,A IM 2 EI .... Здесь мы задействуем под прерывание IM2 области памяти: #BE00..#BF01 и #BFBF..#BFC1. По сути, этот участок и есть классическая установка IM2. Чаще всего некоторым кодерам не хочется жертвовать 257-ю байтами для полной таблицы прерываний, и они устанавливают указатель таблицы в различные места - кто куда придумает, в основном им полюбилась область ПЗУ, из-за этого обычно и происходят фатальные зависы их программ у некоторых юзеров. Вот вам первый постулат: * Нежелательно устанавливать вектор прерываний вне области памяти #8000..#BF00. В области памяти #4000..#7f00 или #C000..#FF00 не стоит ставить вектор таблицы, поскольку на многих компьютерах с медленной памятью по этим адресам как раз и располагается эта самая медленная память. Фатальных глюков не происходит, но сама программа может работать заторможено. А в области памяти #0000..#3F00 вообще лучше никогда не ставить вектор таблицы, поскольку там невозможно создать нормальную таблицу прерываний. А вот второй постулат: * При создании самой таблицы прерываний корректнее всего заполнить всю таблицу (257 байт) одним и тем же значением. Это, пожалуй, самое злосчастное место, ведь используя таблицу из ПЗУ (т.е. заполненную мусором), или не заполняя её в ОЗУ, вы тем самым допускаете вероятность перехода процессора в ложное место памяти, ведь никто со 100% вероятностью вам не гарантировал, что переход происходит только по 2 последним байтам (включая Клайва). Т.е. я не говорю, что подобное явление носит массовый характер, но, судя по нашему городу, могу утверждать, что с этим часто сталкивались многие. Когда спек был больше распостранён, да и программ делали больше, это явление встречалось часто, т.е. то у кого-то одно не работает, то у другого другое. Сейчас могу точно сказать, что у одного из четырех спектрумистов, знакомых мне (включая меня :), не работает ни одна из программ, с хреновой таблицей прерываний. У меня, по странному капризу моего Пентагона, подобные программы могут проработать довольно долго, но кончают все одинаково - сбросом через некоторое время. Напоследок приведу свой способ установки прерываний IM2, который мне кажется удобней: Где-то в начале программы: ORG #8000 DEFS 257,#81 ; в ALASMe заполняет 257 байт кодом #81 .... ORG #8181 DI ; INTERRUPT ROUTINE EI RET .... ENTRY: .... DI LD A,#80 LD I,A IM 2 EI .... Таким образом таблица и сопутствующие действия происходят на этапе трансляции программы, что избавляет вас от лишних действий, к тому же вы как бы включаете таблицу в размер программы, тем самым заранее соглашаетесь с лишними занятыми 257-ю байтами, которые на самом деле никогда не были решающими. Кстати, нетрудно заметить, что по адресу #8101 получаются 128 свободных байт, которые можно использовать как ячейки для переменных. Необходимо добавить, что если в конце вашей программы нужно передать управление системе, то лучше сделать это следующим способом: DI LD A,#3F LD I,A IM 1 RET (оооох ! чуть не написал rts ;-) Почему это стоит делать именно таким образом, читайте далее. Пункт 2 -> Вектор прерываний и TR-DOS. Создав правильную таблицу прерываний IM2 согласно советам предыдущего пункта, вы ещё не до конца освобождаетесь от потенциальных проблем с прерываниями. Если вы захотите вдруг в середине программы, где уже работает ваше прерывание IM2, загрузить что-нибудь с диска, то обычно используете для этого подпрограммы TR-DOS. Мы сейчас не рассматриваем загрузчики с включенными прерываниями IM2, это уже рассматривалось в различных статьях. Следующий комментарий в равной степени будет относиться и к стандартной работе с TR-DOS через #3D13, и к часто используемым быстрым загрузчикам (через прямой вызов низкоуровневых подпрограмм работы с ВГ93). Перед работой с TR-DOS многие отключают музыку и прерывания посредством команды DI. Как показывает грустная практика, этого недостаточно, особенно при использовании низкоуровневых подпрограмм TR-DOS. Другими словами, перед вызовом любой подпрограммы TR-DOS лучше перейти в режим прерывания IM1 c вектором #3F: DI LD A,#3F LD I,A IM 1 CALL TR-DOS Эта проблема очень похожа на описанную в предыдущем пункте, но здесь уже происходит конфликт между ВГ93 и процом. Особо не углубляясь в детали, советую использовать приведенную конструкцию для доступа в TR-DOS. При использовании быстрых загрузчиков с использованием низкоуровневых вызовов TR-DOS хватит лишь добавления IM1/#3F в начало цикла счета секторов для загрузки или записи. Пункт 3 -> Опрос клавиатуры. Предполагаю, что к этому пункту вряд ли прислушаются, но не могу не поведать о такой проблеме, как опрос клавиатуры. Я думаю многие не понаслышке знакомы с таким понятием, как дребезг клавиатуры. Я с ним вплотную познакомился именно на Пентагоне. Другими словами, при не очень удачном коде опроса клавиатуры хрен чего наберешь потом. Сразу могу однозначно сказать, что самый лучший способ опросить клавиатуру для набора какого-либо текста... это использовать подпрограмму в ПЗУ Бейсика 48. Многие могут мне возразить, что, мол, нам не пристало пользоваться подпрограммами ПЗУ, мы, мол, сами все можем написать. Но опять же грустная практика показала, что самая удачная подпрограмма опроса именно для набора текста - это ПЗУшная подпрограмма из обработки прерывания IM1. Можно ее, конечно, просто скопировать оттуда, но не проще ли сделать RST#38?! Я использую ее следующем образом : XOR A LD (23560),A LD IY,#5C3A RST #38 Этот участок располагаю внутри моего прерывания IM2. Такой способ конечно не отличается большой скоростью выполнения, однако он очень короткий и главное - довольно безглючный. Последнюю нажатую клавишу затем можно получить в любом месте программы из ячейки по адресу 23560. Дополнительную информацию про такой опрос клавиатуры можно получить из различных справочных книг по спеку. Всю эту, на первый взгляд, ересь для продвинутого кодера я рассказываю не случайно. Дело в том, что проблема всплывает в различных случаях, когда самые корректные с виду подпрограммы опроса клавиатуры начинают барахлить. Это имеет место по различным причинам, в частности: а) при использовании конроллера пц-клавы; б) при изменении каких-то внутренних характеристик компа (обычно Пентагона, будь он неладен) - как правило при старение железа; в) турбирование проца. Опять же отмечу, что это происходит редко, однако эти прискорбные случае были много раз зафиксированы мною в нашем регионе. Ну и, как вы уже догадались, единственная программа, которая выдержала проверку по глючности, - это именно подпрограмма опроса в ПЗУ Бейсика 48. Честно скажу, так и не понял, что в ней магического, может, потому, что она именно в ПЗУ расположена, а может, и по нескольким особенностям сразу, только она практически никогда не глючит. Если вы просто хотите опросить несколько клавиш на предмет нажатости, то хороший способ - воспользоваться командой IN A,(C), а не IN A,(254). Другими словами, чтение из порта клавиатуры с помощью пары BC происходит надежнее, видимо, вследствие технологической особенности Z80. Все эти рекомендации многим могут показаться странными, но все это проверено на собственном опыте. Практическое применение этих методик вы можете найти в нашей последней игре FARSPACE (для CC01), если залезете туда STS-ом. :) fyrex@klax.tula.ru ---------------------------------------------------------------- by Fyrex/Mayhem (c) Buzz 2002