netlib.narod.ru< Назад | Оглавление | Далее >

3.11. Реализация встроенного ассемблера

Приводимый ниже текст является законченной реализацией встроенного структурного ассемблера для форт-систем на базе микропроцессора К580. В оттранслированном виде он занимает около 1300 байт и является типичным для 8-разрядных микропроцессоров. Для 16- или 32-разрядных процессоров в силу их большей сложности объем текста больше. Но даже в этом случае объем исходного текста и скомпилированного кода существенно меньше, чем для традиционных ассемблеров.

  (  FORTH-83 АССЕМБЛЕР ДЛЯ К580 ТЕМЯШКИНО  1985 )
  VOCABULARY ASSEMBLER
  ASSEMBLER DEFINITIONS
             (  МАШИННЫЕ КОМАНДЫ  )
  DECIMAL       : 8* 2* 2* 2* ;
  4 CONSTANT H  5 CONSTANT L  7 CONSTANT A  6 CONSTANT PSW
  2 CONSTANT D  3 CONSTANT E  0 CONSTANT B  1 CONSTANT C
  6 CONSTANT M  6 CONSTANT SP
  : 1MI  ( ---> ) CREATE C, DOES> C@ C, ;
  : 2MI  ( ---> ) CREATE C, DOES> C@ + C, ;
  : 3MI  ( ---> ) CREATE C, DOES> C@ SWAP 8* + C, ;
  : 4MI  ( ---> ) CREATE C, DOES> C@ C, C,   ;
  : 5MI  ( ---> ) CREATE C, DOES> C@ C,  ,   ;

  HEX
  00 1MI NOP   76 1MI HLT   F3 1MI DI    FB 1MI EI
  07 1MI RLC   0F 1MI RRC   17 1MI RAL   1F 1MI RAR
  E9 1MI PCHL  F9 1MI SPHL  E3 1MI XTHL  EB 1MI XCHG
  27 1MI DAA   2F 1MI CMA   37 1MI STC   3F 1MI CMC
  80 2MI ADD   88 2MI ADC   90 2MI SUB   98 2MI SBB
  A0 2MI ANA   A8 2MI XRA   B0 2MI ORA   B8 2MI CMP
  09 3MI DAD   C1 3MI POP   C5 3MI PUSH  02 3MI STAX
  0A 3MI LDAX  04 3MI INR   05 3MI DCR   03 3MI INX
  0B 3MI DCX   C7 3MI RST   D3 4MI OUT   DB 4MI IN
  C6 4MI ADI   CE 4MI ACI   D6 4MI SUI   DE 4MI SBI
  E6 4MI ANI   EE 4MI XRI   F6 4MI ORI   FE 4MI CPI
  22 5MI SHLD  2A 5MI LHLD  32 5MI STA   3A 5MI LDA
  C4 5MI CNZ   CC 5MI CZ    D4 5MI CNC   DC 5MI CC
  E4 5MI CPO   EC 5MI CPE   F4 5MI CP    FC 5MI CM
  CD 5MI CALL  C9 1MI RET   C3 5MI JMP
  C0 1MI RNZ   C8 1MI RZ    D0 1MI RNC   D8 1MI RC
  E0 1MI RPO   E8 1MI RPE   F0 1MI RP    F8 1MI RM
  C2 5MI JNZ   CA 5MI JZ    D2 5MI JNC   DA 5MI JC
  E2 5MI JPO   EA 5MI JPE   F2 5MI JP    FA 5MI JM
  : MOV SWAP 8* 40 + + C, ;
  : MVI SWAP 8* 6  + C, C, ;
  : LXI SWAP 8* 1 + C, , ;
    (  КОДЫ УСЛОВИЙ ДЛЯ СТРУКТУР УПРАВЛЕНИЯ  )
  C2 CONSTANT 0=   D2 CONSTANT CS
  E2 CONSTANT PE   F2 CONSTANT 0<
    (  СТРУКТУРЫ УПРАВЛЕНИЯ  )
  DECIMAL
  : NOT    ( N:КОД УСЛОВИЯ ---> N1) 8 + ;
  : THEN   ( АДР,2 ---> ) 2 ?PAIRS HERE SWAP ! ;
  : IF     ( КОД ---> АДР,2 ) C, HERE 0 , 2 ;
  : ELSE   ( АДР,2 ---> АДР1,2) 2 ?PAIRS C3 IF ROT SWAP THEN  2 ;
  : BEGIN  ( ---> АДР,1 )  HERE 1 ;
  : UNTIL  ( АДР,1,КОД --->) SWAP 1 ?PAIRS С, , ;
  : AGAIN  ( АДР,1 --->) 1 ?PAIRS C3 C, , ;
  : WHILE  ( АДР,1,КОД ---> АДР,1,АДР1,4)  IF 2 + ;
  : REPEAT ( АДР,1,АДР1,4 --->) >R >R AGAIN R> R> 2- THEN ;

    (  РАБОТА С МЕТКАМИ  )
  10 CONSTANT LBLMAX ( МАКСИМАЛЬНОЕ ЧИСЛО ЛОКАЛЬНЫХ МЕТОК)
     VARIABLE LTABLE   LBLMAX 1+ 2*  ALLOT
  10 CONSTANT FRMAX ( МАКСИМАЛЬНОЕ ЧИСЛО ССЫЛОК ВПЕРЕД)
     VARIABLE FRTABLE  FRMAX  2* 2*  ALLOT
  : FRCHK   ( ---> ПРОВЕРКА НЕРАЗРЕШЕННЫХ ССЫЛОК ВПЕРЕД )
      FRMAX 0 DO I 2* 2* FRTABLE + @
      ABORT" НЕРАЗРЕШЕННАЯ ССЫЛКА ВПЕРЕД"
      LOOP ;
  : FRCLR   ( ---> ИНИЦИАЛИЗАЦИЯ ТАБЛИЦЫ ССЫЛОК ВПЕРЕД )
      FRTABLE FRMAX 2* 2* ERASE
      LTABLE LBLMAX 1+ 2* ERASE ;

  : FRRES   ( N:МЕТКА --->   РАЗРЕШЕНИЕ ССЫЛОК ВПЕРЕД )
      FRMAX 0 DO I 2* 2* FRTABLE + 2DUP @ =
      IF HERE OVER 2+ @ +! 0!
      ELSE DROP THEN
      LOOP ;
  : FRADD   ( N:МЕТКА ---> ДОБАВЛЕНИЕ ССЫЛКИ ВПЕРЕД В ТАБЛИЦУ )
      FRMAX 1+ 0
      DO FRMAX I = ABORT" СЛИШКОМ МНОГО ССЫЛОК ВПЕРЕД"
      I 2* 2* FRTABLE + DUP @ 0=
      IF 2DUP ! HERE 1+ SWAP 2+ ! LEAVE ELSE DROP THEN
      LOOP ;

    (   ОПРЕДЕЛЯЮЩИЕ ВХОЖДЕНИЯ МЕТОК )
  : !LT     CREATE , DOES> @  FRRES HERE SWAP 2* LTABLE + ! ;
    (   ИСПОЛЬЗУЮЩИЕ ВХОЖДЕНИЯ МЕТОК )
  : @LT     CREATE , DOES> @ DUP 2*
      LTABLE + @ SWAP OVER 0=
      IF FRADD THEN DROP ;
  1 !LT 1#:   2 !LT 2#:  3 !LT 3#:  4 !LT 4#:  5 !LT  5#:
  6 !LT 6#:   7 !LT 7#:  8 !LT 8#:  9 !LT 9#: 10 !LT 10#:
  1 @LT 1#    2 @LT 2#   3 @LT 3#   4 @LT 4#   5 @LT  5#
  6 @LT 6#    7 @LT 7#   8 @LT 8#   9 @LT 9#  10 @LT 10#
    (   ПЕРЕКЛКЮЧЕНИЕ В АССЕМБЛЕР  )
  FORTH DEFINITIONS
  : BEG-ASM [ ASSEMBLER ] FRCLR [ FORTH ] ASSEMBLER
       !CSP ;
  : END-ASM [ ASSEMBLER ] FRCHK [ FORTH ] ?CSP;

В приведенном тексте можно выделить четыре группы определений: машинные команды, структуры управления, метки и стандартные слова для создания определений в машинном коде. Помимо них данный текст определяет ряд вспомогательных слов.

Машинные команды на языке ассемблера записываются в обратной польской форме, принятой для языка Форт: <операнды> <операция>, где <операнды> — слова, вычисляющие на стеке размещения операндов данной машинной команды, а <операция> — ее мнемоника. Для обозначения регистров микропроцессора К580 зарезервированы слова А В С D E H L, для задания регистровых пар используются слова В D H SP PSW, для косвенной адресации через регистровую пару HL — слово М. При исполнении слов, обозначающих регистры, регистровые пары и косвенную адресацию, на стеке оставляются значения, соответствующие принятым в системе команд К580 обозначениям для регистров и регистровых пар:

  A  B  C  D  E  H  L  M   SP PSW
  7  0  1  2  3  4  5  6   6   6

При исполнении мнемоники машинной команды на вершину словаря компилируется соответствующая машинная инструкция. Размещения операндов при этом снимаются со стека. Порядок вычисления операндов машинной команды соответствуют порядку написания операндов на обычном языке ассемблера.

Ниже приведены для сравнения записи машинных команд на обычном языке ассемблера и на языке ассемблера данной форт-системы:

  HLT              HLT
  DAD  SP          SP DAD
  PUSH PSW         PSW PUSH
  CMP  C           C CMP
  MOV  A,M         A M MOV
  MVI  B,2         B 2 MVI
  LXI  D,120+8     D 120 8 + LXI
  CALL 5002H       HEX 5002 CALL DECIMAL

Для определения мнемоник используются определяющие слова, соответствующие форматам машинных команд (1MI, ..., 5MI). Все они имеют одинаковую создающую часть, которая компилирует в поле параметров статьи для мнемоники однобайтный код маски для кода данной команды, который снимается со стека. Исполняющая часть определений, используя маску и размещения операндов, которые она снимает со стека, компилирует двоичный код, соответствующий данной команде. Так, например, через слово 1MI определяются машинные команды, не имеющие операндов. При исполнении мнемоники такой команды на вершину словаря компилируется однобайтный код операции. Слово 3MI определяет мнемоники команд, имеющих один операнд — номер регистра. Этот номер занимает разряды со 2 по 4 в однобайтном коде команды. Поэтому исполняющая часть сдвигает свой операнд — номер регистра — влево на 3 разряда исполнением слова 8* и добавляет к нему маску команды. Получившийся однобайтный код компилируется на вершину словаря. Три команды — MOV, MVI и LXI — не подходят под описанные общие форматы, поэтому они определяются непосредственно через двоеточие.

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

Условный оператор в полной или сокращенной форме записывается следующим образом:

  <КОД-УСЛОВИЯ> IF <ЧАСТЬ-ТО> ELSE <ЧАСТЬ-ИНАЧЕ> THEN
  <КОД-УСЛОВИЯ> IF <ЧАСТЬ-ТО> THEN

Часть «то» выполняется, только если в разрядах PSW установлен заданный «код условия», в противном случае выполняется часть «иначе», если она есть.

Циклы могут быть записаны в одной из трех форм:

  BEGIN <ТЕЛО-ЦИКЛА> AGAIN
  BEGIN <ТЕЛО-ЦИКЛА> <КОД-УСЛОВИЯ> UNTIL
  BEGIN <ТЕЛО-1> <КОД-УСЛОВИЯ> WHILE <ТЕЛО-2> REPEAT

Цикл BEGIN-AGAIN является бесконечным, BEGIN-UNTIL прекращает выполнение при указанном коде условия, в цикле BEGIN-WHILE-REPEAT, наоборот, указанный код условия задает продолжение цикла.

Для указания кода условия в ассемблере используются следующие слова: 0= — установлен флаг Z, 0< — флаг S, CS — флаг C, PE — флаг P. Для инвертирования кода условия используется слово NOT.

Структурные операторы компилируют на своем месте команды безусловных и условных переходов с указанным условием.

Для работы с явно задаваемыми метками в ассемблер включены слова вида 1#: 2#: ... 10#: и 1# 2# ... 10#. Слова первой группы задают определение метки, слова второй — использование. Метки имеют строго локальный характер, т.е. эти слова можно использовать только внутри определений через CODE и между словами ;CODE и END-CODE. Наряду с метками допускается использование ассемблерных структур управления.

Локальные метки рекомендуется использовать только в трехбайтных командах типа JMP, CALL, LXI. Уже определенные локальные метки могут участвовать в арифметических и стековых операциях; использующие вхождения меток, определяющие вхождения которых вводятся позднее (ссылки вперед), могут участвовать только в операциях, сводящихся к добавлению к ним числа со знаком.

Для реализации работы с метками ассемблер имеет таблицу меток LTABLE и таблицу ссылок вперед FRTABLE. Их размер определяет максимальное число разных меток и ссылок вперед в пределах одного определения в машинном коде (от слова CODE или ;CODE до слова END-CODE). Для каждой возможной метки соответствующий элемент таблицы LTABLE содержит нуль, если метка еще не определена, или адрес, который является ее значением, если метка уже определена. Входом в эту таблицу служит номер метки. В таблице FRTABLE для каждой ссылки вперед хранятся два значения: номер метки и адрес в словаре, по которому нужно вписать ее значение. По этому адресу скомпилировано значение смещения, которое нужно добавить как число со знаком к значению данной метки.

Слова для использующих вхождений меток определяются через @LT, например 1 @LT 1#. Исполнение определенного таким образом слова 1#, обозначающего метку номер 1, состоит в обращении к таблице LTABLE по индексу 1. Если там стоит нуль, т.е. метка номер 1 еще не определена, то этот нуль выдается на стек в качестве смещения от значения метки, которое определится позднее. Одновременно в таблицу FRTABLE заносится запись о данной ссылке вперед. В качестве адреса, куда нужно будет впоследствии вписать значение метки, берется HERE 1+. Здесь используется тот факт, что в микропроцессоре К580 операнд-адрес занимает 2 байта, следующие за однобайтным кодом операции.

Слова для определения меток определяются через слово !LT, например 1 !LT 1#:. Исполнение определенного таким образом слова 1#: определяет метку номер 1 как текущий адрес вершины словаря HERE. Его действие состоит в том, что выполняется просмотр таблицы FRTABLE с разрешением всех накопившихся ссылок на данную метку, после чего запись о данной метке заносится в таблицу LTABLE.

Последнюю группу определений составляют слова для доступа к встроенному ассемблеру при компиляции машинного кода. Помимо стандартных форт-слов CODE, ;CODE и END-CODE здесь определяются слова LABEL и NEXT;. Первое используется для создания именованных подпрограмм, к которым можно обращаться из машинного кода. Второе является сокращением для часто встречающегося окончания ассемблерных определений: NEXT JMP END-CODE. В качестве примера приведем определение слова ><, которое меняет местами байты в переданном на стеке двухбайтном значении:

  CODE ><  ( N1 ---> N2)   H POP
    A L MOV  L H MOV  H A MOV  H PUSH  NEXT;

Приведенная реализация встроенного ассемблера может быть усовершенствована по нескольким направлениям. Прежде всего, увеличив константы LBLMAX и FRMAX и добавив новые определения для слов, обозначающих метки, можно увеличить количество разных меток и ссылок вперед, которые разрешается использовать в ассемблерном определении. Далее можно ввести контроль правильности операндов, включив соответствующие проверки в исполняющую часть определяющих слов для мнемоник команд. Для проверки числа элементов на стеке обычно используется глобальная ячейка CSP и слово !CSP, которое засылает в нее текущий адрес вершины стека. Интересным расширением является возможность введения макрокоманд. Макрокоманды без локальных меток можно определять обычным образом через двоеточие:

  INRN ( R:РЕГИСТР,N:ЧИСЛО РАЗ ---> )
    [ ABSEMBLER ] 0 DO DUP INR LOOP  DROP ;

При исполнении текста А 3 INRN будут скомпилированы три команды А INR.

Если же макрорасширение должно порождать обращения к адресам через локальные метки, то потребуется более основательное расширение ассемблера.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz