Assembler для начинающих


Процедура Бэйсика BLOAD



Процедура Бэйсика BLOAD


      При первом способе подпрограмма на машинном языке добавляется к
    программе для интерпретатора Бэйсика. Пожалуй, использование
    интерпретатора Бейсика является наиболее распространенным методом
    написания программ для персональной ЭВМ. Подпрограмма на языке
    ассемблера, которую предполагается включить в разрабатываемую
    программу, довольно велика - более 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 точек. Каждая точка растра передается на принтер. Если
    точка на экране имеет цвет фона, то соответствующая точка на печать
    не выдается. Если точка окрашена в один из трех основных цветов, то
    программа выводит на печать черную точку. Эта программа не
    масштабирует изображение, поэтому окружность на экране может
    отобразиться в эллипс на принтере. Между тремя основными цветами не
    проводится различий. Цветное изображение превращается в
    черно-белое.
 
      Подпрограмма PRINT_SCREEN является процедурой типа FAR. Вызов
    ее из языка Бейсик является вызовом типа FAR, поэтому и возврат в
    программу должен быть соответствующего типа. Последовательность ESC
    + "3" + 24 устанавливает такой интервал между строками печати, что
    один ряд точек вплотную примыкает к другому. В печатающей головке
    имеется восемь иголок, расстояние между которыми равно 1/72 дюйма.
    Если сделать интервал между строками равным 8/72 дюйма (или 24/216
    дюйма), то ряды точек соединятся. Приведенный фрагмент программы
    показывает способ пересылки на устройство печати последовательности
    служебных символов. Управляющая последовательность символов и чисел
    пересылается на принтер как обычные символы. Остальное обеспечивает
    устройство печати.
 
      При каждом проходе печатающей головки на бумаге остается по
    восемь рядов точек (по одному на каждую иголку печатающей головки)
    в   каждой из 320 колонок. От метки NEXT_ROW в программе
    последовательность ESC + "K" + 64 + 1 пересылается на принтер. Это
    означает, что последующие 320 байт (64 + 1*256) являются образами
    точек для получения графического изображения на принтере. В
    графическом режиме "K" на принтере можно получить изображение
    шириной до 480 точек.
 
      Для считывания точек с дисплея программа использует видео
    функцию 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 в командной строке Бейсика ограничивает
    рабочую область Бейсика и оставляет место для подпрограммы.
    Аналогичная команда потребуется и при запуске программы.
 
      Программой DEBUG можно воспользоваться для вашей ассемблерной
    процедуры и при работе интерпретатора Бейсика .  Включите в команду
    G при запуске программы Бейсика установку контрольной точки в
    подпрограмме.  По достижении контрольной точки работа
    интерпретатора Бейсика приостанавливается, и производится обычная
    для программы DEBUG выдача содержимого регистров.
 
      Теперь все готово для выполнения подпрограммы на языке
    ассемблера как части программы на языке Бейсик. Снова предположим,
    что система располагает 128 кбайтами памяти, и выполним следующую
    последовательность действий:
 
      введите "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.




Содержание раздела