Oberon
#04
28 ноября 1997 |
|
Обо всём - как написать Boot длинной в 1 сектор (256 байт).
М.М.A/SPEED СО. Был на свете такой хороший полиграфический журнал "ZX-РЕВЮ" ..... Был, да как это ни прискорбно, но весь вышел! И на пепелище последнего его тиража, осталась неопубликованной статья, написанная мной и Максом Васильевым специально для этого издания. И хотя нижеследующий текст был набит ещё в первых числах 1997-го года, он не потерял той актуальности и остроты. Вот я и решил включить этот материал в свежий номер ОБЕ- РОН'а. Не пропадать же добру! Правда была одна маленькая проблем- ка....... Текст статьи написан языком "ZX-РЕВЮ" и для читателей "ZX-РЕВЮ". ес- тественно всё нужно было переделывать. Од- нако, поскольку перспектива полного пере- писывания статьи меня нисколько не прельщала, я решил оставить всё как есть. Итак, давайте "поскорбим" по безвременно ушедшему от нас НАСТОЯЩЕМУ спектрумовскому журналу - "ZX-РЕВЮ"! (C) MAXSOFT / SPEED СО. (C) М.М.A / SPEED СО. г.Самара 1997 а.d. ВООТ-программа в один сектор. Со времён первых компьютеров с системой TR-DOS , появившихся в нашей стране, хаккеры и програмисты не перестают решать великую проблему современности: зачем, как и какой boot-загрузчик написать ??? Тех, кто интересуется вопросом современного boot-остроения, я позволю себе отослать к статье, посвящённой именно этой теме, ко- торая была опубликована в третьем номере Самарского электронного журнала "ОБЕРОН". В настоящей же статье, на примере написа- ния boot-программы, мы рассмотрим вопросы реализации сверхкоротких программ на ас- семблере, а также возможность рацио- нального использования процедур стан- дартного ПЗУ и TR-DOS'а в подобных прог- раммах. Стоит отметить, что попытки создания сверхкоротких boot-загрузчиков уже были, и достаточно успешные. Например boot, напи- санный Shi-soft'ом в 1992-ом году занимал два сектора и вполне неплохо работал. Я принципиально не говорю о длине в байтах, так как в связи с использованием не кас- сетных носителей информации (дискеты, и как следствие, дисковые ОС, например TR-DOS), понятие длины программы в байтах, однозначно заменяется на понятие длины в секторах. И в случае, если ваша процедура имеет размер 260 байтов, а так же если она будет занимать 460 байтов, всё равно при записи на диск будет организован файл объёмом в два сектора. Таким образом, если ваша программа близко связана с DOS, имеет смысл выбрать предельный её размер, крат- ный размеру стандартного TR-DOS'овского сектора и в последствии стараться ис- пользовать каждый байт (бит) этого объёма памяти. Мы несколько отступили от темы, вернёмся к нашим boot'ам! Другой пример boot-заг- рузчика в два сектора - это программа Д.Пьянкова SMALL ВООТ,распространяемая ИН- ФОРКОМ'ом. Как пишется в описании на эту программу : "Основная особенность - малый объём (2 сектора), благодаря чему обеспе- чивается быстрая загрузка". Вполне очевид- но, что при размере в один сектор загрузка будет ещё быстрее, а места на диске такой boot вообще практически не занимает. Воп- лощением именно этой, абсолютно казалось бы безумной идеи и занялись сразу два са- марских программиста. Со времени возникновения этой идеи в моей (М.М.A) голове прошло уже около полутора лет. Так как в то время я был недостаточно опытен в программировании, то просто поде- лился мыслью о написании подобного шедевра с другими самарскими программистами. В ре- зультате, в жесткой конкурентной борьбе, односекторный boot был не просто написан, а написан настолько оптимально, что боюсь, читателям "ZX-РЕВЮ" уже не удастся что-ли- бо оптимизировать. Хотя, если не смотреть листинг, приведённый ниже, а попробовать реализовать эту идею, что называется с "чистого листа", то, возможно, вам, доро- гие читатели, удастся найти какие-либо но- вые, нестандартные решения. Другое дело - изменение функциональных особенностей... Полный дизассемблер boot'а с комментариями практически по каждой команде вы найдёте в конце статьи. Там же находится дамп boot'а и примечания по объединению кодового блока и BASIC'а. Мы же продолжим тему изменений и посмотрим, что и как можно поменять в этой (базовой) версии boot'а. В данной версии управление программой осуществляется с помощью SINCLAIR JOYSTICK'а и клавиш "Q","A","О","Р". Выбор файла - "0","ENTER", чтение нового катало- га - "SPACE". Как видно, управление от SINCLAIR джойстика несколько излишне и при желании вы можете его выкинуть и вставить что-либо другое. Например, неплохой эффект даст утолщённый шрифт! Хранить дополнительный символьный набор в памяти - это уже три сектора (768 байт), да и воспользоваться методиками создания шрифтов с использованием стандартного ПЗУ шрифта, не раз описанными в ZX-РЕВЮ, тоже нельзя - слишком много байтов! Решение должно быть нестандартным и одновременно простым. А что, если сначала напечатать на экране всё обычным шрифтом, а потом проде- лать над экраном следующую операцию: ORG 30000 LD HL,#4000 В HL- начальный адрес экрана LOOP1 LD А,(HL) Открываем цикл, грузим в A содержимое (HL) SRL A Сдвигаем A вправо (или SLA A - влево) OR (HL) Накладываем A на исходный байт в экране LD (HL),A Помещаем результат на экран INC HL Увеличиваем адрес в экране на единицу LD A,Н Загружаем в A значение Н, СР #58 и смотрим, не дошло ли оно до старшего разряда области атрибутов (#5800) JR NZ,LOOP1 Повторяем цикл, если HL < #5800 RET Листинг l В принципе, процедура на листинге l рабо- тоспособна, и занимает всего 14 байт. Но для сверхкороткого boot'а и этого много! Дальнейшее совершенствование процедуры мо- жет осуществляться путём изменения принци- па определения конца экранной области. Сам же алгоритм утолщения и так оптимален. ORG 30000 LD HL,#57FF В HL - самый последний байт экрана LOOP1 LD A,(HL) В А грузим содержимое (HL) RRCA Сдвигаем через RRCA (короче на один байт!) OR (HL) Накладываем на оригинал LD (HL),A Копируем обратно в экран DEC HL Уменьшаем HL ***** LD A,Н Проверяем содержимое Н на 0 OR A JR NZ,LOOP1 Если HL > #OOFF, то повторяем цикл RET Листинг 2 В данном случае отсчёт байтов идёт "снизу вверх",и не заканчивается на #4000, а про- ходит через всё ПЗУ (там,естественно,ниче- го не изменяется) и доходит до адреса #0100. Используя такой способ,мы экономим ещё два победных байта и получаем процеду- ру в 12 байт длиной. Некоторое неудобство заключается в том, что пока программа "идёт" через ПЗУ, тра- тится достаточно большое количество тактов процессора и пользователь начинает заме- чать, как вы утолщаете символы. C одной стороны это даже неплохо - получается очень интересный эффект, но если он вам кардинально не нравится, то попробуйте следующее: Сразу после команды DEC HL, помеченной в предыдущем листинге, наберите : BIT 6,Н Проверяем, установлен ли шестой бит в адресе, записанном в HL. Если установлен, то продолжаем цикл, иначе - выходим. JR NZ,LOOP1 RET Для понимания работы этого условия поясню, что все те адреса,которые могут находиться в регистре HL при работе с экраном, имеют выставленный шестой бит (#40 = %01000000), а начиная с адреса #ЗFFF ( #3F = %00111111) этот бит сброшен. По этому принципу и работает определение конца эк- ранной области. Байтов на этом мы не выиг- рали, но зато работает побыстрее, чем вер- сия с проверкой Н на 0. Но можно ли вооб- ще сэкономить ещё? Естественно, можно ! Посмотрите в комментарии к листингу boota. Там всё построено на том, что последующая процедура использует данные предыдущей. Если перед вызовом процедуры утолщения в регистре L будет находиться число #FF, то нам достаточно просто загрузить оставшуюся половинку регистра - Н. Поставьте в листинге 2 вместо LD HL,#57FF команду LD Н,#57 и не забудьте, что в ре- гистре L должно быть число #FF, оставлен- ное от предыдущей процедуры. Вот мы и по- лучили процедурку в 11 байтов - вполне нормально для нашего односекторного дети- ща. Вот только ситуация с регистром L не- понятная. Нужно ли вообще его загружать ? Если представить, что в регистре L к мо- менту старта процедуры находится абсолютно случайное число, то по окончании работы мы просто получим неутолщёнными от одного до #FF байтов в нижней трети экрана в нижней части каждого знакоместа! Но в ПЗУ-шном шрифте, насколько я помню, лишь запятая и некоторые символы используют нижнюю строку знакоместа. А так как эти символы в назва- нии файла вообще редко встречаются, то смело оставляем точно загруженным только регистр Н. ORG 30000 LD Н,#57 LOOP1 LD A,(HL) RRCA OR (HL) LD (HL),A DEC HL BIT 6,Н JR NZ,LOOP1 RET Вот она - оптимизированная версия утолще- ния всего экрана, которую вы, дорогие чи- татели, можете вставлять в наш односектор- ный boot вместо дополнительного управления от SINCLAIR - джойстика. Основной нашей целью было показать вам,как нужно размышлять при написании сверхком- пактного кода. К тому же мы хотим выбро- сить идею односекторного boot'а на мозго- вой штурм всей страны. В наших головах эта идея дошла уже до полного оптимума. Но мы будем очень рады, если кто-либо из читате- лей предложит что-то новое,интересное, от чего захочется, как в известной рекламе, сказать : "СВЕЖО...."! А вот и сам boot-загрузчик длиною в один сектор: ORG #5D3B AUTHOR EQU #5D52 FILE_Р EQU #5D52 ;BASIC СТРОКА ДЛЯ ЗАПУСКА DEFB #00,#01,#F8,#00,#Е7,#C3,#A7,#3A DEFB #F9,#C0,#В0,#22,#32,#33,#39,#30 DEFB #35,#22,#3A,#ЕА,#3A,#F7,#22 ;ИНФОРМАЦИЯ ОБ АВТОРЕ(НЕ МЕНЕЕ 8 СИМВОЛОВ) DEFB 23,11,32,"MAXSOFT'96" DEFB #22 ;КОНЕЦ BASIC-СТРОКИ DEFB #D ;"СВОБОДНЫЙ" БАЙТ ;1 SECTOR ВООТ ;IDEA ВУ М.М.A SOFT/SPEED СО. ;CODED ВУ MAXSOFT/SPEED СО. LD (IY+#53),#5 ;УСТАНОВКА ЦВЕТА PAPER В ЯЧЕЙКУ (#SC8D) ;BORDER УЖЕ УСТАНОВЛЕН ИЗ BASIC'A NEW_DISK ;ЗАЧИТЫВАНИЕ ДИСКА CALL #D6B ;ОЧИСТКА ЭКРАНА ;НА ВЫХОДЕ DE=#0000,HL=#50E0,ВС=#1721 ;ЗАГРУЖАЕМ КАТАЛОГ ДИСКА С АДРЕСА #6801 ADD HL,ВС LD ВС,#905 PUSH HL CALL #3D13 ;ПЕЧАТАЕМ ИНФОРМАЦИЮ ОБ АВТОРЕ LD DE,AUTHOR LD C,#D CALL #203C LD A,2 ;ОТКРЫВАЕМ ПОТОК ПЕЧАТИ НА ЭКРАН CALL #1601 РОР HL LD D,Н LD Е,L SORT ;СОРТИРОВКА КАТАЛОГА LD ВС,8 DEC (HL) JR Z,NEXT_F ;СTЁРTЫЙ ФАЙЛ INC (HL) JR Z,END_SORT ;КОНЕЦ КАТАЛОГА PUSH HL ADD HL,ВС LD A,(HL) РОР HL СР "В" ;ТИП ФАЙЛА JR NZ,NEXT_F PUSH HL LD A,#20 ;ПЕЧАТЬ "ПРОБЕЛа" RST #10 МАКЕ_FILE LD A,(HL) ;ПЕЧАТЬ RST #10 ;БУКВЫ LDI ;И ЕЁ ПЕРЕНОС JP РЕ,МАКЕ_FILE ;(ДЛЯ УПЛОТНЕНИЯ КАТАЛОГА) LD HL,#70D1 ;СЧЁТЧИК ФАЙЛОВ INC (HL) LD A,(HL) FILE_C SUB 3 ;ВЫЧИСЛЯЕМ, НАПЕЧАТАНО-ЛИ ;ТРИ ИМЕНИ ФАЙЛОВ В ОДНОЙ СТРОКЕ JR Z,FILE_C1 JR NC,FILE_C LD A,#20 ;НЕТ,НЕ НАПЕЧАТАНО RST #10 ;-ПЕЧАТЬ "ПРОБЕЛа" FILE_C1 ;ДА,НАПЕЧАТАНО LD A,#20 RST #10 РОР HL NEXT_F LD C,#10 ;ПЕРЕХОДИМ ADD HL,ВС ;К СЛЕДУЮЩЕМУ ФАЙЛУ JR SORT END_SORT ;КОНЕЦ СОРТИРОВКИ NEW_CUR ;РЕГИСТР В=0 LD C,В ;РЕГИСТР С-СЧЁТЧИК ФАЙЛОВ MOVE_CUR LD HL,#57F5 LD DE,#В XOR A ;РЕГИСТР A-ВРЕМЕННЫЙ СЧЁТЧИК MOVE_C1 LD В,3 MOVE_C2 ADD HL,DE ;ВЫЧИСЛЯЕМ ПОЗИЦИЮ КУРСОРА СР C JR Z,CURSOR INC A DJNZ MOVE_C2 DEC HL JR MOVE_C1 CURSOR ;РИСУЕМ КУРСОР LD В,#A LD DE,(#70D3) LD (#70D3),HL LD A,5 CURSOR1 LD (DE),A ;СТИРАЕМ СТАРЫЙ КУРСОР INC DE LD (HL),#16 ;РИСУЕМ НОВЫЙ КУРСОР INC HL DJNZ CURSOR1 LD HL,#5C08 ;ОБНУЛЯЕМ СИСТЕМНУЮ ПЕРЕМЕННУЮ (LAST-KEY) LD (HL),В KEYS ;ОПРОС КЛАВИШ LD A,(HL) СР " " ;ПРОБЕЛ-ПЕРЕЗAЧИTЫВAНИЕ ДИСКА JR Z,NEW_DISK СР #D ;ENTER-ЗАПУСК ПРОГРАММЫ JR Z,START_F СР "0" ;0-ЗАПУСК ПРОГРАММЫ JR Z,START_F СР "7" JR Z,L_RIGHT СР "6" JR Z,L__LEFT СР "8" JR Z,L__DOWN СР "9" JR Z,L____UP OR #20 ;ВКЛЮЧЕНИЕ ВЕРХНЕГО РЕГИСТРА ДЛЯ БУКВ ;ОПРОС БУКВЕННЫХ КЛАВИШ НЕЗАВИСИМО ОТ ;РЕЖИМА "CAPS" СР "р" JR Z,L_RIGHT СР "о" JR Z,L__LEFT СР "а" JR Z,L__DOWN СР "q" JR NZ,KEYS L____UP ;КУРСОР ВВЕРХ DEC C DEC C L__LEFT ;КУРСОР ВЛЕВО DEC C JP Р,MOVE_CUR ;КУРСОР НЕ ДОШЁЛ ДО НАЧАЛА КАТАЛОГА LD ВС,(#70D1) ;КУРСОР - НА КОНЕЦ КАТАЛОГА DEC C JR MOVE_CUR L__DOWN ;КУРСОР ВНИЗ INC C INC C L_RIGHT ;КУРСОР ВПРАВО INC C LD A,(#70D1) DEC A СР C JR NC,MOVE_CUR ;КУРСОР НЕ ДОШЁЛ ДО КОНЦА КАТАЛОГА JR NEW_CUR ;КУРСОР - НА НАЧАЛО КАТАЛОГА START_F ;ЗАПУСК ФАЙЛА LD A,C INC A LD C,L ;РЕГИСТР L=8 LD HL,#67F9 ;АДРЕС НАЧАЛА КАТАЛОГА МИНУС 8 ST_F1 ADD HL,ВС ;ВЫЧИСЛЯЕМ ПОЗИЦИЮ ИМЕНИ ФАЙЛА В КАТАЛОГЕ DEC A JR NZ,ST_F1 LD DE,FILE_Р ;ПЕРЕНОСИМ ИМЯ ФАЙЛА В BASIC LDIR JP #3D03 ;ВЫХОДИМ В BASIC С ЗАПУСКОМ ФАЙЛА Листинг 4 l. НАБРАТь ТЕКСТ ВООТ'A В АССЕМБЛЕРЕ. 2. ВЫЙТИ В BASIC. СТЕРЕТь ВСЕ BASIC-СТРО- КИ,ОТНОСЯЩИЕСЯ К АССЕМБЛЕРУ И СОЗДАТь СВОЮ СТРОЧКУ ДЛИНОЙ 248 БАЙТ,Т.Е. КО- МАНДА PRINT РЕЕК 23869 ДОЛЖНА ПОКАЗАТь 248.ПРИ ЭТОМ НЕЖЕЛАТЕЛьНО ИСПОЛьЗОВА- НИЕ РЕДАКТОРА BASIC 128. 3. ВЕРНУТьСЯ В АССЕМБЛЕР И ПРОИЗВЕСТИ АССЕМБЛИРОВАНИЕ. 4. ВЫЙТИ В BASIC И СОХРАНИТь BASIC-ПРОГ- РАММУ : RANDOMIZE USR 15619:REM:SAVE"1SBOOT"LINE 1 По поводу доработок и изменений. В базовой версии boot'а,приведённой в лис- tuhre 4. имеется 1 свободный байт. Его ис- пользование для дополнительных сервисных возможностей практически нереально. Зато реально попробовать сделать печать файлов не в три колонки, а в две, и тогда новые и новые освободившиеся байты откроют вам возможность ко всё новым и новым наворотам в пределах всё того же одного сектора дис- кового пространства. Вообще,если всё же окажется, что мы дос- таточно оптимизировали идею односекторных boot'ов, и читателям не удастся выкроить даже лишнего байта, то предлагаем устроить конкурс на самый удобный и мощный семисек- торный загрузчик. Такой boot очень удобен тем, что может быть расположен в неис- пользуемых секторах нулевого трека. В этом случае получается, что boot не занимает ни одного сектора на диске. К тому же, если в одно/двух-секторных boot-загрузчиках речь идёт только об обес- печении минимального сервиса, то в boot'ах длиной в семь секторов можно использовать и автозачитывание дисков и красивые эффек- ты на заднем плане (звезды,снег) и многое другое. Р.S. И главное, помните : "Любую процедуру можно дооптимизировать до такой степени. что она будет состоять из одной команды NOP и при этом выполнять всё. что от неё требуется". Вот такая хорошая была статья..... Однако, поскольку мы пубикуем её в электронном, а не бумажном журнале, есть возможность немного облегчить вам жизнь! В приложении к журналу вы найдёте две го- товых к употреблению версии "односектор- ного" boot'а: 1SBOOT_М (версия by MAXSOFT) и 1SBOOT_Р (версия by POLTERGEIST) Версия от MAXSOFT'а была подробно описана в прочитанной вами статье, а версия от POLTERGEISTA примерно тоже самое, но с другими функциональными особенностями. К тому же эта версия появилась несколько раньше и поэтому запрограммирована не- много иначе. Как? Разберётесь сами, когда дизассемблируете! Ну а для самых пытливых умов, на диске записанно два файла в формате редактора ZX-WORD: 1S_boot+.(листинг с комментариями) и 1S_boot-. (листинг без комментариев) Первый файл удобен для конвертирования в ассемблеры с редактором на 64 символа в строке и с поддержкой русского шрифта по альтернативной кодировке. Примером тако- го ассемблера является версия ALASM4X8, в то время как TASM х.хх хотя и поддер- живает 64 символа в строку, но "обламы- вается" на русских коментариях. Для всех тех, кто пользуется не ALASM'ом, предназначен второй листинг. В нём отсут- ствуют комментарии на русском языке и дли- на строки не превышает 42 символов. Этот файл можно непосредственно грузить в TASM 2.0, а с помощью опции Import Tasm2.0 и в ассемблеры TASM 3.XX, TASM 4.0 (XLD), TASM 4.XX (RST#7). Как конвертировать текст в другие типы ассемблеров, я надеюсь, вы разберётесь сами. Удачи! -════════════════════════════════════════- * * * * * MUSIC ВУ: VISUAL/MS/XTM
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября