[an error occurred while processing this directive]
.цв .шп2 ПЕРСОНАЛЬНАЯ ЭВМ 'АГАТ' СИСТЕМА ПРОГРАММИРОВАНИЯ : ========================================================= ЖЖЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖЖ ЖЖЖЖЖ ЖЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖЖЖ ЖЖЖЖЖЖЖЖЖЖ ЖЖЖЖЖЖЖЖЖ ЖЖЖ ЖЖЖ ЖЖЖЖЖЖЖЖ ЖЖЖЖЖ ЖЖЖЖЖЖЖЖ ========================================================= ( тонкости при программировании ) .кт---------------------------------------------------------------- .ов .сс
.шп2
1. РАСПРЕДЕЛЕНИЕ ОПЕРАТИВНОЙ ПАМЯТИ.
.шп0
1.1 Расположение программы в памяти.
Программа на Бейсике в памяти представляет набор кодов, которые заменяют операторы, переменные, текстовые и цифровые данные. На данный момент существует две версии интерпретатора языка которые имеют некоторые отличия. Первая версия - это штатный Бейсик или другое его название Бейсик-60. Вторая версия - это Бейсик в системе ИКП. Далее эти версии мы будем называть Бейсик-60 и Бейсик-ИКП соответственно.
Первое различие состоит в том, что при наборе программы или ее загрузке с диска начало программы лежит в разных областях памяти. В любом случаее Вы можете узнать где находится начало программы, если опросите ячейки памяти в которых находится адрес начала программы на бейсике (BADR). Это ячейки ¤67 и ¤68. В ячейке ¤68 находится старший байт начала программы, а в ячейке ¤67 - младший.
Конец программы на Бейсике можно узнать обратившись к ячейкам ¤AF и ¤B0 в которых находится конец программы. Причем в ячейке ¤b0 находится старший байт, а в ячейке ¤AF - младший.
Таким образом зная начало программы и конец программы мы сможем определить длинну программы в байтах. Для этого нужно проделать следующие вычисления:
PRINT (PEEK(¤B0*256)+PEEK(¤AF))-(PEEK(¤68*256)+PEEK(67))
На экране будет отпечатано число, которое соответствует длинне той программы на Бейсике, которая в данный момент находится в памяти.
Второе отличие состоит в текстовом окне включаемом при загрузке. В Бейсик-ИКП включается TEXT=2 который в памяти находится перед программой, а в Бейсик-60 включается TEXT=15 который находится в конце ОЗУ. Расположение текстового окна перед программой (Бейсик-ИКП) является очень большим преимуществом, о чем будет рассказано ниже. К сожалению в Бейсик-60 нельзя текстовое окно раположить перед программой.
+-------------------+--------------+------+--------------+ ! Версия Бейсика ! Адрес начала ! TEXT ! Адрес текста ! +-------------------+--------------+------+--------------+ ! Бейсик-60 ! ¤801 ! 15 ! ¤7800 ! ! Бейсик-ИКП ! ¤1901 ! 02 ! ¤1000 ! +-------------------+--------------+------+--------------+
1.2 Выделение максимального об'ема памяти под данные.
Для работы с максимальным количеством данных далеко не безразлично какие текстовые окна используются в процессе работы программы, а также какой об'ем памяти представляет та или иная версия Бейсика. Прежде всего отметим, что Бейсик-ИКП выделяет больше свободных ячеек памяти под программу и данные, чем Бейсик-60.
.сс
Теперь определимся с некоторыми понятиями, которыми мы будем пользоваться:
Видеопамять - это тот участок памяти, в котором мы ведем диалог, т.е. наше текстовое окно. Память программы - Это та память, которую занимают только коды программы на Бейсике. Память данных - это память которая отводится под переменные программы на Бейсике. Доступная память - это все те ячейки памяти, в которых мы можем расположить программу, данные и видеопамять.
Нужно отметить, что в Бейсик-ИКП текстовое окно (TEXT=2) не относится к доступной памяти. Поэтому если мы будем использовать TEXT=2 (цветной текст) и TEXT=50 (та же область память, но только нецветной текст), то в этом случае:
Память данных = Доступная память - память программы.
В Бейсик-60 все гораздо сложнее. Поскольку текстовое окно там располагается после программы, то оно захватывает часть доступной памяти, а именно 2048 (¤800) ячеек памяти. Но и это еще не вся беда. Взгляните на таблицу распределения доступной памяти:
------+-------------------+¤0800 ~ !///////////////////! ! ! Программа ////////! ! !///////////////////! ! +-------------------+ ---------------- Д ! ! ! ~ ~ о ! ! ! ! ! с ! ! ! ! ! т ! ! ! ! ! у ! ! ! ! ! п ! ! ! ! ! н ! ! ! ! Память1 ! а ! ! ! ! ! я ! ! ! ! ! ! ! ! ! ! Память данных п ! ! ! ! ! а ! ! ! ! ! м ! ! ! v ! я ! +-------------------+¤7800---- ! т ! !///////////////////! ! ь ! ! Текстовое окно ///! ! ! ! (TEXT=15) ////////! ! ! +-------------------+¤8000---- ! ! ! ! ~ ! ! ! ! ! Память2 ! ! ! ! ! ! v ! ! v v ------+-------------------+¤9600-------------
.сс
Все дело в том, что текстовое окно (видеопамять) лежит в области 'память данных', и когда программа начнет заполнять память данными, рано или поздно, но они начнут ложиться в видеопамять т.е. произойдет засорение текстового окна. Для того, чтобы текстовое окно не засорялось мы должны ограничить память данных там где лежит видео память, т.е. разбить память на память1 и память2 (см.таблицу). Но проблема в том, что Бейсик позволяет указать только один участок памяти под данные. В таком случае у нас не будет использоваться память1 или память2. Если из двух зол выбирать меньшее, то нам придется отказаться от памяти2 (она как правило всегда меньше памяти1), применив оператор Бейсика
.шп2;HIMEM:¤7800
.шп0
Теперь попробуем придумать что-нибудь, чтобы использовать память2. единственный выход это переместить текстовое окно так, чтобы оно не дробило память на два участка. Перенести текстовое окно (видеопамять) в конец памяти (ближе к ¤9600) мы не можем, т.к. этого не позволяет Бейсик и вообще в ПЭВМ АГАТ-7 это не возможно. Тогда остается перенести текстовое окно к концу программы. Но в связи с тем, что видеопамять может располагаться только в определенных адресах памяти (Приложение 1), мы не можем расположить видеопамять сразу за программой. Для того, чтобы узнать какое ближайшее к концу программы текстовое окно мы можем использовать, необходимо выполнить следующие действия:
PRINT INT(PEEK(¤B0)*256/¤800)+1
На экране отпечатается цифра (запомним эту цифру) которая будет соответствовать номеру текста который будет ближе всего к концу программы.
Теперь, чтобы видеопамять не засорялась нам в программе нужно указать границы памяти под данные. Для этого нужно в Приложении 1 найти значение на пересечении строки с номером текста (которы мы только что узнали) со столбцом 'Конец видеопамяти'. Эту цифру нужно указать в операторе LOMEM: , например, при выполнении оператора print (см. выше) нам бала выдана цифра '6'. Посмотрев в шестую строку Приложения 1, там где она пересекается со столбцом 'конец видеопамяти' мы увидели значение ¤3800. Это нижняя граница памяти. Верхняя граница конец доступной памяти т.е. ¤9600 (не забывайте, что мы говорим пока про Бейсик-60). Тогда в программе мы должны вставить соответствующие операторы :
.шп2;LOMEM:¤3800:HIMEM:¤9600 .
.шп0;
1.3 Операторы HIMEM: и LOMEM:
Синтаксис оператора:
.шп2
HIMEM:XXXX
.шп0; - верхняя граница памяти под переменные
LOMEM:YYYY
.шп0; - нижняя граница памяти под переменные
Здесь XXXX значение верхней, а YYYY - нижней границы памяти. Это значение может быть выражением, десятичной константой или шестнадцатеричной константой. Например: LOMEM:(5*2048) , HIMEM:10338 или HIMEM:¤3200 . При выполнении этих операторов, для обеспечения надежности работы программы должны учитываться некоторые особенности операторов:
1) значения ранее установленных переменных теряются;
2) в операторе lomem: нельзя увеличивать границу памяти;
3) в операторе himem: нельзя уменьшать границу памяти;
4) в программе эти операторы лучше использовать один раз;
5) располагать эти операторы нужно в начале программы.
Исходные значения (как при начальной загрузке) верхней и нижней границ памяти можно установить директовой FP . Но при этом необходимо помнить, что программа в памяти теряется. Нужно знать, что при запуске программы параметр LOMEM: принимается по умолчанию равным концу программы на Бейсике. Для версий Бейсика начальные значения верхней и нижней границ при загрузке системы (или при исполнении директивы FP) различные:
+-------------------+---------+---------+ ! Версия Бейсика ! Верхняя ! Нижняя ! ! ! граница ! граница ! +-------------------+---------+---------+ ! Бейсик-60 ! ¤9600 ! ¤0801 ! ! Бейсик-ИКП ! ¤C000 ! ¤1901 ! +-------------------+---------+---------+
.шп2
2. СТРУКТУРА ПРОГРАММЫ.
.шп0
2.1 Характеристики программы.
Прежде всего хочется отметить, что программа имеет определенные качества, такие, например: размер программы, скорость выполнения, надежность, удобство пользования, легкость чтения программы, графический дизайн и могие другие. Как правило скорость программы имеет зависимость от размера. Можно написать короткую программу, но она будет выполняться дольше, чем такая же, но более длинная. При этом не нужно забывать, что котороткая программа обычно, это не очень удобная в пользовании программа. Замечено, что в программе которая предоставляет пользователю максимум удобств, 50-60%% этой программы уходит на организацию этих удобств и дизайна. Учитывая все зарактеристики программист должен находить оптимальное соотношение между скоростью, длинной (а значит занримаемой памятью), удобством и дизайном. Если программа работает с огромными массивами, то для обеспечения надежности работы программы лучше пренебречь некоторыми (не играющими большой роли) удобствами, упростить графический дизайн или постараться сделать программу короче, но как правило приходиться сокращать все понемножку. Причем все меры сокращения программы желательно производить именно в том порядке в каком они перечислены.
2.2 Особенности выполнения программы.
На скорость выполнения программы, а значит и на ее структуру, сильно влияет то, как эту программу выполняет интерпретатор языка Бейсик. Рассмотрим как работает оператор GOTO (GOSUB). Встретив в программе строку '100 GOTO 15000' интерпретатор переходит к выполнению строки 15000, причем сначала он должен найти эту строку. Поиск строки осуществляется так, интерпретатор переходит к самой первой строке программы и проверяет 'это строка 15000?', если нет, то он переходит к следующей строке и производит аналогичную проверку, и т.д. до тех пор, пока он не найдет сторку 15000. Есть и еще одна деталь оператора GOTO (GOSUB). Код оператора занимает в памяти 1 байт, а следующий за ним номер столько байт сколько цифр в этом номере. Например, оператор GOSUB1 займет в памяти 2 байта, а оператор GOSUB15000 - 6 байт. Допустим, что у нас в программе есть сто операторов GOSUB15000, теперь если мы их заменим на оператор gosub1, а подпрограмму со строки 15000 перенесем в 1-ую строку, то мы высвободим (только этим переносом) 400 байт памяти.
.сс
Теперь должно быть понятно почему подпрограммы которы выполняются чаще всего необходимо размещать в начале программы, а операторы и подпрограммы которые выполняются один раз нужно разместить в конце программы. По этой же причине операторы DATA следует ставить в самый конец программы. То есть можно определить приближенное правило размещения подпрограмм и модулей: чем чаще подпрограмма выполняется тем ближе к началу программы она должна быть, и чем реже выполняется тем ближе к концу программы. Это накладывает отпечаток на структуру программы. Автор данной статьи не настаивает на абсолютной правильности но рекомендует следующую схему программы:
0 GOTO10000 ------------------- 1 подпрограммы частого применения 99 ------------------- 100 основные модули 999 ------------------- 1000 подпрограммы применяющиеся редко 9999 ------------------- 10000 начальные установки, одноразовые подпрограммы 10999 ------------------- 11000 списки операторов DATA 25000 -------------------
2.3 Стиль программы.
Здесь мы сразу оговоримся, что нужно различать понятия 'ситль программирования' и 'стиль программы'. Стиль программирования - это те приемы и та методика которую применяет каждый программист. Практически сколько программистов, столько и стилей программирования. Здесь уместно сравнить программиста с писателем. Стиль программы - это организация диалога с пользователем в программе, причем выполненная в едином стиле. Предположим нам нужно запросить у пользователя одну цифру. Организовать запрос можно многими способами. А теперь предположим, что в программе нам в разных местах нужно вводить одну цифру, и организацию ввода мы каждый раз будем делать по разному. Пользователю будет очень трудно привыкнуть и запомнить, что от него требуется, а если бы мы везде зделали одинаковый ввод цифры, то пользователь быстро бы привык к тому, что от него требуется.
.сс
Вот несколько различных способов организовать меню:
1) 1 - Каталог диска 2 - Переименовать файл 3 - Защитить файл 4 - Снять защиту 5 - Удалить файл 6 - Окончание работы
Причем в этом случае можно сделать так, чтобы пользователь нажимал нужную цифру, а затем клавишу 'ввод', а можно, чтобы пользователь нажимал только цифру без нажатия на клавишу 'ввод'.
2)
.шп2;К .шп0;аталог диска .шп2;П .шп0;ереименовать файл .шп2;З .шп0;ащитить файл .шп2;С .шп0;нять защиту .шп2;У .шп0;далить файл .шп2;О .шп0;кончание работы
Здесь работа меню построена на том, что пользователь должен нажать выделенную букву соответствующую нужному режиму (на экране эта буква выделяется цветом).
3) Каталог диска
.шп2;Переименовать файл .шп0;Защитить файл Снять защиту Удалить файл Окончание работы
Здесь выделенный режим на экране высвечивается инверсными символами, а все остальные режимы высвечиваются на экране нормальными символами. Управление меню производится стрелками вверх и вниз, а выбор режима клавишей 'ввод'.
По мнению автора если использовать в программе третий тип меню (управление стрелками), то пользоваться программой будет удобней, чем программами с меню первого или второго типов. Логика здесь простая. Для работы с третим типом меню нужны клавиши которые сосредоточены в одном месте, а значит управлять этим меню можно не глядя на клавиатуру и одной рукой. Для первого и второго типов меню тоже нужна одна рука, но перед тем как нажать на нужную клавишу во-первых сначала нужно найти эту клавишу, а затем перенести к ней руку. Все эти действия вызывают больше времени и приносят мало удовольствия.
Но здесь есть маленькое 'но'. Программа использующая третий тип меню будет немного длиннее, чем программа с первым или вторым типами меню. Это справедливо при использовании в программе одного меню. При использовании более одного меню, наоборот, становится выгодным третий тип меню (имеются ввиду те реализации которые предлагает автор).
.сс
Ниже мы приводим программы для всех трех типов меню. Как уже отмечалось это три основных и наиболее часто встречающихся типа меню. Программы которые приводит автор применялись во многих программах и имели великое множество вариантов. Здесь приводятся основные варианты меню. При желании их можно усложнить и дополнить. Это уже на Ваше усмотрение.
1) Первый тип меню.
0 GOTO100 100 HOME:VTAB12:RIBBON=2 105 HTAB6:?"1 - КАТАЛОГ ДИСКА":? 110 HTAB6:?"2 - ПЕРЕИМЕНОВАТЬ ФАЙЛ":? 115 HTAB6:?"3 - ЗАЩИТИТЬ ФАЙЛ":? 120 HTAB6:?"4 - СНЯТЬ ЗАЩИТУ":? 125 HTAB6:?"5 - УДАЛИТЬ ФАЙЛ":? 130 HTAB6:?"6 - ОКОНЧАНИЕ РАБОТЫ":? 135 GETA¤:A=VAL(A¤):IF A<1 OR A>6 THEN 135 140 ON A GOTO 200,300,400,500,600,700
Выше приведен пример меню выбор в котором происходит при нажатии только на клавишу с нужным номером, но в этом случае при организации работы программы нужно сделать так, чтобы пользователь при ошибочном нажатии на клавишу имел возможность вернуться в меню. Если потребуется организовать ввод так, чтобы после нажатия на клавишу нужного режима, пользователь нажимал клавишу 'ввод', то оператор GETA¤ в строке 135 нужно заменить на INPUT"";A¤.
2) второй тип меню.
0 GOTO10000 100 HOME:VTAB12:FOR I=ML TO MH:RIBBON=3:HTAB6 105 ?LEFT¤(M¤(I),1);:RIBBON=2:?RIGHT¤(M¤(I),LEN(M¤(I))-1) 110 ?:NEXT:A=0 115 GETA¤:FOR I=ML TO MH:IF A¤=LEFT(M¤(I),1) THEN A=I:I=6 120 NEXT:IF A=0 THEN 115 125 ON A GOTO 200,300,400,500,600,700 10000 ML=1:MH=6:FOR I=ML TO MH:READM¤(I):NEXT 10010 GOTO100 11000 DATA КАТАЛОГ ДИСКА 11010 DATA ПЕРЕИМЕНОВАТЬ ФАЙЛ 11020 DATA ЗАЩИТИТЬ ФАЙЛ 11030 DATA СНЯТЬ ЗАЩИТУ 11040 DATA УДАЛИТЬ ФАЙЛ 11050 data окончание работы
Этот вариант меню во всех версиях бейсика будет работать только при нажатии клавиш в русском регистре, а в Бейсик-ИКП, при этом нужно удерживать клавишу 'Рег'.
.сс
3) третий тип меню.
0 GOTO10000 30 N=PEEK(¤C000):IF N<128 THEN 30 31 POKE¤C010,0:RETURN 40 M=ML:RIBBON=2:FOR I=ML TO MH:VTABV(I):HTAB6:?M¤(I):NEXT 42 VTABV(M):HTAB6:INVERSE:RIBBON=3:?M¤(M):NORMAL:RIBBON=2 44 GOSUB30:?M¤(M):IF N=141 THEN RETURN 46 IF N=153 THEN M=M-1:IF M<ML THEN M=MH 48 IF N=154 THEN M=M+1:IF M>MH THEN M=ML 50 GOTO44 100 GOSUB40:ON M GOTO 200,300,400,500,600,700 10000 ML=1:MH=6 10010 FOR I=ML TO MH:READ M¤(I),V(I):NEXT 10020 GOTO100 11000 DATA КАТАЛОГ ДИСКА,12 11010 DATA ПЕРЕИМЕНОВАТЬ ФАЙЛ,14 11020 DATA ЗАЩИТИТЬ ФАЙЛ,16 11030 DATA СНЯТЬ ЗАЩИТУ,18 11040 DATA УДАЛИТЬ ФАЙЛ,20 11050 DATA ОКОНЧАНИЕ РАБОТЫ,22
.стbasic2
[an error occurred while processing this directive]