При первом способе подпрограмма на машинном языке добавляется к программе для интерпретатора Бэйсика. Пожалуй, использование интерпретатора Бейсика является наиболее распространенным методом написания программ для персональной ЭВМ. Подпрограмма на языке ассемблера, которую предполагается включить в разрабатываемую программу, довольно велика - более 100 байт. Ассемблерную процедуру такой длины трудно вставить в текст программы на языке Бейсик, способ, позволяющий сделать это будет рассмотрен в следующем примере.
Функция, которую мы добавляем к программе на языке Бейсик позволяет выводить на принтер графические изображения. IBM PC снабжена графическими средствами. Графические команды позволяют программно управлять отдельными точками, выводимыми на принтер, во многом подобно тому, как в графическом режиме адаптер цветного дисплея дает программисту возможность управлять отдельными точками растра. На Фиг. 10.4 представлены графические команды, которые потребуются в рассматриваемом примере. Практически, графические функции реализуются на принтере через управляющие последовательности символов. Вместо символа в коде ASCII программа выдает на принтер служебный символ (27 в коде ASCII). Следующие за ним символы задают уже не символы для вывода на печать, а определенные действия принтера. Как видно из Фиг. 10.4, существуют команды для вывода на принтер изображения точки, в результате выполнения которых печатается определенная точка изображения.
Команда Действие
---------------------------------------------------------
ESC + "3" + n Установка промежутка между
строками n/216
Esc + "K" +n1+n2+v1...vk Печатать образы точек v1...vk
(k = n1 + 256*n2) как 480 точек поперек страницы
---------------------------------------------------------
Фиг.10.4 Графические команды для принтера
Приведенная на Фиг. 10.5 программа использует указанные команды для вывода на принтер образа экрана графического дисплея размером 320*200 точек. Каждая точка растра передается на принтер. Если точка на экране имеет цвет фона, то соответствующая точка на печать не выдается. Если точка окрашена в один из трех основных цветов, то программа выводит на печать черную точку. Эта программа не масштабирует изображение, поэтому окружность на экране может отобразиться в эллипс на принтере. Между тремя основными цветами не проводится различий. Цветное изображение превращается в черно-белое.
Для считывания точек с дисплея программа использует видео функцию BIOS . Эта функция считывает восемь рядов точек текущего столбца и собирает их в один байт: "1" означает, что точка имеет основной цвет и должна появиться на бумаге. Цикл продолжается через метку NEXT_COLUMN - до тех пор, пока все 320 столбцов (что соответствует 320 байтам) не будут переданы на принтер . После перехода принтера на новую строку при помощи служебных символов "возврат каретки" и "перевод строки" (13 и 10 в коде ASCII), программа пересылает следующую группу из восьми рядов. За 25 проходов печатающей головки выводятся все 200 рядов. Возврат в интерпретатор Бейсика производится при помощи возврата типа FAR.
В рассматриваемой программе было бы удобно использовать процедуру PRINT. Эта процедура выдает один байт на принтер при помощи функции печати BIOS. Функция помещает необходимые для базовой системы ввода-вывода установки регистров в определенное место. Если не использовать указанную функцию, то программа сама должна была бы устанавливать регистры AH и DX равными нулю перед каждым вызовом процедуры PRINT.A
Microsoft (R) Macro Assembler Version 5.00 1/1/80 04:06:57
Фиг. 10.5 Печать графической копии дисплея Page 1-1
PAGE ,132
TITLE Фиг. 10.5 Печать графической копии дисплея
= 001B ESC EQU 27 ; Символ Escape
0000 CODE SEGMENT
ASSUME CS:CODE
0000 PRINT_SCREEN PROC FAR
0000 B0 1B MOV AL, ESC ; Установка перевода строки на 1/8 дюйма
0002 E8 0060 R CALL PRINT
0005 B0 33 MOV AL, '3'
0007 E8 0060 R CALL PRINT
000A B0 18 MOV AL, 24 ; 1/8 = 24/216 дюйма
000C E8 0060 R CALL PRINT
000F BA 0000 MOV DX, 0 ; Номер строки
0012 NEXT_ROW:
0012 B0 1B MOV AL, ESC
0014 E8 0060 R CALL PRINT
0017 B0 4B MOV AL, 'K'
0019 E8 0060 R CALL PRINT
001C B0 40 MOV AL, 320-256
001E E8 0060 R CALL PRINT
0021 B0 01 MOV AL, 1
0023 E8 0060 R CALL PRINT
0026 B9 0000 MOV CX, 0 ; Номер столбца
0029 NEXT_COLUMN:
0029 52 PUSH DX ; Сохранение номера строки
002A BB 0008 MOV BX, 8 ; Число одновлеменно обрабатываемых точек
002D NEXT_DOT:
002D D0 E7 SHL BH, 1 ; Освобождение младшего разряда
002F B4 0D MOV AH, 13 ; Чтение цвета точки из памяти дисплея
0031 CD 10 INT 10h
0033 0A C0 OR AL, AL
0035 74 03 JZ BACKGROUND ; Проверка на цвет фона
0037 80 CF 01 OR BH, 1 ; Не фон, необходимо вывести точку на печать
003A BACKGROUND:
003A 42 INC DX ; Переключение на следующую строку
003B FE CB DEC BL ; Уменьшение счетчика строк в данном проходе
003D 75 EE JNZ NEXT_DOT
003F 8A C7 MOV AL, BH ; Печать 8-ми точек
0041 E8 0060 R CALL PRINT ; Вывод на печать
0044 5A POP DX ; Восстановление номера строки начала прохода
0045 41 INC CX ; Переключение на следуюий столбец
0046 81 F9 0140 CMP CX, 320 ; Все столбцы выведены?
004A 75 DD JNZ NEXT_COLUMN
004C B0 0D MOV AL, 13 ; Переход на следующую строку на принтере
004E E8 0060 R CALL PRINT
0051 B0 0A MOV AL, 10
0053 E8 0060 R CALL PRINT
0056 83 C2 08 ADD DX, 8 ; Переключение на слдующую группу из 8 строк
0059 81 FA 00C8 CMP DX, 200 ; Все строки выведены?
005D 72 B3 JB NEXT_ROW
005F CB RET ; Возврат в BASIC
Фиг. 10.5 Печать графического экрана (начало)
0060 PRINT_SCREEN ENDP
0060 PRINT PROC NEAR
0060 52 PUSH DX
0061 B4 00 MOV AH, 0 ; Печать символа, находящегося в регистре AL
0063 BA 0000 MOV DX, 0
0066 CD 17 INT 17h
0068 5A POP DX
0069 C3 RET
006A PRINT ENDP
006A CODE ENDS
ENDA
Фиг. 10.5 Печать графического экрана (продолжение)
Как же обратиться к этой процедуре из программы, написанной на языке Бейсик? В языке Бейсик существуют два способа подключения подпрограмм. Во время работы интерпретатор Бейсика использует оставшуюся память системы (до 64 кбайт) в качестве рабочей области. Если в системе более 96 кбайт памяти, часть памяти будет не доступна для интерпретатора Бейсика. Лучше всего поместить нашу процедуру в эту область. Если свободной области памяти нет, то можно специально выделить некоторый объем памяти из рабочей области интерпретатора Бейсика для хранения подпрограммы. В данном примере подпрограмма будет храниться вне рабочей области интерпретатора Бейсика. В следующем примере будет показано, как включить процедуру в контролируемую интерпретатором Бейсика область памяти.
На Фиг. 10.6 показана последовательность действий для подготовки подпрограммы к дальнейшему использованию. Соответствующая информация приведена в приложении C справочника по языку Бейсик. Программа (на Фиг. 10.6) предназначена для машины с оперативной памятью 96 кбайт и более. Программа ассемблируется обычным образом. При редактировании связей задается опция /H. Редактор связей создает файл типа .EXE таким образом, что программа загружается в верхние адреса оперативной памяти, а не с самого низкого из доступных адресов.
Чтобы подключить процедуру к программе, написанной на языке Бейсик, нам потребуется программа DEBUG. После загрузки программы на языке Бейсик во время работы программы DEBUG и уточнения значений регистров, загружаем процедуру на языке ассемблера. Приведенный пример реализован на машине с памятью 128 кбайт. Значение регистра CS, равное 1FF9H, указывает на то, что программа помещена в 70H байт от конца оперативной памяти. Заметим, что рассматриваемая программа имеет объем около 6AH байт, так что редактор связей разместил программу с самого старшего адреса памяти, допускающего выравнивание по границе параграфа. Следует также заметить, что эта программа является сегментно - перемещаемой. Это означает, что ее можно перемещать в памяти, поскольку первая ее команда имеет смещение 0 относительно текущего сегмента кода. При переносе этой программы на машину с большим или меньшим объемом памяти эта особенность оказывается решающей.
A
B>A:MASM FIG10-5,,,;
The IBM Persona Computer MACRO Assembler
Version 1.00 (C)Copyright IBM Corp 1981
Warning Severe
Errors Errors
0 0
B>A:LINK FIG10-5,,,/H;
IBM Personal Computer Linker
Version 1.10 (C)Copyright IBM Corp 1982
Warning: No STACK segment
There was 1 error detected
B>A:DEBUG A:BASIC.COM
-R
AX=0000 BX=0000 CX=2B80 DX=0000 SP=FFF0 BP=0000 SI=0000 DI=0000
DS=04B5 ES=04B5 SS=04B5 CS=04B5 IP=0100 NV UP DI PL NZ NA PO NC
04B5:0100 E91329 JMP 2A16
-NFIG10-5.EXE
-L
-R
AX=0000 BX=0000 CX=006A DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=04B5 ES=04B5 SS=1FF9 CS=1FF9 IP=0000 NV UP DI PL NZ NA PO NC
1FF9:0000 B01B MOV AL,1B
-RSS
SS 1FF9
:4B5
-RCS
CS 1FF9
:4B5
-RIP
IP 0000
:100
-G
---- В интерпретаторе Бэйсика введите команды
DEF SEG = &H1FF9
BSAVE "FIG10-5",0,&H70
Фиг. 10.6 (а) Создание подпрограммы для Бэйсика
B>A:MASM FIG10-5,,,;
The IBM Persona Computer MACRO Assembler
Version 1.00 (C)Copyright IBM Corp 1981
Warning Severe
Errors Errors
0 0
B>A:LINK FIG10-5,,,/H;
IBM Personal Computer Linker
Version 1.10 (C)Copyright IBM Corp 1982
Warning: No STACK segment
There was 1 error detected
B>A:DEBUG A:BASIC.COM /M:&H8000
-R
AX=0000 BX=0000 CX=2B80 DX=0000 SP=FFF0 BP=0000 SI=0000 DI=0000
DS=04B5 ES=04B5 SS=04B5 CS=04B5 IP=0100 NV UP DI PL NZ NA PO NC
04B5:0100 E91329 JMP 2A16
-NFIG10-5.EXE
-L
-R
AX=0000 BX=0000 CX=006A DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=04B5 ES=04B5 SS=0FF9 CS=0FF9 IP=0000 NV UP DI PL NZ NA PO NC
0FF9:0000 B01B MOV AL,1B
-RSS
SS 0FF9
:4B5
-RCS
CS 1FF9
:4B5
-RIP
IP 0000
:100
-G
---- В интерпретаторе Бэйсика; введите команды
DEF SEG = &H0FF9
BSAVE "FIG10-5",0,&H70
(b)
A
Фиг. 10.6 (а) Создание подпрограммы для Бэйсика; (b) Создание подпрограммы для Бэйсика на машине с 64K
Теперь мы имеем дело с интерпретатором Бейсика. Нам необходимо восстановить содержимое регистров таким, каким оно было после загрузки Бейсика. После того, как интерпретатор Бейсика запущен, для локализации подпрограммы используется команда DEF SEG. Команда BSAVE помещает обратно на дискету объектный код, готовый к новой загрузке из Бейсика при помощи команды BLOAD.В части (b) Фиг. 10.6, повторяются действия из части (а), но для машины с объемом памяти 64 кбайт. Различие здесь состоит в том, что интерпретатор Бейсика не может использовать всю память под рабочую область. Опция /M в командной строке Бейсика ограничивает рабочую область Бейсика и оставляет место для подпрограммы. Аналогичная команда потребуется и при запуске программы.
введите "BASIC" на уровне команд DOS;
введите "SCREEN1" во время работы интерпретатора Бейсика.
Фиг. 10.7 Печатная копия экрана
Эти действия вводят нас в интерпретатор и переводят режим изображения на размер 320*200 точек. На Фиг. 10.7. показаны оставшиеся события этой истории. Команда BLOAD загружает процедуру в ту же область памяти, из которой она была сохранена. При желании в команде BLOAD можно задать параметры, обеспечивающие загрузку программы в другую область памяти. Оператор LINE дает процедуре графической распечатки экрана информацию для печати. Для вызова этой процедуры мы используем команду DEF SEG, чтобы установить значение регистра CS на процедуру. Значение регистра IP для процедуры помещается в простую переменную. Оператор CALL осуществляет дальний вызов по заданному адресу. Фиг. 10.7 представляет собой копию реальной распечатки, полученной при выполнении приведенной программы.Если в системе 64Кбайт памяти, то программа будет отлична в двух аспектах. Для вызова интерпретатора Бейсика используется команда BASIC/M:&H8000, резервирующая верхнюю часть памяти для нашей ассемблерной процедуры, а команда DEF SEG задает адрес подпрограммы, как это было сделано в части (b) Фиг. 10.6.