[an error occurred while processing this directive]
│.........*.......*.......*.......*.......*.......*.......*.........<

─SRP 1
─PL70
─TM0
─HM2
─DH//-|P-//
─LM5





─CEШевкунов В.В.

─CEПрограммирование на Ассемблере в системе BBC BASIC
─CEи системные вызовы ОС ОНИКС
























─CEМосква, 1991
─PE
│.........*.......*...........*.............*.......................<
─CE|||/Язык Программирования Ассемблер/|||

 Для чего нужен Ассемблер, если можно писать программы на Бейсике?

 Бейсик - это относительно легкий  для  изучения  язык, второе его
преимущество  заключается  в  том,  что если Вы ошибетесь, система
сразу  отреагирует  на это. Однако  ничего  не  дается  даром,  за
простоту  и  "дружелюбность"   языка   приходится   расплачиваться
существенным увеличением времени  выполнения  программы.  В данной
версии   Бейсика  существует  возможность  соединить  преимущества
интерактивности   Бейсика   с  быстротой  Ассемблера,  т.е.  можно
встраивать  в  программу  на  Бейсике  подпрограммы  написанные на
Ассемблере.

 Программа на Ассемблере состит из операторов типа

|LDA #3|

 что  означает  "загрузить  в  аккумулятор  число  3"  ("Load  the
accumulator with 3") или

|JSR &6000|

 что означает "вызвать подпрограмму по  адресу 6000" ("Jump to the
subroutine at location 6000 hex").

 Ассемблер - это программа, которая  преобразует команды мнемокода
в машинный код, который "понимает" микропроцессор.

 Ассемблер используется в тех случаях,  когда  быстродействие  или
размер  программы  имеют  решающее значение. Бейсик хорош там, где
легкость  написания  программы  важнее   требованиий   к  скорости
выполнения и размеру используемой памяти.

 Из-за ограниченного объема данного руководства невозможно научить
Вас  программировать на Ассемблере, хотя  он  и  входит  в  состав
интерпретатора. Однако,  программисты,  владеющие  ассемблером для
6502  найдут  здесь  всю  необходимую   информацию   для  создания
эффективных машинных подпрограмм. В конце данной главы описываются
осовные вызовы операционной системы и их параметры.

 При  запуске  Бейсика с диска  в  память  Агата  так  же  грузитс
Операционная Система (ОС).  ОС  прежде всего осуществляет операции
ввода/вывода  доступ  к которым осуществляется  через  стандартные
точки  вызовов  ОС.  Многие  вызовы  осуществляются  по  векторам,
расположенным в ОЗУ.

 ОС  обеспечивает все графические и  текстовые  операции,  включая
выбор режима отображения, рисование линий, установку графических и
текстовых окон, переопределение символов.

 ОС  также  осуществляет  взаимодействие  с  аналоговыми  входами,
паралельным интерфейсом и клавиатурой.

 Из программы на Ассемблере можно  осуществлять различные операции
с Дисковой Файловой Системой (ДФС).

 Все обращения к ОС должны  осуществляться  только  по стандартным
точкам   входов,   что   гарантирует  работоспосбность  прикладных
программ независимо от конфигурации компьютера.

 Ассемблер является частью интерпретатора Бейсик,  и   может  быть
вызван  квадратной скобкой "|[|". Конец ассемблирования обозначается
правой квадратной скобкой "|]|".
─PE5
	|10 PRINT "THIS IS BASIC"
	20 [
	30 JSR &FFE7
	40 ]|

 (Не пытайтесь запустить эту программу - она не закончена!)

 В предыдущем примере ассемблеру не  было ссобщено, куда поместить
отассемблированный  машинный  код.  "Программным счетчиком" служит
переменная  P%,  которой  можно   присвоить   требуемое  значение,
например
─PE14
	|10 PRINT "THIS IS BASIC"
	15 P%=&7000
	20 [
	30 JSR &FFE7
	40 ]
	50 PRINT "AND THIS IS BASIC TOO"

 >RUN
 THIS IS BASIC
 7000
 7000 20 E7 FF JSR &FFE7
 AND THIS IS BASIC TOO|

 Однако  существует  другой,  более  практичный  способ  выделения
памяти   для   машинной   подпрограммы.  Для   этого   применяется
специальная версия оператора |DIM|.
─PE16

	|10 PRINT "THIS IS BASIC"
	15 DIM GAP% 20
	16 P%=GAP%
	20 [
	30 JSR &FFE7
	40 ]
	50 PRINT "AND THIS IS BASIC TOO"
 
 >RUN
 THIS IS BASIC
 0F6B
 0F6B 20 E7 FF JSR &FFE7
 AND THIS IS BASIC TOO|

 В последней программе автоматически выделяется область размером в
21 байт, начало которой хранится в переменной |GAP%|. Это безопасный
способ совмещения программы на Бейсике с машинными подпрограммами.
Естественно размещение машинной подпрограммы будет  изменяться при
изменении основной программы до оператора |DIM|:
─PE16

	|10 PRINT "THIS IS BASIC"
	12 REM INSERT AN EXTRA LINE
	15 DIM GAP% 20
	16 P%=GAP%
	20 [
	30 JSR &FFE7
	40 ]
	50 PRINT "AND THIS IS BASIC TOO"

 >RUN
 THIS IS BASIC
 0F85
 0F85 20 E7 FF JSR &FFE7
 AND THIS IS BASIC TOO|

 Два   оператора   Бейсика   обеспечивают   доступ    к   машинным
подпрограммам: |CALL| и |USR|. Оператор |USR| позволяет легко передавать
значения  регистрам микропроцессора и обратно.  Когда  выполняется
оператор

|R = USR(Z)|

компьютер сначала помещает значения переменных  |X%,  Y%, A%| и |C%| в
регистры  микропроцессора  X  и  Y,  аккумулятор и  флаг  переноса
соответственно.  Конечно,  толко младшие значащие байты переменных
X%, Y%, A% и млдаший значащий бит пременной C% используются.

 После установки региситров управление передается  подпрограмме по
адресу Z. Эта подпрограмма должна заканчиваться  командой  |RTS| для
возврата  в  вызывающую  программу  на  Бейсике.  Перед  возвратом
регистры A, X, Y и регистр состояния помещаются в переменную R.

 Для наглядности ниже приводится короткая  программа, использующая
вызов  |OSBYTE|  (Operating System Byte) для  определения  положения
текстового курсора на экране.
─PE8

	|30 A%=&86
	40 X%=0
	50 R=USR(&FFF4)
	60 PRINT ~R|

 Строки 30 и 40 устанавливают  регистр  X и аккумулятор. Строка 50
помещает  результат  в  R  и строка 60  печатает  содержимое  R  в
шестнадцатиричном виде. Результат может быть таким:

─PE10
	|B1120086|

	|B1| Значение регистра состояния (P).
	|12| Значение регистра Y, что в данном случае
	   соответствует Y-координате курсора.
	|00| Значение регистра X, что в данном случае
	   соответствует X-координате курсора.
	|86| Значение аккумулятора.

 Оператор  |CALL|  предоставляет  более  гибкий   способ  доступа  к
машинным подпрограммам. |CALL| не возвращает  результат в переменную
Бейсика. Однако пользователь может, если он  хочет,  сделать любую
переменную  доступной  из  машинной  подпрограммы.   Если в состав
оператора  |CALL|  входят  переменные,  Создается "Блок Параметров",
помещаемый по адресу &600.

 При  входе  в  подпрограмму  регистрам   процессора   A,   X,  Y,
присваиваются значения младших значащих байт  переменных  A%, X% и
Y%.  Флаг  переноса  устанавливается  в  соответствии с состоянием
младшего значащего бита переменной C%.

 Перед  вызовом  подпрограммы компьютер создает  Блок  Параметров,
содержащий следующие данные:
─PE10

   Количество параметров - 1 байт
   адрес 1-го параметра  - 2 байта
   тип 1-го параметра    - 1 байт
   адрес 2-го параметра  - 2 байта
   тип 2-го параметра    - 1 байт
   ....................  - .......
   адрес N-го параметра  - 2 байта
   тип N-го параметра    - 1 байт

─PE8
|||/Типы параметров/|||
     0-  8 бит байт (например ?X)
     4- 32 бит целая переменная (например !X или X%)
     5- 40 бит число с плавающей запятой (например V)
   128- Строка с заданным адресом (например ¤X-оканчивающаяся &0D) 
   129- Символьная переменная (например A¤)

 В  случае символьной переменной адрес  параметра  содержит  адрес
Информационного Блока  Строки,  который  содержит стартовый адрес,
количество выделенных байт и текущую длину строки.

 Ниже приведена программа, использующая оператор |CALL
─PE28

	 10 REM Demonstration of CALL with a parameter
	 20 PROCINIT
	 30 A%=&12345678
	 40 CALL SWAP,A%
	 50 PRINT~A%
	 60 END
	 70 DEF PROCINIT
	 80 DIM Q% 100
	 90 FOR C=0 TO 2 STEP 2
	100 PAR=&600: REM Parameter block
	110 ZP=&80: REM Usable zero page
	120 P%=Q%
	130 [OPT C
	140 .SWAP LDA PAR
	150 CMP#1:BEQ OK
	160 .ERRO BRK
	161 ]
	162 ?P%=45
	163 ¤(P%+1)="Swap Parameters"
	164 P%=P%+16
	170 [OPT C:BRK
	180 .OK LDA PAR+3:CMP #4:BNE ERRO
	190 LDA PAR+1:STA ZP
	200 LDA PAR+2:STA ZP+1
	210 LDY#3:LDX#0
	220 LDA(ZP,X):PHA:LDA(ZP),Y:STA(ZP,X):PLA:STA(ZP),Y
	230 RTS
	240 ] NEXT
	250 ENDPROC|

 Строки  с  10  по  60  формируют  главную  Бейсик-программу.  Она
использует  машинную  подпрограмму  для  циклического  перемещения
содержимого переменной A%. 20-я строка вызывает процедуру, которая
ассемблирует   мнемокод   в   машинную   подпрограмму.  Строка  30
присваивает переменной произвольное значение, а строка 40 вызывает
машинную  подпрограмму  для  изменения  содержимого переменной A%.
50-я строка печатает результат работы подпрограммы.

 Процедура (строки 70 - 250)  ассемблирует мнемокод подпрограммы в
машинный код. 80-я строка резервирует 101 байт памяти и помещает в
Q%  адрес  начала  зарезервированной  области.  Строки  90  и  240
формируют   цикл  |FOR...NEXT|,  который  обеспечивает  два  прохода
ассемблирования  - первый для формирования таблицы меток, а второй
для помещения  машинного  кода  в  память компьютера. 120-я строка
иницализирует   программный   счетчик  в  начале  каждого  прохода
ассемблирования.   В   строках   140  и  150  происходит  проверка
содержимого по адресу &600. Адрес &600 содержит "число параметров"
и наша подпрограмма рассчитана только на один параметр. Если число
параметров  не  равно  единице управление передается на метку |ERRO|
(строка 160).

 Строки  160  -  164  показывают,  как  можно  легко  генерировать
сообщения об ошибках. Подробно об  это  рассказывается  в  разделе
"Системные прерывания". Следует только сказать, что в нашем случае
будет  генерироваться  код  ошибки  45 и выдаваться сообщение |"Swap
Parameters"|  с  последующей  передачей управления  Бейсику.  164-я
строка  увеличивает  значение  программного   счетчика   с   целью
выделения места для сообщения.

 В   строке   170   происходит  повторный   вызов   Ассемблера   и
переустановка |OPT|. В строке 180 происходит проверка типа параметра
- он должен быть равен  четырем  (целая  переменная). Строки 190 -
220  осуществляют  непосредственную  обработку  параметра, а 230-я
строка обеспечивает возврат в Бейсик.
─PE
─CE|Ассемблер языка Бейсик|

 Вход  в режим Ассемблирования осуществляется  оператором  "|[|",  а
выход   -    оператором   "|]|".   Внутри   режима   ассемблирования
псевдооператор |OPT|  используется  для установки режимов листинга и
выдачи  сообщений  об  ошибках.   |OPT|  может  принимать  следующие
значения:
─PE7

	|OPT 0 |отмена вывода листинга и сообщений
	|OPT 1 |вывод только листинга
	|OPT 2 |вывод только сообщений
	|OPT 3 |вывод листинга и сообщений

 Обычно первому проходу соответствует |OPT  0|,  а  второму - |OPT 2|.
Если требуется вывод листинга, то  вместо |OPT 2|  используется  |OPT
3|.

 |Метки| задаются словом, перед которым  должна  стоять  точка.  Для
обращения к метке точку ставить не надо.
─PE6

		|LDA #8
	.LOOP	BIT VIA+&D
		BNE LOOP|

 Имена  меток  формируются  аналогично  именам  переменных.  Таким
образом они должны начинаться с  буквы  и  не  должны начинаться с
зарезервированных слов. Во время первого прохода неизвестные метки
вызываеют  генерацию  иекущего  адреса.  Таким образом все команды
перехода будут передавать управление сами на себя.

 Для  ввода |байтовых или символьных  констант|  программист  должен
временно   выйти    из    режима    ассемблера    и   использовать
непосредственные операторы. Например
─PE9

	|JMP LABEL1
	]
	¤P%="TODAY"
	P%=P%+6
	[
	.LABEL1 LDA&|

 Напоминаем,  что  переменная  P%  служит  программным  счетчиком,
оператор  (¤)  используется  для помещения  ASCII  кодов  символов
непосредственно в память компьютера.  Слово |TODAY| будет занесено в
память вместе с перводом строки  (&0D)  оканчивающим его - всего 6
символов.  Если Вы хотите, чтобы слово оканчивалось  нулем  вместо
&0D Вы должны написать следущее:
─PE6

	|¤P%="TODAY"
	P%?5=0
	P%=P%+6|

 Для  размещения  числовых  значений  вы   должны  воспользоваться
операторами доступа к байтам и словам памяти ? и !, например:
─PE9

	|JMP LABEL2
	]
	?P%=10
	P%?1=20
	P%?2=66
	P%=P%+3
	[|

 Режимы адресации 6502 обозначаются стандартным  образом,  но  для
обозначения шестнадцатиричного режима используется амперсенд.
│...*.........................*.............*.......................<
─PE15

	 |Режим адресации	Примеры|

	 Непосредственная         LDA #4        LDA #VALUE
	 Абсолютная               JMP &8000     LDA LOCATION
	 Нулевой страницы         LDA &FC       STY TEMPI
	 Аккумуляторная           ASL A
	 Командная                RTS
	 Прединдексная косвенная  LDA (5,X)     CMP (OFFSET,X)
	 Постиндексная косвенная  LDA (&84),Y   ORA (TABLE),Y
	 Короткая индексная       LDA 10,X      INC CNT,X
	 Абсолютная индексная     LDA &1234,X   STA STORE,X
	 Косвенная                JMP (&20E)    JMP (WRCHV)
	 Короткая косвенная по Y  LDX 24,Y      LDX VAR,Y
│.........*.......*...........*..............*......................<

 |Комментарии| могут быть вставлены в  фрагмент  на  ассемблере, для
этого  перед  комментарием  помещается  символ  "\". В Бейсике все
символы от оператора |REM| и до  конца  строки игнорируются, так что
невозможно  поместить  следующий  оператор на той же строке. Таким
образом 

	|10 REM HELLO : PRINT "FRIDAY"|

 не будет печатать слово FRIDAY.  Однако, в ассемблере комментарии
заканчиваются  также символом ":". Все следующие  операторы  будут
отассемблированы:

	|LDA #&10 \MASK :.LOOP BIT VIA+13
	\INTERRUPT FLAG : BEQ LOOP|
[an error occurred while processing this directive]