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


Компилируемые языки высокого уровня



Компилируемые языки высокого уровня


      В предыдущих примерах рассматривалась программа на языке
    ассемблера, используемая совместно с интерпретатором Бейсика.
    Версия языка Бейсик, входящая в поставку IBM PC, является
    интерпретируемым языком.  Это означает, что программа хранится в
    ЭВМ в виде, очень похожем на исходный текст.  Интерпретатор не
    преобразует операторы языка Бейсик в команды машинного языка.
    Интерпретатор Бейсика во время выполнения просматривает каждый
    оператор программы и делает все, что необходимо для выполнения
    этого оператора.
 
      По-другому работает компилятор.  Он преобразует операторы языка
    высокого уровня в команды машинного языка.  Фирма IBM предлагает


    компиляторы для персональной ЭВМ с языков Бейсик, Паскаль, Фортран
    и Кобол.  Выходом компилятора является программа на машинном языке
    (файл *.OBJ), т.е.  он во многом аналогичен выходу ассемблера.
    Запуск программы, написанной на компилируемом языке высокого уровня
    состоит из двух этапов.  Сначала программа должна быть
    скомпилирована, и должны быть отредактированы связи.  Затем она
    может быть выполнена.  Интерпретируемая программа может выполняться
    непосредственно, минуя этап компиляции.
 
      Компилируемые языки на персональной ЭВМ аналогичны языку Бейсик
    в том смысле, что не дают возможности делать с техническим
    обеспечением все, что вздумается.  На самом деле интерпретатор
    Бейсика еще позволяет программисту при помощи операторов программы
    считывать и записывать информацию с портов ввода-вывода и ячеек
    памяти.  Другие языки не всегда предоставляют даже эту возможность.
    Поэтому применение подпрограмм на языке ассемблера в программе на
    Паскале или Фортране может оказаться даже более необходимым.
    Возможно, вам придется заняться этим, если вы захотите
    воспользоваться всеми возможностями технического обеспечения.
 
      К счастью, включить процедуру на языке ассемблера в программу
    на компилируемом языке высокого уровня довольно просто, так как
    выходом компилятора является объектный файл, готовый к
    редактированию связей.  Выход ассемблера - тоже объектный файл.
    Следовательно, достаточно лишь связать программу на языке высокого
    уровня и программу на языке ассемблера при помощи редактора связей
    DOS.  Нет необходимости соединять программы в процессе выполнения,
    как это делалось для интерпретатора Бейсика.
 
      Построим пример на языке Фортран (Фиг.    10.11).  Для языка
    Паскаль все очень похоже.  Подобный пример приведен в приложении D
    справочника к компилятору Фортрана.  В примере головная программа,
    написанная на Фортране, объединена с программой на языке
    ассемблера, которая считывает текущее время, используя программное
    прерывание базовой системы ввода-вывода.  Подпрограмма на языке
    ассемблера обращается к BIOS для определения текущего времени и
    возвращает соответствующее значение в программу на Фортране.
    Головная программа преобразует кванты таймера, в текущее время,
    выраженное в часах, минутах и секундах.
 
      На Фиг.  10.11 представлена головная программа на Фортране.
    Эта программа вызывает внешнюю процедуру TIMER, имеющую один
    параметр A - четырехбайтовое целое значение.  Возрващаемое
    процедурой TIMER значение представляет собой текущее время,
    выраженное в квантах таймера и отсчитываемое от полуночи.
    Программа на Фортране по полученному из процедуры TIMER значению
    вычисляет время в часах(HOURS), минутах(MINS), секундах(SECS) и
    сотых долях секунды(HSECS).  Отметим, насколько проще реализовать
    умножение и деление на языке Фортран, чем на языке ассемблера.
    Можно убедиться, что выполнение всех подобных операций на Фортране
    существенно упрощает программирование.  Чрезвычайно удобен и способ
    преобразования целых переменных в выдаваемые на печать символы при
    помощи операторов Фортрана WRITE и FORMAT.  На языке ассемблера для
    выполнения тех же самых действий потребовалось бы несколько сот
    строк.  Вспомним пример для сопроцессора 8087, где программа
    преобразовывала число с плавающей точкой в код ASCII.  В этой
    программе содержалось значительное число команд, и, кроме того,
    использовался сопроцессор 8087.
 
      $STORAGE=4
            INTEGER A,HOURS,MINS,SECS,HSECS
            CALL TIMER(A)
            HOURS=A/65543
            A=A-HOURS*65543
            MINS=A/1092
            A=A-MINS*1092
            SECS=A/18
            HSECS=(100*(A-SECS*18))/18
            WRITE(*,10)HOURS,MINS,SECS,HSECS
      10    FORMAT(1X,'THE TIME IS: ',I2,':',I2,':',I2,'.',I2)
            END
 
      Фиг. 10.11 Программа определения времени дня на Фортране
 
             Microsoft (R) Macro Assembler Version 5.00                4/2/89 16:07:35
             Фиг. 10.12 Подпрограмма для программы на ФОРТРАНе         Page     1-1
 
                                           PAGE ,132
                                           TITLE      Фиг. 10.12 Подпрограмма для программы на ФОРТРАНе
                                     FRAME      STRUC
              0000      ????              SAVEBP  DW ?
              0002      ????????          SAVERET DD ?
              0006      ????????          A    DD   ?          ; Указатель на параметр
              000A                        FRAME      ENDS
 
              0000                        CODE SEGMENT 'CODE'
                                     DGROUP  GROUP    DATA
                                           ASSUME  CS:CODE,DS:DGROUP,ES:DGROUP,SS:DGROUP
              0000                        TIMER      PROC FAR
                                           PUBLIC  TIMER          ; Указание программе LINK на расположение
                                                             ;  программы TIMER
              0000      55                      PUSH BP
              0001      8B EC                   MOV  BP,SP            ; Загрузка адреса стека
              0003      B4 00                   MOV  AH,0
              0005      CD 1A                   INT  1Ah        ; Вызов BIOS для получения даты и времени
              0007      C4 5E 06                LES  BX,[BP].A  ; Загрузка адреса поля параметров
              000A      26: 89 17               MOV  ES:[BX],DX   ; Сохранение младшей части времени
              000D      26: 89 4F 02                  MOV  ES:[BX+2],CX     ; Сохранение старшей части времени
              0011      5D                      POP  BP
              0012      CA 0004                  RET  4          ; Возврат с удалением параметров из стека
              0015                        TIMER      ENDP
              0015                        CODE ENDS
                                           END
 
      Фиг. 10.12 Ассемблерная процедура для программы на Фортране
      На Фиг.  10.12 представлена подпрограмма на языке ассемблера -
    процедура TIMER.  В этой несложной программе для считывания
    текущего времени и сохранения полученного значения в двойном слове
    используется обращение к BIOS.  Здесь нам необходимо рассмотреть
    способ передачи параметров из программы на Фортране в подпрограмму
    на языке ассемблера.
 
      На Фиг.10.13 показано содержимое стека в начальный момент
    выполнения подпрограммы на языке ассемблера.  Точно так же, как
    интерпретатор Бейсика, программа на Фортране помещает адрес
    параметра в стек.  Однако компиляторы Фортрана и Паскаля передают
    указатель длиной в два слова, а не одно только смещение параметра.
    Это означает, что программа на языке ассемблера, прежде чем
    получить доступ к параметру, должна установить как сегментный
    регистр, так и адрес смещения.  Если бы параметров было более
    одного, то программа на Фортране перед вызовом поместила бы в стек
    значения адресов и остальных параметров.
 
                       ГДДДДДДДДДДДДґ
                  SPДДДД>і Смещение   і
                       і возврата   і
                       ГДДДДДДДДДДДДґ
                       і Сегмент      і
                       і возврата   і
                       ГДДДДДДДДДДДДґ
                       і Смещение   і
                       і аргумента  і
                       ГДДДДДДДДДДДДґ
                       і Сегмент      і
                       і аргумента  і
                       ГДДДДДДДДДДДДґ
 
      Фиг. 10.13 Стек для вызова процедуры в Фортране
 
      Подпрограмма TIMER на Фиг.  10.12 адресует стек, помещая в него
    регистр BP и устанавливая его на вершину стека.Структура FRAME
    помогает идентифицировать разные значения в стеке после того как
    программа сохранит в нем значение BP.  Команда LES BX,[BP]+A
    помещает адрес параметра в пару регистров ES:BX.  Используя этот
    адрес, программа помещает четырехбайтовое значение текущего времени
    в четырехбайтовую целую переменную.
 
      Заметим, что процедура TIMER извлекает адрес параметра из стека
    при выполнении команды возврата точно так же, как это делалось в
    программах на языке Бейсик.  Заметим также, что в этой ассемблерной
    программе для идентификации имени TIMER используется оператор
    PUBLIC.  Делается это для того, чтобы редактор связей мог найти
    подпрограмму и правильно связать ее с программой на Фортране.  Для
    интерпретатора Бейсика такой необходимости не было, поскольку
    программа на Бейсике не редактировалась совместно с программой на
    языке ассемблера.




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