20 DIM DB%(DBL%) 30 FOR I%==0 TO DBL% 40 DB%(I%)=INT(RND(1)*100) 50 NEXT 60 GOSUB 200 'DRUCK DER AUSGANGSDATENFOLGE 70 REM SORTIERUNG AM PLATZ 80 DBH%=DBL% 90 FLAG%=1 100 WWHILE FLAG% 110 FOR I%=DBH%-1 TO 0 STEP -1 120 IF DB%(I%) > DB%(DBH%) THEN SWAP DB%(I%), DB%(DBH%) 130 NEXT 140 DBH%=DBH%-1 150 IF DBH%=0 THEN FLAG%=0 160 WEND 170 PRINT 180 GOSUB 200 'DRUCK DER SORTIERFOLGE 190 END 200 REM UNTERPROGRAMM 210 FOR I%=0 TO DBL% 220 PRINT DB%(I%); 230 NEXT 240 RETURN RUN 24 30 31 51 5 78 49 36 98 90 5 24 30 31 36 49 51 78 90 98 OK Указание: Для компилятора языка Бейсик допускается статическое вложение циклов WHILE-WEND, т.к. каждому оператору WHILE должен соответствовать оператор WEND. 11. Безусловные и условные программные разветвления в языке Бейсик. 11.1. Оператор GOTO для реализации программных переходов (безусловные программные переходы) С помощью оператора GOTO может быть изменена нормальная последовательность выполнения строк программы. Формат: GOTO <номер строки> после оператора GOTO программа продолжается со строки, указанной с помощью <номера строки>. Пример: 10 DATA 2,4,6 20 READ Z% 30 PRINT "Z%="; Z% 40 GOTO 10 RUN Z%=2 Z%=4 Z%=6 OUT OF DATA IN 10 Указание: С точки зрения стиля программирования, построенного на основе современных достижений технологии программирования, следует сильно ограничивать использование оператора GOTO. В общем случае он должен действовать только в направлении "конец программы". Остальные случаи использования должны быть исключениями, которых следует избегать в каждом коллективе программистов. Оператор GOTO может быть с пользой применен для того, чтобы в длинных программах облегчить процесс записи накопленных текстов программ. Для этого, ниже строки с номером, который заведомо больше самогобольшого номера строки программы, подлежащей вводу, следует запрограммировать следующий оператор: 60000 SAVE "B:TESTPROG.BAS" Всегда, когда необходимо произвести запись в память в режиме настольной эвм (без номера строки), происходит переход на строку 60000: GOTO 60000 Далее следует активация оператора SAVE. 11.2. Операторы IF, THEN, и ELSE для реализации условных переходов. Кодовым словом IF начинается условный оператор (неполный или полный). Формат: IF <выражение> GOTO <номер строки> [ELSE <последовательность операторов>] или IF <выражение> THEN <последовательность операторов> [[,] ELSE <последовательность операторов> <последовательность операторов> = <оператор>=[:<оператор>] или <последовательность операторов> = <номер строки> Условный оператор должен умещаться в (логической) Бейсик-строке, т.е. условный оператор может иметь максимум 255 знаков. В качестве <выражения> может быть логическое или числовое выражение. Если логическое выражение иммет значение "истина", или числовое выражение отличется от нуля, выполняются опереторы, стоящие в ветви GOTO или THEN. Во всех других случаях выполняются операторы, стоящие в строке после оператора ELSE отсутствует (неполный условный оператор), то выполняется следующая строка программы. <Последовательность операторов> это последовательность выполняемых операторов языка Бейсик, которые разделены с помощью ":", или номер строки. Допускается вложение условных операторов. Примеры: 10 IF A%=3 THEN PRINT B% 20 IF (A%=0) OR NOT (B%=4) THEN C%=5 ELSE GOTO 50 30 IF A% THEN A%=A%+100 : B%=200 : PRINT C%: GOTO 100 ELSE A%=A%-100 : B%=C%*5+D% : PRINT B% Примечание: Заслуживает внимания следующий пример: 10 IF X! > Y! THEN A!=3*X!+Y! ELSE B!=3*Y!+X!/2 20 C%=0 11.3. Оператор ON для формулирования перехода на номер из списка Кодовым словом ON начинается оператор CASE для осуществления перехода или вызова подпрограмы. Формат: ON <выражение> GOTO <список номеров строк> или ON <выражение> GOSUB <список номеров строк> <список номеров строк> = <номер строки>[,<номер строки>]... <Выражение> может быть числовым выражением, имеющим целочисленное значение от 1 до 255 включительно. В данном случае значение выражения округяется до ближайшего наибольшего целого числа. При значении выражения, равном N, оператор действует следующим образом: из списка берется N-ый номер строки, и работа программы продолжается с данной строки при соблюдении спецификации GOTO или GOSUB. Если выражение равно 0 или больше числа номеров строк в списке, то программа продолжается со следующей строки. Если выражение имеет отрицательное значение, или больше чем 255, появляется сообщение об ошибке: ILLEGAL FUNCTION CALL. Примеры: 10 ON I%-I% GOTO 100, 200, 300 50 ON G% GOSUB 500,700 . . . . 500 REM G%=1 : подпрограмма1 . . . 590 RETURN 700 REM G%=2 : подпрограмма2 . . . 870 RETURN 12. Работа с подпрограммами на языке бейсик 12.1. Конструкция GOSUB и RETURN для обеспечения работы с подпрограммами С помощью инструкции GOSUB можно обращаться к подпрограммам, расположенным в программе. Формат: GOSUB номер строки . . RETURN Подпрограмма, расположенная в программе, представляет собой некоторую связанную последовательность произвольных строк инструкций, оканчивающуюся инструкцией RETURN. В одной подпрограмме могут встречаться несколько инструкций RETURN. Последовательность инструкций должна быть составлена таким образом< чтобы в конце всегда была инструкция RETURN. В подпрограммах могут быть другие вызовы подпрограмм. Переход в подпрограмму осуществляется инструкцией GOSUB. При этом данная инструкция сообщает номер строки, с которой должна стартоваться подпрограмма. Следует обратить внимание на то, что этот номер строки не должен быть обязательно первой строкой, с которой начинается подпрограмма. В отдельных случаях такая подпрограмма может иметь даже несколько стартовых строк (подпрограмма с точками входов!). Инструкция RETURN действует таким образом, что управление выполнением программы возврвщается инструкции, непосредственно следующей за инструкцией GOSUB. Пример: 10 F%=I 20 FOR I%=1 TO 6 30 GOSUB 100 40 NEXT 50 END 100 REM подпрограмма, расположенная в программе 110 F%=F%*F% 120 PRINT F% 130 RETURN RUN 1 2 6 24 120 720 OK Примечание: Подпрограммы, расположенные в программе, целесообразно использовать всегда в тех случаях, когда какая-либо определенная последовательность инструкций требуется в нескольких местах программы в одном и том же виде. 12.2. Инструкция CALL для вызова программ в машинном коде с организацией передачи параметров Инструкция CALL позволяет включать в бейсик-программу подготовленные в машинном коде и загруженные в память программные сегменты, при этом каждый сегмент может получить обработанную Бейсик-программой информацию в виде параметров. Точно также результаты работы программного сегмента можно вернуть в Бейсик-программу через соответствующие параметры. Формат: CALL <стартовый адрес программы в машинном коде> /(<параметр>/, <параметр>/...)/ В качестве <параметра> разрешается использовать только простые переменные любого типа (не может быть константой или выражением). (Относительно передачи параметров смотри приложение а.) Пример: 100 RUTIN%=&H7000 110 CALL RUTIN%(Z!, 15%, AI$) Указание: С помощью программной инструкции можно вызывать также подпрограммы через Бейсик, которые получены компилятором, работающим в операционной системе СРМ. Примечание: Для программы в машинном коде автоматически организуется стек размером 16 байт. Если этой области не хватает, то можно организовать в стандартной программе в машинном коде новую область, однако перед возвратом указатель стека снова следует установить на прежнее значение. Т.к. в области машинного кода обычно работают с шестнадцатеричными числам, то и стартовый адрес также следует задавать в шестнадцатеричном виде (смотри строку программы 100 в примере). В отличие от формата в Бейсик-интерпретаторе в Бейсик-компиляторе вместо стартового адреса подпрограммы указывают какое-либо имя подпрограммы, состоящее максимально из 6 символов. Для стандартной программы на ассемблере это имя должно быть об'явлено с помощью PUBLIC. Задание параметров не обязательно, так как в данном случае параметры можно передать также с помощью инструкции COMMON (смотри 12.6.). 12.3. Функция VARPTR для подготовки адресов памяти Функция VARPTR передает начальный адрес первого байта области памяти для задаваемых переменных или областей ввода-вывода (области буфера) какого- либо набора данных. Формат: VARPTR (<аргумент>) или VARPTR (#<номер набора данных>) Перед первым использованием функции переменной должно быть присвоено какое-либо значение. Если этого не было сделано, то происходит сообщение об ошибке. В качестве <аргумента> можно задавать любую простую числовую переменную или переменную типа символьной строки или любую числовую переменную поля или переменную поля типа символьной строки. Заданные адреса лежат в диапазоне от -32768 до 32767. Следует обратить внимание на то, что адреса поля изменяются, если позже будут обЪявлены еще какие-либо простые переменные. Это значит, что определение начальных адресовполей должно происходить непосредственно передих дальнейшим использованием. <Номер набора данных> устанавливается при открытии набора данных с помощью инструкции OPEN (смотри пункт 15.4.). При задании <номера набора данных> подготавливается начальный адрес области ввода-вывода. Функцию используют для передачи адресов обЪявленных в Бейсик-программе переменных и т.д. программе на ассемблере. Пример: 30 ADDR%=VARPTR(#3) 12.4. Инструкция описания DEF USR для условного перехода в пользовательскую машинную программу С помощью инструкции DEF USR можно включить в какую-либо Бейсик- программу программные сегменты в машинном коде. Формат: Описание: DEFUSR (<номер>) = <стартовый адрес программы в машинном коде> Вызов: <идентификатор переменной>=USR (<номер> (<фактическое выражение>) Можно использоватьмаксимально 10 составленных пользователем программных сегментов в машинном коде, имеющих номера от 0 до 9. Если номер не задан, то стандартно используется номер 0. Стартовый адрес программы в машинном коде представляет собой выражение типа INTEGER, INTEGER-переменную или INTEGER- константу. У каждой программы есть какой-либо параметр, с помощью которого можно передать программному сегменту соответствующее числовое значение. В результате работы программного сегмента также можно передать только одно числовое значение вызывавшей Бейсик-программе. (Относительно передачи параметров смотри приложение а.). Пример: 10 DEF USR 5=32763 . . . 90 !=USR 5(A!-B!*C%) Примечание: В одной Бейсик-программе может содержаться сколько угодно инструкций DEF USR с одинаковыми номерами. Поэтому в какой-либо выполняемой можно снова установить стартовые адреса. При работе с Бейсик-компилятором следует обратить внимание на то, что для USR-вызовов не предусмотрена передача параметров. Однако с помощью инструкции POKE (смотри пункт 13.9.) Можно записать данные в какую-либо защищенную область памяти, которые затем могут быть считаны и обработаны стандартной программой в машинном коде. Стандартная программа в машинном коде может возвратить целочисленное значение вызывавшей программе. Остальные значения можно считать с помощью инструкции PEEK (смотри пункт 14.4.) Из какой-либо защищенной области оперативной памяти. Рекомендуется необходимые стадартные программы в машинном коде с помощью редактора связей включить в откомпилированную Бейсик-программу. Данные программные блоки можно вызывать затем с помощью инструкции CALL (смотри пункт 12.2.) 12.5. Инструкция CHAIN для создания оверлейных структур в Бейсик-программах. С помощью инструкции CHAIN можно дозагружать программные сегменты. Формат: CHAIN /MERGE/<допустимый идентификатор набора данных>/, /,<номер строки>//,ALL//,DELETE<область вычеркиваемых номеров строк>// <допустимый идентификатор набора данных> представляет собой какой-либо допустимый в операционной системе СРМ идентификатор набора данных. Он задается как выражение из символьных строк, как переменная типа символьной строки или как константа типа символьной строки, идентификатор задается в кавычках. В указанном наборе данных содержатся дозагружаемые Бейсик- программы. Набор данных создают командой SAVE (смотри пункт 5.11.). Если не задан признак типа, то автоматически принимается признак ".BAS". Если используется опция MERGE, то дозагружаемые программы смешиваются в существующей программе. При этом следует учитывать все условия, упомянутые при описании команды MERGE (смотри пункт 5.14.). Если опция MERGE не используется, то дозагружаемые программные сегменты стандартно обрабатываются в режиме LOAD. При этом следует учитывать все условия, упомянутые при описании команды LOAD (смотри пункт 5.12.) С применением параметра R. Особенно следует обратить внимание на то, что теряют свое значение неявные описания типов (смотри пункт 7.2.), Описания функций и установки OPTION BASE (смотри пункт 9.2.). В случае необходимости их следует повторить в новой программе. С помощью параметра номер строки сообщается стартовая строка для загружаемого программного сегмента. Данный номер строки не изменяется при возможной перенумерации с помощью команды RENUM (смотри пункт 5.10.). Если номер строки не задан, дозагружаемый программный сегмент стартуется с первой строки программы. Если используется опция ALL, то дозагружаемому программному сегменту предаются все значения переменных. В противном случае программному сегменту предоставляются только фактические значения тех переменных, которые были описаны в инструкциях COMMON (смотри пункт 12.6.). Опеция DELETE вызывает стирание указанных строк, прежде чем будет загружен новый программный сегмент. Для задания области стираемых строк действуют приведенные в команде DELETE правила (смотри пункт 5.9.). Наборы данных после выполнения инструкции CHAIN остаются открытыми. Пример: 100 CHAIN "набор данных 1" 150 CHAIN "набор данных 1", 300 200 CHAIN "набор данных 1", 300, ALL 250 CHAIN MERGE "набор данных 1", 400 350 CHAIN MERGE "набор данных 1", 400, DELETE 200-700 10 COMMON I%, K%() 20 I%=5 30 FOR I%=I% TO 0 STEP -1 40 K%(I%)=I%+2*I% 50 PRINT I%,K%(I%) 60 NEXT 70 CHAIN "PROG2" P 5 15 4 12 3 9 2 6 1 3 0 0 0 0 1 3 2 6 3 9 4 12 5 15 Подпрограмма PROG2, размещенная в наборе данных с идентификатором "PROG2.BAS" 10 COMMON I%, K%() 20 FOR I%=0 TO I% 30 PRINT I%, K%(I%) 40 NEXT 50 END Примечание: При работе с бейсик-компилятором нельзя задавать опции ALL, MERGE, DELETE и параметр номер строки. Если хотят скомпилировать какую-либо Бейсик- программу, то этих опций не должно быть. Переменные лучше сообщать с помощью инструкции COMMON (смотри пункт 12.6.). 12.6. Инструкция описания COMMON Инструкция COMMON позволяет передавать информацию для сцепленных и наложенных программных сегментов вместе с программной инструкцией CHAIN (смотри пункт 12.5.). Формат: COMMON <идентификатор переменной> /, <идентификатор переменной>/... Указываются все переменные, фактическое расположение которых должно быть предоставлено дозагружаемым программным сегментам. Идентификаторы полей следует задавать в круглых скобках "()". Каждое описание COMMON должно стоять перед всеми остальными инструкциями соответствующего программного сегмента. Последовательность параметров в инструкции COMMON у отдельных программных сегментов может быть различной. Каждый параметр следует задавать только один раз. Пример: 10 COMMON I%, I1%, T#(), S1$, S2$ . .