(*~\Глагол\приложкемяLink\МПГ2009 (компилируется, но НЕ раб.?)\~~~~~~~~~~~~~~~*)
(**)                                                     ОТДЕЛ Узел;
(****************************************************************************** 
 * НАЗНАЧЕНИЕ: работа с узлами
 * ВНИМАНИЕ: зСместить, зОбнулить пока не работают !
 ******************************************************************************)

ИСПОЛЬЗУЕТ 
  ОБХОД,
        (*  \Глагол\              *)
  Асм     ИЗ "..\..\Отделы\Заграница\",

  Слово,
  Ядро,
  Рег,
  Код,
  Данные,
  Настрой,
  Ошибка;
                    (*--
                            общедоступные ПОСТоянные 
                      --*)
ПОСТ
                              (* род узлов *)
  уПустой-     =20;
  уАдрО-       = 4; (* общие переменные отдела *) 
  уАдрС-       = 1;  
  уАдрСС-      = 2; (* доступ к рядам со сдвигаемым смещением 2^.. *)
  уАдрЗС-      = 9; (* занесение в стек *)
  уАдрСАдрС-   = 3;  
  уПост-       = 5;
  уРон-        = 6; (* регистр общего назначения *)
  уРпер-       =21; (* регистровая переменная быстрой задачи *)
  уКодУсл-     = 8;
  уВид-        =14;
  уЗадача-     =15;
  уВстрЗадача- =16;
(*
 роду      |  ро       a        b       Обращение к:
 -------------------------------------------------------------------------------
 уПост     |  -        знач     -        знач
 уРон      |  р        -        -        р
 уРпер     |  р        -        -        р
 уАдрО     |  -        смещ     -       [имя+смещ]       
 уАдрС     |  ро       смещ     -       [ро+смещ]       
 уАдрСС    |  ро       ср       сдвиг   [ро+(ср LSL сдвиг)]
 уАдрЗС    |  рс(SP)   смещ(-4) -       [рс], рс+=смещ
 уАдрСАдрС |  ро       смещ1    смещ2   [[ро+смещ1]+смещ2]
 уКодУсл   |  условие  мВкл     мОткл
 
  р  - регистр
  ро - регистр основы
  ср - сдвигаемый регистр смещения
  рс - регистр стога  *)


                            (*--- общедоступные ВИДы ---*)

(*------------------------------------ Вид -----------------------------------*)
ВИД
  нВид- = НАБОР
    роду+:ЦЕЛ;
    ро+,a+,b+:ЦЕЛ;
    вид+:Данные.ДкВиду;
    пон+:Данные.ДкПонятию;
    толькочт+:КЛЮЧ
  КОН;


(*-оооооооооооооо- опережающие определения/заготовки задач -ооооооооооооооооо-*)

ЗАДАЧА ^ВыставитьКУ(у+:Узел.нВид);


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Создать-(пон:Данные.ДкПонятию;
                 у+:Узел.нВид);
УКАЗ
  у.толькочт:=ОТКЛ;
  ВЫБРАТЬ пон.родп ИЗ
  | Данные.пПер:
      ЕСЛИ (Данные.прНеизменяемая В пон.признаки) И
          ((Данные.прВложенная    В пон.признаки) ИЛИ НЕ (Данные.прТекущегоОтдела В пон.признаки)) ТО
        у.толькочт:=ВКЛ
      КОН;
      ЕСЛИ Данные.прБыстрая В пон.признаки ТО
        у.роду:=уРпер;
        у.ро:=пон.адр
      ИНАЧЕ
        ЕСЛИ Данные.прВложенная В пон.признаки ТО
          у.роду:=уАдрС;
          у.ро:=Рег.FP
        ИНАЧЕ
          у.роду:=уАдрО
        КОН;
        у.a:=пон.адр
      КОН
  | Данные.пСсылка:
      ЕСЛИ Данные.прНеизменяемая В пон.признаки ТО
        у.толькочт:=ВКЛ
      КОН;
      ЕСЛИ Данные.прБыстрая В пон.признаки ТО
        у.роду:=уАдрС;
        у.ро:=пон.адр;
        у.a:=0
      ИНАЧЕ
        у.роду:=уАдрСАдрС;
        у.ро:=Рег.FP;
        у.a:=пон.адр;
        у.b:=0 
      КОН
  | Данные.пПост:
      у.роду:=уПост;
      у.a:=пон.адр
  | Данные.пВид:
      у.роду:=уВид
  | Данные.пЗадача:
      у.роду:=уЗадача
  | Данные.пВстрЗадача:
      у.роду:=уВстрЗадача
  КОН;
  у.пон:=пон;
  у.вид:=пон.вид
КОН Создать;

(******************************************************************************)
ЗАДАЧА ОпредЦелВид-(у+:Узел.нВид);
УКАЗ
  ЕСЛИ  (Настрой.МинЦел8  <= у.a) И (у.a <= Настрой.МаксЦел8) ТО
    у.вид:=Данные.цел8вид
  АЕСЛИ (Настрой.МинЦел16 <= у.a) И (у.a <= Настрой.МаксЦел16) ТО
    у.вид:=Данные.цел16вид
  АЕСЛИ (Настрой.МинЦел32 <= у.a) И (у.a <= Настрой.МаксЦел32) ТО
    у.вид:=Данные.цел32вид
  ИНАЧЕ
    у.вид:=Данные.цел64вид
  КОН
КОН ОпредЦелВид;

(******************************************************************************)
ЗАДАЧА СоздатьЦелПост-(у+:Узел.нВид; ц:ЦЕЛ);
УКАЗ
  у.роду:=уПост;
  у.a:=ц;
  ОпредЦелВид(у)
КОН СоздатьЦелПост;

(******************************************************************************)
ЗАДАЧА СоздатьКУ-(у+:Узел.нВид; ку:ЦЕЛ);
УКАЗ
  у.роду:=уКодУсл;
  у.вид:=Данные.ключвид;
  у.ро:=ку;
  у.a:=Код.ПолучитьМетку();
  у.b:=Код.ПолучитьМетку()
КОН СоздатьКУ;

(******************************************************************************)
ЗАДАЧА ПереходПоОтклНа-(у+:Узел.нВид):ЦЕЛ;
(* Цель:  условный переход по ОТКЛ вперёд на метку <у.b>
 * До:    <у> - узел с ключём
 * Ответ: метка <у.b> *)
УКАЗ
  ВыставитьКУ(у);
  Код.ПереходПоКУ(у.b,Код.ОбратныйКУ(у.ро));
  Код.ПоставитьМетку(у.a);
  ВОЗВРАТ у.b
КОН ПереходПоОтклНа;

(******************************************************************************)
ЗАДАЧА ПовторятьДо-(у+:Узел.нВид; мПовторять:ЦЕЛ);
(* Цель:  отработка условия перехода у ПОВТОРЯТЬ ДО
 * До:    <у>          - узел с ключём ДО
 *        <мПовторять> - метка начала ПОВТОРЯТЬ
 * После: 
 *        условный переход по ОТКЛ и по метке <у.b> (ОТКЛ) назад в <мПовторять>
 *        в конце будет метка <у.a> (ВКЛ) *)
УКАЗ                          
  ВыставитьКУ(у);
  Код.ПереходПоКУ(у.a,у.ро);
Код.ПоставитьМетку(у.b);
  Код.ПереходНа(мПовторять);
Код.ПоставитьМетку(у.a)
КОН ПовторятьДо;

(******************************************************************************)
ЗАДАЧА Освободить-(у+:Узел.нВид);
УКАЗ
  ЕСЛИ НЕ (у.роду В {уПустой,уПост,уРпер,уКодУсл}) ТО
    Рег.ОсвободитьРОН(у.ро);
    ЕСЛИ у.роду = уАдрСС ТО
      Рег.ОсвободитьРОН(у.a)
    КОН
  КОН;
  у.роду:=уПустой
КОН Освободить;

(******************************************************************************)
ЗАДАЧА АдрОвАдрС(у+:Узел.нВид);
(* адресацию переменных отдела переводит на адресацию по смещению *)
ПЕР
  ро:ЦЕЛ; (* новый ро *)
УКАЗ
  ПРОВЕРИТЬ(у.роду В {уАдрО,уЗадача});
  Рег.ЗанятьРОН(ро); 
  Код.ЗагрузитьОбщАдр(ро,у.пон);
  ЕСЛИ у.роду = уЗадача ТО
    у.a:=0
  КОН;
  у.роду:=уАдрС;
  у.ро:=ро
КОН АдрОвАдрС;

(******************************************************************************)
ЗАДАЧА НастроитьАдрС(у+:Узел.нВид);
(* приводит ро в соответствии с текущим уровнем задачи *)
ПЕР
  ро:ЦЕЛ;      (* новый ро *)
  разница:ЦЕЛ; (* разница в уровнях *)
УКАЗ
  ЕСЛИ (у.роду В {уАдрС,уАдрСС,уАдрСАдрС}) 
     И (у.ро = Рег.FP)
     И (у.пон # ПУСТО)
     И (у.пон.обл.уровень < Данные.уровень) ТО
    разница:=Данные.уровень-у.пон.обл.уровень;
    ЕСЛИ Данные.быстрая ТО (* SL уже в FP *)
      УМЕНЬШИТЬ(разница)
    КОН;
    ЕСЛИ разница > 0 ТО
      Рег.ЗанятьРОН(ро); 
      ПОКА разница > 0 ВЫП
        Код.ПЗС1(Код.LDR,ро,у.ро,8);
        у.ро:=ро;
        УМЕНЬШИТЬ(разница)
      КОН
    КОН;
  КОН
КОН НастроитьАдрС;

(******************************************************************************)
ЗАДАЧА АдрСАдрСвАдрС(у+:Узел.нВид);
(* До:    у.роду = уАдрСАдрС
 * После: у.роду = уАдрС *)
ПЕР
  ро:ЦЕЛ; (* новый ро *)
УКАЗ
  ПРОВЕРИТЬ(у.роду = уАдрСАдрС);
  Рег.ЗанятьРОН(ро); (* чтобы не затереть FP *)
  Код.ПЗС1(Код.LDR,ро,у.ро,у.a);
  у.a:=у.b;
  у.ро:=ро;
  у.роду:=уАдрС
КОН АдрСАдрСвАдрС;

(******************************************************************************)
ЗАДАЧА ПереписатьВРег-(у+:Узел.нВид):ЦЕЛ;
(* Цель:  переписать значение <у> в регистр,
 *        оставляя возможность повторного использования <у> 
 * До:    у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС}
 * Возвр: регистр, содержащий полученное значение *)
ПЕР
  ку:ЦЕЛ; (* код условия *)
  цр:ЦЕЛ; (* целевой регистр *)
  метка:ЦЕЛ;
УКАЗ
  Рег.ЗанятьРОН(цр);
  НастроитьАдрС(у);
  ЕСЛИ у.роду = уАдрСАдрС ТО
    АдрСАдрСвАдрС(у)
  АЕСЛИ у.роду В {уАдрО,уЗадача} ТО
    АдрОвАдрС(у)
  КОН;
  ВЫБРАТЬ у.роду ИЗ
  | уРпер:
      Код.ОД(Код.MOV,цр,0,у.ро,0,0)
  | уПост:
      Код.ЗагрузитьПост(цр,у.a)
  | уАдрСС:
      ВЫБРАТЬ у.вид.родв ИЗ
        Данные.вЯчейка,Данные.вЦел8,Данные.вКлюч:
          Код.ПЗС(Код.LDRB,цр,у.ро,у.a,у.b)
      | Данные.вЦел16,Данные.вЗнак:
          (* у.а заменили на цр *)
          Код.ОД(Код.MOV,цр,0,у.a,Код.LSL,у.b+16);  (* LSL y.b *)
          ЕСЛИ у.вид.родв = Данные.вЗнак ТО
            Код.УЗС(Код.LDRH, цр,у.ро,цр)
          ИНАЧЕ
            Код.УЗС(Код.LDRSH,цр,у.ро,цр)
          КОН
      | Данные.вДоступ,Данные.вЗадача,Данные.вЦел32,Данные.вМнож,Данные.вВещ32:
          Код.ПЗС(Код.LDR,цр,у.ро,у.a,у.b)
      КОН
  | уАдрС:
      ВЫБРАТЬ у.вид.родв ИЗ
        Данные.вЯчейка,Данные.вЦел8,Данные.вКлюч:
          ЕСЛИ у.вид.родв = Данные.вЦел8 ТО
            Код.ПЗС1(Код.LDRSB,цр,у.ро,у.a)
          ИНАЧЕ
            Код.ПЗС1(Код.LDRB,цр,у.ро,у.a)
          КОН
      | Данные.вЦел16,Данные.вЗнак:
          ЕСЛИ у.вид.родв = Данные.вЗнак ТО
            Код.УЗС1(Код.LDRH, цр,у.ро,у.a)
          ИНАЧЕ
            Код.УЗС1(Код.LDRSH,цр,у.ро,у.a)
          КОН
      | Данные.вДоступ,Данные.вЗадача,Данные.вЦел32,Данные.вМнож,Данные.вВещ32:
          Код.ПЗС1(Код.LDR,цр,у.ро,у.a)
      КОН
  | уКодУсл:
      ку:=у.ро;
      ЕСЛИ (у.a = 0) И (у.b = 0) ТО
        (* метки пусты, можно отработать попроще *)
        Код.будетКУ:=Код.ОбратныйКУ(ку);
        Код.ОД1(Код.MOV,цр,0,0);
        Код.будетКУ:=ку;
        Код.ОД1(Код.MOV,цр,0,1)
      ИНАЧЕ
        метка:=Код.ПолучитьМетку();
        Код.ПереходПоКУ(у.b,Код.ОбратныйКУ(ку));
Код.ПоставитьМетку(у.a);
        Код.ОД1(Код.MOV,цр,0,1);
        Код.ПереходНа(метка);
Код.ПоставитьМетку(у.b);
        Код.ОД1(Код.MOV,цр,0,0);
Код.ПоставитьМетку(метка);
      КОН
  ИНАЧЕ
    цр:=цр
  КОН;
  ВОЗВРАТ цр
КОН ПереписатьВРег;

(******************************************************************************)
ЗАДАЧА ПеренестиВРОН-(у+:Узел.нВид);
(* До:    у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уРон} *)  
ПЕР
  цр:ЦЕЛ; (* целевой регистр *)
УКАЗ
  ЕСЛИ у.роду = уРон ТО ВОЗВРАТ КОН;
  цр:=ПереписатьВРег(у);
  Освободить(у);
  у.ро:=цр;
  у.роду:=уРон
КОН ПеренестиВРОН;

(******************************************************************************)
ЗАДАЧА ПеренестиВРег-(у+:Узел.нВид);
(* До:    у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уРон} *)  
УКАЗ
  ЕСЛИ у.роду # уРпер ТО
    ПеренестиВРОН(у)
  КОН
КОН ПеренестиВРег;

(******************************************************************************)
ЗАДАЧА ПеренестиВТребРег-(у+:Узел.нВид; р:ЦЕЛ);
(* До:    у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уРон} *)
УКАЗ
  ЕСЛИ у.роду В {уРон,уРпер} ТО 
    ЕСЛИ у.ро # р ТО
      Рег.Нужен(р);
      Рег.ЗанятьРОН(р);
      Код.ОД(Код.MOV,р,0,у.ро,0,0);
      ЕСЛИ у.роду = уРпер ТО
        у.роду:=уРон
      ИНАЧЕ
        Рег.ОсвободитьРОН(у.ро)
      КОН;
      у.ро:=р
    КОН
  ИНАЧЕ
    Рег.Нужен(р);
    ПеренестиВРОН(у);
    Рег.Нужен(-1)
  КОН
КОН ПеренестиВТребРег;

(******************************************************************************)
ЗАДАЧА Переписать-(уа+,уб+:Узел.нВид); 
(* Цель:  переписать <уа> в <уб>
 * До:    уб.роду В {уРон,уАдрО,уАдрС,уАдрСС,уАдрЗС,уАдрСАдрС}
 * После: уа и уб пустые *)
УКАЗ
  ЕСЛИ уб.роду = уРон ТО 
    Рег.ОсвободитьРОН(уб.ро);
    ПеренестиВТребРег(уа,уб.ро)
  АЕСЛИ уб.роду = уРпер ТО 
    ПеренестиВТребРег(уа,уб.ро)
  ИНАЧЕ
    ПеренестиВРег(уа);
    ЕСЛИ уб.роду = уАдрСАдрС ТО
      АдрСАдрСвАдрС(уб)
    АЕСЛИ уб.роду В {уАдрО,уЗадача} ТО
      АдрОвАдрС(уб)
    КОН;
    НастроитьАдрС(уб);
    ЕСЛИ уб.роду = уАдрСС ТО
      ВЫБРАТЬ уб.вид.родв ИЗ
        Данные.вЯчейка,Данные.вЦел8,Данные.вКлюч:
          Код.ПЗС(Код.STRB,уа.ро,уб.ро,уб.a,уб.b)
      | Данные.вЦел16,Данные.вЗнак:
          Код.ОД(Код.MOV,уб.a,0,уб.a,Код.LSL,уб.b+16); (* LSL уб.b *)
          Код.УЗС(Код.STRH,уа.ро,уб.ро,уб.a)
      | Данные.вДоступ,Данные.вЗадача,Данные.вЦел32,Данные.вМнож,Данные.вВещ32:
          Код.ПЗС(Код.STR,уа.ро,уб.ро,уб.a,уб.b)
      КОН
    АЕСЛИ уб.роду = уАдрЗС ТО
      Код.ВСтог(уа.ро)
    ИНАЧЕ
      ВЫБРАТЬ уб.вид.родв ИЗ
        Данные.вЯчейка,Данные.вЦел8,Данные.вКлюч:
          Код.ПЗС1(Код.STRB,уа.ро,уб.ро,уб.a)
      | Данные.вЦел16,Данные.вЗнак:
          Код.УЗС1(Код.STRH,уа.ро,уб.ро,уб.a)
      | Данные.вДоступ,Данные.вЗадача,Данные.вЦел32,Данные.вМнож,Данные.вВещ32:
          Код.ПЗС1(Код.STR,уа.ро,уб.ро,уб.a)
      КОН
    КОН
  КОН;
  Освободить(уа);
  Освободить(уб)
КОН Переписать;

(******************************************************************************)
ЗАДАЧА ВыставитьКУ(у+:Узел.нВид);
УКАЗ
  ЕСЛИ у.вид.родв # Данные.вКлюч ТО
    Ошибка.Отметить(Ошибка.ОЖИДАЕТСЯ_КЛЮЧ)
  КОН;
  ЕСЛИ у.роду # уКодУсл ТО
    ЕСЛИ у.роду = уПост ТО
      ЕСЛИ у.a = 0 ТО
        СоздатьКУ(у,Код.NV)
      ИНАЧЕ
        СоздатьКУ(у,Код.AL)
      КОН
    ИНАЧЕ
      ПеренестиВРег(у);
      Код.будетS:=ВКЛ;
      Код.ОД1(Код.CMP,0,у.ро,0);
      Освободить(у);
      СоздатьКУ(у,Код.NE)
    КОН
  КОН
КОН ВыставитьКУ;

(******************************************************************************)
ЗАДАЧА СнятьКУ-(у+:Узел.нВид);
УКАЗ
  ЕСЛИ у.роду = уКодУсл ТО
    ЕСЛИ  у.ро = Код.AL ТО
      у.роду:=уПост;
      у.a:=1 (* ВКЛ *)
    АЕСЛИ у.ро = Код.NV ТО
      у.роду:=уПост;
      у.a:=0 (* ОТКЛ *)
    КОН
  КОН
КОН СнятьКУ;

(******************************************************************************)
ЗАДАЧА АдресВРег-(у+:Узел.нВид);
(* загружает адрес <у> в регистр
 * До:    у.роду В {уПост+вЦепь,уАдрО,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уРон} *)
ПЕР
  цр:ЦЕЛ; (* целевой регистр *)
УКАЗ
  ЕСЛИ (у.роду = уПост) И (у.вид.родв = Данные.вЦепь) ТО
    Рег.ЗанятьРОН(цр);
    ЕСЛИ у.пон.адр = 0 ТО
      Код.ВводЦепочки(у.пон)
    КОН;
    Код.ЗагрузитьЦепьАдр(цр,у.пон.адр)
  ИНАЧЕ
    ЕСЛИ у.роду В {уАдрО,уЗадача} ТО
      АдрОвАдрС(у)
    КОН;
    НастроитьАдрС(у);
    ЕСЛИ у.ро = Рег.FP ТО
      Рег.ЗанятьРОН(цр)
    ИНАЧЕ
      цр:=у.ро
    КОН;
    ВЫБРАТЬ у.роду ИЗ
      уАдрС:
        ЕСЛИ у.a # 0 ТО
          Код.ОД1(Код.ADD,цр,у.ро,у.a)
        АЕСЛИ цр # у.ро ТО
          Код.ОД(Код.MOV,цр,0,у.ро,0,0)
        КОН
    | уАдрСС:
        Код.ОД(Код.ADD,цр,у.ро,у.a,Код.LSL,у.b+16) 
    | уАдрСАдрС:
        Код.ПЗС1(Код.LDR,цр,у.ро,у.a);
        ЕСЛИ у.b # 0 ТО
          Код.ОД1(Код.ADD,цр,цр,у.b)
        КОН
    КОН;
    ЕСЛИ цр # у.ро ТО
      Рег.ОсвободитьРОН(у.ро)
    КОН
  КОН;
  у.роду:=уРон;
  у.ро:=цр
КОН АдресВРег;

(******************************************************************************)
ЗАДАЧА ВСтог-(у+:Узел.нВид); 
(* Цель:  сохраняет <у> в стеке и освобождает <у>
 * До:    у.роду В {уРон,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у пустой *)
УКАЗ
  ПеренестиВРег(у);
  Код.ВСтог(у.ро);
  Освободить(у)
КОН ВСтог;

(******************************************************************************)
ЗАДАЧА ЦелВСтог(ц:ЦЕЛ); 
(* Заносит <ц> в стек. *)
ПЕР
  y:Узел.нВид;
УКАЗ
  СоздатьЦелПост(y,ц);
  ВСтог(y)
КОН ЦелВСтог;

(******************************************************************************)
ЗАДАЧА РазмерРяда(у+:Узел.нВид); 
(* Цель:  получить число слагаемых ряда
 * До:    у.вид.родв В {вРяд,вОРяд,вЦепь,вОЦепь,вОЯчейки}
 * До:    у.роду В {уРон,уРпер,уПост,уКодУсл,уАдрС,уАдрСС,уАдрСАдрС}
 * После: у.роду В {уПост,уРпер,уАдрС}
 *        значение регистров не изменяется *)
УКАЗ
  ЕСЛИ у.вид.родв В {Данные.вОРяд,Данные.вОЦепь,Данные.вОЯчейки} ТО
    ЕСЛИ Данные.быстрая ТО
      ПРОВЕРИТЬ(у.роду = уАдрС);
      у.роду:=уРпер;
      УВЕЛИЧИТЬ(у.ро,у.вид.размер)
    ИНАЧЕ
      ПРОВЕРИТЬ(у.роду = уАдрСАдрС);
      у.роду:=уАдрС;
      УВЕЛИЧИТЬ(у.a,4*у.вид.размер)
    КОН;
    у.вид:=Данные.цел32вид
  АЕСЛИ у.вид.родв В {Данные.вРяд,Данные.вЦепь} ТО
    СоздатьЦелПост(у,у.вид.размер ДЕЛИТЬ у.вид.овид.размер)
  ИНАЧЕ
    ПРОВЕРИТЬ(ОТКЛ)
  КОН
КОН РазмерРяда;

(******************************************************************************)
ЗАДАЧА ОД(нкд:ЦЕЛ; уа+,уб+:Узел.нВид);
(* Цель:  уа':=уа нкд уб
 * После: уб пустой *)
УКАЗ
  ПеренестиВРОН(уа);
  ЕСЛИ уб.роду = уПост ТО
    Код.ОД1(нкд,уа.ро,уа.ро,уб.a)
  ИНАЧЕ
    ПеренестиВРег(уб);
    Код.ОД(нкд,уа.ро,уа.ро,уб.ро,0,0);
    Освободить(уб)
  КОН
КОН ОД;

(******************************************************************************)
ЗАДАЧА ОДсОбрЗап(нкд:ЦЕЛ; уа+,уб+:Узел.нВид);
(* Цель:  уа:=уа нкд уб
 * После: уб пустой *)
ПЕР
  уа1:Узел.нВид;
УКАЗ
  ПРОВЕРИТЬ(уа.роду # уПост);
  ЕСЛИ уа.роду В {уРон,уРпер} ТО
    уа1:=уа
  ИНАЧЕ
    уа1.роду:=уРон;
    уа1.вид:=уа.вид;
    уа1.ро:=ПереписатьВРег(уа)
  КОН;
  ЕСЛИ уб.роду = уПост ТО
    Код.ОД1(нкд,уа1.ро,уа1.ро,уб.a)
  ИНАЧЕ
    ПеренестиВРег(уб);
    Код.ОД(нкд,уа1.ро,уа1.ро,уб.ро,0,0);
    Освободить(уб)
  КОН;
  ЕСЛИ НЕ (уа.роду В {уРон,уРпер}) ТО
    Переписать(уа1,уа)
  КОН
КОН ОДсОбрЗап;

(******************************************************************************)
ЗАДАЧА Сравнить(уа+,уб+:Узел.нВид; ку:ЦЕЛ);
(* Цель:  уа:=уа ? уб
 * До:    ку - код условия для сравнения
 * После: уа.роду=УКодУсл, уб пустой *)
УКАЗ
  ПеренестиВРег(уа);
  ЕСЛИ уб.роду = уПост ТО
    Код.будетS:=ВКЛ;
    Код.ОД1(Код.CMP,0,уа.ро,уб.a)
  ИНАЧЕ
    ПеренестиВРег(уб);
    Код.будетS:=ВКЛ;
    Код.ОД(Код.CMP,0,уа.ро,уб.ро,0,0);
    Освободить(уб)
  КОН;
  Освободить(уа);
  СоздатьКУ(уа,ку)
КОН Сравнить;

(******************************************************************************)
ЗАДАЧА АдрПерРяда-(уа+,уб+:Узел.нВид);
(* уа <- адрес уа[уб] *)
ПЕР
  овид:Данные.ДкВиду; (* вид переменных ряда *)
  степень2:ЦЕЛ;    (* такая, что 2^степень2 = овид.размер *)
  родв:ЦЕЛ;
  смещ:ЦЕЛ;
  размеро:ЦЕЛ;
  уп:Узел.нВид;

  ЗАДАЧА Степень2(остаток:ЦЕЛ):КЛЮЧ;
  УКАЗ
    степень2:=0;
    ПОКА ЧЕТ(остаток) ВЫП
      остаток:=остаток ДЕЛИТЬ 2;
      УВЕЛИЧИТЬ(степень2)
    КОН;
    ВОЗВРАТ остаток = 1
  КОН Степень2;

УКАЗ
  ЕСЛИ НЕ (уб.вид.родв В Данные.множЦелых) ТО
    Ошибка.Отметить(Ошибка.НОМЕР_НЕ_ЦЕЛЫЙ)
  КОН;
  родв:=уа.вид.родв;
  ЕСЛИ родв В {Данные.вРяд,Данные.вОРяд,Данные.вЦепь,Данные.вОЦепь,Данные.вОЯчейки} ТО
    овид:=уа.вид.овид
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.ЭТО_НЕ_РЯД)
  КОН;
  размеро:=овид.размер;
  ЕСЛИ уб.роду = уПост ТО
    смещ:=уб.a*размеро;
    ЕСЛИ (смещ < 0) ИЛИ (родв В {Данные.вРяд,Данные.вЦепь}) И (смещ >= уа.вид.размер) ТО
      Ошибка.Отметить(Ошибка.ВЫХОД_ЗА_ГРАНИЦЫ_РЯДА)
    КОН;
    ЕСЛИ уа.роду = уАдрСАдрС ТО
      УВЕЛИЧИТЬ(уа.b,смещ)
    ИНАЧЕ
      ПРОВЕРИТЬ(уа.роду В {уАдрС,уАдрО});
      УВЕЛИЧИТЬ(уа.a,смещ)
    КОН;
    (* 
    ЕСЛИ родв В {Данные.вОРяд,Данные.вОЦепь,Данные.вОЯчейки}) ТО
      Ловушка! при (смещ >= уа.вид.размер)
    КОН;
    *)
  ИНАЧЕ
    ПеренестиВРег(уб);
    АдресВРег(уа);
    ЕСЛИ Степень2(размеро) ТО
      уа.роду:=уАдрСС;
      уа.a:=уб.ро;
      уа.b:=степень2
    ИНАЧЕ
      СоздатьЦелПост(уп,размеро);
      ПеренестиВРег(уп);
      Код.Умн(Код.MLA,уа.ро,уп.ро,уб.ро,уа.ро);
      Освободить(уб);
      Освободить(уп);
      уа.роду:=уАдрС;
      уа.a:=0
    КОН
  КОН;
  уа.вид:=овид
КОН АдрПерРяда;

(******************************************************************************)
ЗАДАЧА Свойство-(  у+:Узел.нВид;
                 пон :Данные.ДкПонятию);
(* у.вид.родв = Данные.вНабор,
 * пон.родп = Данные.пСвойство *)
ПЕР
  обл:Данные.ДкОбласти;
УКАЗ
  ПРОВЕРИТЬ(пон.родп = Данные.пСвойство);
  ЕСЛИ у.роду = уАдрО ТО
    АдрОвАдрС(у);
    УВЕЛИЧИТЬ(у.a,пон.адр)
  АЕСЛИ у.роду = уАдрС ТО
    УВЕЛИЧИТЬ(у.a,пон.адр)
  АЕСЛИ у.роду = уАдрСАдрС ТО
    УВЕЛИЧИТЬ(у.b,пон.адр)
  АЕСЛИ пон.адр # 0 ТО
    АдресВРег(у);
    у.роду:=уАдрС;
    у.a:=пон.адр
  КОН;
  ЕСЛИ (у.вид.нвхотд # 0)
      И
       (Данные.прНеизменяемая В пон.признаки)
  ТО
    у.толькочт:=ВКЛ
  ИНАЧЕ
    у.толькочт:=ОТКЛ
  КОН;
  у.вид:=пон.вид;
  (* у.пон:=ПУСТО *)
  обл:=у.пон.обл;
  у.пон:=пон;
  у.пон.обл:=обл
КОН Свойство;

(******************************************************************************)
ЗАДАЧА Доступ-(у+:Узел.нВид);
ПЕР
  обл:Данные.ДкОбласти;
УКАЗ
  ЕСЛИ у.вид.родв # Данные.вДоступ ТО
    Ошибка.Отметить(Ошибка.ССЫЛКА_НЕ_ОТ_ДОСТУПА)
  КОН; 
  ЕСЛИ у.роду = уАдрС ТО
    у.роду:=уАдрСАдрС;
    у.b:=0
  ИНАЧЕ
    ПеренестиВРег(у);
    у.роду:=уАдрС;
    у.a:=0
  КОН;
  обл:=у.пон.обл;
  у.вид:=у.вид.овид;
  у.пон:=Данные.поДоступу;
  у.пон.обл:=обл
КОН Доступ;

(******************************************************************************)
ЗАДАЧА ВМнож-(уа+,уб+:Узел.нВид);
(* Цель:  уа:=уа В уб
 * После: уа.роду = уКодУсл
 *        уб пустой *)
ПЕР
  вр:ЦЕЛ; (* временный регистр *)
  ку:ЦЕЛ; (* код условия *)
УКАЗ
  ЕСЛИ НЕ (уа.вид.родв В Данные.множЦелых)
         ИЛИ
          (уб.вид.родв # Данные.вМнож)
  ТО
    Ошибка.Отметить(Ошибка.ВИД_НЕ_ДЛЯ_В)
  КОН;
  ку:=Код.NV;
  ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
    ЕСЛИ (уа.a < 0) ИЛИ (уа.a > 31) ТО
      Ошибка.Отметить(Ошибка.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН;
    ЕСЛИ уа.a В ОБХОД.Значение(МНОЖ,уб.a) ТО
      ку:=Код.AL
    КОН
  АЕСЛИ уа.роду = уПост ТО
    ЕСЛИ (уа.a < 0) ИЛИ (уа.a > 31) ТО
      Ошибка.Отметить(Ошибка.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН;
    ПеренестиВРег(уб);
    Код.ОД1(Код.TST,0,уб.ро,Асм.Сдвиг(1,уа.a));
    Освободить(уб);
    ку:=Код.NE
  ИНАЧЕ
    ПеренестиВРег(уа);
    ПеренестиВРег(уб);
    Рег.ЗанятьРОН(вр);
    Код.ОД1(Код.MOV,вр,0,1);
    Код.ОД(Код.TST,0,уб.ро,вр,Код.LSL,уа.ро); (* TST уб.ро, вр LSL уа.ро *)
    (* +1 -> ро*10H - рег *)
    Освободить(уб);
    Освободить(уа);
    Рег.ОсвободитьРОН(вр);
    ку:=Код.NE
  КОН;
  СоздатьКУ(уа,ку)
КОН ВМнож;

(******************************************************************************)
ЗАДАЧА Внести1-(уа+,уб+:Узел.нВид);
(* Цель:  внести во множество 1 элемент (уа:={уб})
 * После: уа.роду В {уРон,уПост}
 *        уб пустой *)
УКАЗ
  ЕСЛИ НЕ (уб.вид.родв В Данные.множЦелых) ТО
    Ошибка.Отметить(Ошибка.МНОЖЕСТВО_НЕ_ИЗ_ЦЕЛЫХ)
  КОН;
  ЕСЛИ уб.роду = уПост ТО
    ЕСЛИ (уб.a < 0) ИЛИ (уб.a > 31) ТО
      Ошибка.Отметить(Ошибка.ГРАНИЦЫ_МНОЖЕСТВА)
    КОН;
    уа.роду:=уПост;
    уа.a:=Асм.Сдвиг(1,уб.a)
  ИНАЧЕ
    уа.роду:=уРон;
    Рег.ЗанятьРОН(уа.ро);
    Код.ОД1(Код.MOV,уа.ро,0,1);
    ПеренестиВРег(уб);
    Код.ОД(Код.MOV,уа.ро,0,уа.ро,Код.LSL,уб.ро); (* MOV уа.ро,уа.ро LSL уб.ро *)
    Освободить(уб)
  КОН; 
  уа.вид:=Данные.множвид
КОН Внести1;

(******************************************************************************)
ЗАДАЧА ВнестиНеск-(уа+,уб+,ув+:Узел.нВид);
(* Цель:  внести во множество несколько элементов (уа:={уб..ув})
 * После: уа.роду В {уРон,уПост}
 *        уб и ув пустой *)
ПЕР
  вр:ЦЕЛ; (* временный регистр *)
УКАЗ
  ЕСЛИ НЕ (уб.вид.родв В Данные.множЦелых) ИЛИ НЕ (ув.вид.родв В Данные.множЦелых) ТО
    Ошибка.Отметить(Ошибка.МНОЖЕСТВО_НЕ_ИЗ_ЦЕЛЫХ)
  КОН;
  ЕСЛИ (уб.роду = уПост) И (ув.роду = уПост) ТО
    ЕСЛИ (уб.a < 0) ИЛИ (уб.a > 31) ИЛИ (ув.a < 0) ИЛИ (ув.a > 31) ТО
      Ошибка.Отметить(Ошибка.ГРАНИЦЫ_МНОЖЕСТВА)
    АЕСЛИ уб.a > ув.a ТО
      Ошибка.Отметить(Ошибка.ПЕРЕПУТАНЫ_ГРАНИЦЫ)
    КОН;
    уа.роду:=уПост;
    уа.a:=Асм.Сдвиг(-1,уб.a)-Асм.Сдвиг(-2,ув.a)
  ИНАЧЕ
    уа.роду:=уРон;
    ЕСЛИ уб.роду = уПост ТО
      уб.a:=Асм.Сдвиг(-1,уб.a);
      ПеренестиВРег(уб);
      уа.ро:=уб.ро
    ИНАЧЕ
      Рег.ЗанятьРОН(уа.ро);
      Код.ОД1(Код.MVN,уа.ро,0,0); (* MOV уа.ро,-1 *)
      ПеренестиВРег(уб);
      Код.ОД(Код.MOV,уа.ро,0,уа.ро,Код.LSL,уб.ро); (* MOV уа.ро,-1 LSL уб.ро *)
      Освободить(уб)
    КОН;
    ЕСЛИ ув.роду = уПост ТО
      Код.ОД1(Код.BIC,уа.ро,уа.ро,Асм.Сдвиг(-2,ув.a)) (* BIC уа.ро,уа.ро,ув *)
    ИНАЧЕ
      Рег.ЗанятьРОН(вр);
      Код.ОД1(Код.MVN,вр,0,1); (* MOV вр,-2 *)
      ПеренестиВРег(ув);
      Код.ОД(Код.BIC,уа.ро,уа.ро,вр,Код.LSL,ув.ро); (* BIC уа.ро,уа.ро,-2 LSL ув.ро *)
      Освободить(ув);
      Рег.ОсвободитьРОН(вр)
    КОН
  КОН;
  уа.вид:=Данные.множвид
КОН ВнестиНеск;

(******************************************************************************)
ЗАДАЧА ВызовСреды1(у+:Узел.нВид; имя-:ЦЕПЬ);
(* Цель:  вызов из СРЕДА1.asm задачи с одним приёмником <у>
 * Прим:  сохраняются уже занятые R0-R3 регистры,
 *        источник передаётся через регистр R0
 * После: у - ответ (у.роду = уРон) *)
ПЕР
  сохрРеги:МНОЖ;
УКАЗ
  ЕСЛИ НЕ (0 В Рег.Заняты()) ТО
    ПеренестиВТребРег(у,0)
  ИНАЧЕ
    ПеренестиВРег(у)
  КОН;
  сохрРеги:=Рег.Заняты()*{0..3}-{у.ро};
  ЕСЛИ сохрРеги # {} ТО
    Код.СЗС(Код.STMDB,Рег.SP,ВКЛ,сохрРеги)
  КОН;
  Рег.БудутЗаняты(Рег.Заняты()-сохрРеги);

  ПеренестиВТребРег(у,0);
  Освободить(у);

  Код.ВызовСреды(имя);
  Рег.БудутЗаняты(сохрРеги+{0});
  (* ответ в регистр *)
  у.роду:=Узел.уРон;
  ЕСЛИ 0 В сохрРеги ТО
    (* чтобы не затереть ответ, переносим его из R0 в др. регистр *)
    Рег.ЗанятьРОН(у.ро);
    Код.ОД(Код.MOV,у.ро,0,0,0,0)
  ИНАЧЕ
    у.ро:=0
  КОН;
  ЕСЛИ сохрРеги # {} ТО
    Код.СЗС(Код.LDMIA,Рег.SP,ВКЛ,сохрРеги)
  КОН
КОН ВызовСреды1;

(******************************************************************************)
ЗАДАЧА ВызовСреды2(уа+,уб+:Узел.нВид; имя-:ЦЕПЬ);
(* Цель:  вызов из СРЕДА1.asm задачи с двумя приёмниками
 * До:    <строго> - ВКЛ, если не выполняется переместительный закон
 * Прим:  сохраняются уже занятые R0-R3 регистры,
 *        источники передаются через регистры R0,R1
 * После: уа - ответ (уа.роду = уРон) *)
ПЕР
  сохрРеги:МНОЖ;
УКАЗ
  ЕСЛИ НЕ (0 В Рег.Заняты()) ТО
    ПеренестиВТребРег(уа,0)
  ИНАЧЕ
    ПеренестиВРег(уа)
  КОН;
  ЕСЛИ НЕ (1 В Рег.Заняты()) ТО
    ПеренестиВТребРег(уб,1)
  ИНАЧЕ
    ПеренестиВРег(уб)
  КОН;

  сохрРеги:=Рег.Заняты()*{0..3}-{уа.ро,уб.ро};
  ЕСЛИ сохрРеги # {} ТО
    Код.СЗС(Код.STMDB,Рег.SP,ВКЛ,сохрРеги)
  КОН;
  Рег.БудутЗаняты(Рег.Заняты()-сохрРеги);

  ЕСЛИ уб.ро = 0 ТО (* уб не там *)
    ЕСЛИ уа.ро = 1 ТО (*  уа не там, поменять местами R0 и R1 *)
      Код.ОД(Код.EOR,0,1,0,0,0);
      Код.ОД(Код.EOR,1,0,1,0,0);
      Код.ОД(Код.EOR,0,1,0,0,0)
    ИНАЧЕ
      ПеренестиВТребРег(уб,1);
      ПеренестиВТребРег(уа,0)
    КОН  
  ИНАЧЕ
    ПеренестиВТребРег(уа,0);
    ПеренестиВТребРег(уб,1)
  КОН;
  Освободить(уа);
  Освободить(уб);

  Код.ВызовСреды(имя);
  Рег.БудутЗаняты(сохрРеги+{0});
  (* ответ в регистр *)
  уа.роду:=Узел.уРон;
  ЕСЛИ 0 В сохрРеги ТО
    (* чтобы не затереть ответ, переносим его из R0 в др. регистр *)
    Рег.ЗанятьРОН(уа.ро);
    Код.ОД(Код.MOV,уа.ро,0,0,0,0)
  ИНАЧЕ
    уа.ро:=0
  КОН;
  ЕСЛИ сохрРеги # {} ТО
    Код.СЗС(Код.LDMIA,Рег.SP,ВКЛ,сохрРеги)
  КОН
КОН ВызовСреды2;

(******************************************************************************)
ЗАДАЧА Действие1-(действие:ЦЕЛ; у+:Узел.нВид);
(* действие с одним данным *)
ПЕР
  вещ:ВЕЩ; 
  множ:МНОЖ; 
  родв,a:ЦЕЛ; 
УКАЗ
  родв:=у.вид.родв;
  ВЫБРАТЬ действие ИЗ
  | Слово.плюс:
      ЕСЛИ НЕ (родв В Данные.множЦелых+Данные.множВещ) ТО
        Ошибка.Отметить(Ошибка.ПЛЮС_НЕПРИМЕНИМ)
      КОН
  | Слово.минус:
      ЕСЛИ родв В Данные.множЦелых ТО
        ЕСЛИ у.роду = уПост ТО
          у.a:=-у.a;
          ОпредЦелВид(у)
        ИНАЧЕ
          ПеренестиВРОН(у);
          Код.ОД1(Код.RSB,у.ро,у.ро,0)
        КОН
      АЕСЛИ родв = Данные.вВещ32 ТО
        ЕСЛИ у.роду = уПост ТО
          вещ:=ОБХОД.Значение(ВЕЩ,у.a);
          у.a:=ОБХОД.Значение(ЦЕЛ,-вещ)
        ИНАЧЕ
          ВызовСреды1(у,"Вещ32Отрицание")
        КОН
      АЕСЛИ родв = Данные.вМнож ТО
        ЕСЛИ у.роду = уПост ТО
          множ:=ОБХОД.Значение(МНОЖ,у.a);
          у.a:=ОБХОД.Значение(ЦЕЛ,-множ)
        ИНАЧЕ
          ПеренестиВРОН(у);
          Код.ОД(Код.MVN,у.ро,0,у.ро,0,0)
        КОН
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.МИНУС_НЕПРИМЕНИМ)
      КОН
  | Слово.и:
      ВыставитьКУ(у);
      Код.ПереходПоКУ(у.b,Код.ОбратныйКУ(у.ро));
      Код.ПоставитьМетку(у.a); (* ! *)
  | Слово.или:
      ВыставитьКУ(у);
      Код.ПереходПоКУ(у.a,у.ро);
      Код.ПоставитьМетку(у.b); (* ! *)
  | Слово.не:
      ВыставитьКУ(у);
      у.ро:=Код.ОбратныйКУ(у.ро);
      a:=у.a;
      у.a:=у.b;
      у.b:=a
  | Слово.равно..Слово.бравно:
      ЕСЛИ у.роду = уКодУсл ТО
        ПеренестиВРег(у)
      КОН
  КОН
КОН Действие1;

(******************************************************************************)
ЗАДАЧА ЦелВВещ-(у+:Узел.нВид);
ПЕР
  вещ:ВЕЩ;
УКАЗ
  ЕСЛИ у.роду = уПост ТО
    вещ:=у.a;
    у.a:=ОБХОД.Значение(ЦЕЛ,вещ);
    у.вид:=Данные.вещ32вид
  ИНАЧЕ
    ВызовСреды1(у,"Цел32ВВещ32")
  КОН
КОН ЦелВВещ;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       ЗнакВЦепь-(у+:Узел.нВид);
ПЕР
  достцепь:ДОСТУП К ЦЕПЬ;
УКАЗ
  ЕСЛИ (у.вид.родв = Данные.вЗнак) И (у.роду = уПост) ТО
    СОЗДАТЬ(достцепь,2);
    достцепь[0]:=ВЗНАК(у.a);
    достцепь[1]:=0X;
    у.пон:=Данные.СоздатьПостЦепь(достцепь);
    у.вид:=у.пон.вид
  КОН
КОН ЗнакВЦепь;

(******************************************************************************)
ЗАДАЧА СравнитьЦепочки(уа+,уб+:Узел.нВид; ку:ЦЕЛ);
(* После: уа.роду=уКодУ, уб пустой *)
ПЕР
  ра,рб:ЦЕЛ;          (* регистры для считанных из цепочек знаков *)
  мПовтор,мВыход:ЦЕЛ; (* метки *)
УКАЗ
  ЗнакВЦепь(уа);
  ЗнакВЦепь(уб);
  АдресВРег(уа);
  АдресВРег(уб);
  мВыход:=Код.ПолучитьМетку();
  мПовтор:=Код.ПолучитьМетку();
  (* уа.роду = уРон, уб.роду = уРон *)
  Рег.ЗанятьРОН(ра);
  Рег.ЗанятьРОН(рб);
Код.ПоставитьМетку(мПовтор);
  Код.ПЗС1(Код.LDRBp,ра,уа.ро,1);
  Код.ПЗС1(Код.LDRBp,рб,уб.ро,1);
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.CMP,0,ра,0);
  Код.ПереходПоКУ(мВыход,Код.EQ);    (* идём на выход, если ра = 0 *)
  Код.будетS:=ВКЛ;
  Код.ОД(Код.CMP,0,ра,рб,0,0);
  Код.ПереходПоКУ(мПовтор,Код.EQ);   (* идём на повтор, если ра = рб *)
Код.ПоставитьМетку(мВыход);
  Код.будетS:=ВКЛ;
  Код.ОД(Код.CMP,0,ра,рб,0,0);     (* пригодится если ра = 0 *)
  Рег.ОсвободитьРОН(ра);
  Рег.ОсвободитьРОН(рб);
  Освободить(уа);
  Освободить(уб);
  СоздатьКУ(уа,ку)
КОН СравнитьЦепочки;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Действие-(действие  :ЦЕЛ;
                       уа+,
                       уб+ :Узел.нВид);
ПЕР
  родва,родвб:ЦЕЛ; 
  степень2:ЦЕЛ; (* побочный ответ задачи Степень2 *)
  а,б:ЦЕЛ;
  в1,в2:ВЕЩ;
  ключ:КЛЮЧ; (* спасаемся от ошибки НЕТ_РЕГИСТРОВ *)

 (*................................................подЗАДАЧА...*)
  ЗАДАЧА Степень2(число:ЦЕЛ):КЛЮЧ;
  (* Цель:  пытается найти представление <число> в виде 2^n
   * До:    <число>    - исследуемое число
   * После: <степень2> - найденное n, если это возможно
   * Ответ: ВКЛ, если <число> = 2^<степень2> *)   
  УКАЗ
    степень2:=0;
    ЕСЛИ число > 0 ТО
      ПОКА ЧЕТ(число) ВЫП
        число:=число ДЕЛИТЬ 2;
        УВЕЛИЧИТЬ(степень2)
      КОН;
      ЕСЛИ число = 1 ТО ВОЗВРАТ ВКЛ КОН
    КОН;
    ВОЗВРАТ ОТКЛ
  КОН Степень2;

 (*................................................подЗАДАЧА...*)
  ЗАДАЧА Цепочки():КЛЮЧ;
  (* возвращает ВКЛ, если <уа> и <уб> являются цепочками *)
  УКАЗ 
    ВОЗВРАТ
    (
     ((родва В {Данные.вЦепь,Данные.вОЦепь}) ИЛИ (родва = Данные.вЗнак) И (уа.роду = уПост))
    И
     ((родвб В {Данные.вЦепь,Данные.вОЦепь}) ИЛИ (родвб = Данные.вЗнак) И (уб.роду = уПост))
    )
  КОН Цепочки;

 (*................................................подЗАДАЧА...*)
  ЗАДАЧА Родня(а0,б0:Данные.ДкВиду):КЛЮЧ;
  (* Цель:  определить, являются ли наборы между собой родственниками
   * До:    а0.родв = вНабор, б0.родв = вНабор
   * Ответ: ВКЛ, если являются *)
  ПЕР
    а,б:Данные.ДкВиду;
  УКАЗ
    а:=а0;
    ПОКА а # Данные.неопрвид ВЫП
      б:=б0;
      ПОКА б # Данные.неопрвид ВЫП
        ЕСЛИ а = б ТО
          ВОЗВРАТ ВКЛ
        КОН;
        б:=б.овид
      КОН;
      а:=а.овид
    КОН;
    ВОЗВРАТ ОТКЛ
  КОН Родня;

УКАЗ
  родва:=уа.вид.родв;
  родвб:=уб.вид.родв;
  (* проверим на соответствие видов *)
  ЕСЛИ уа.вид # уб.вид ТО
    ВЫБРАТЬ родва ИЗ
    | Данные.вЦел8:
        ЕСЛИ (родвб = Данные.вЦел16) ИЛИ (родвб = Данные.вЦел32) ТО 
          ЕСЛИ уа.роду # уПост ТО
            ПеренестиВРОН(уа)
          КОН;
          родва:=родвб;
          уа.вид:=уб.вид
        АЕСЛИ родвб В Данные.множВещ ТО
          ЦелВВещ(уа)
        АЕСЛИ родвб # Данные.вЦел8 ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вЦел16:
        ЕСЛИ родвб = Данные.вЦел8 ТО 
          ЕСЛИ уб.роду # уПост ТО
            ПеренестиВРег(уб)
          КОН;
          родвб:=родва;
          уб.вид:=уа.вид
        АЕСЛИ родвб = Данные.вЦел32 ТО 
          ЕСЛИ уа.роду # уПост ТО
            ПеренестиВРОН(уа)
          КОН;
          родва:=родвб;
          уа.вид:=уб.вид
        АЕСЛИ родвб В Данные.множВещ ТО
          ЦелВВещ(уа)
        АЕСЛИ родвб # Данные.вЦел16 ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вЦел32:
        ЕСЛИ (родвб = Данные.вЦел8) ИЛИ (родвб = Данные.вЦел16) ТО 
          ЕСЛИ уб.роду # уПост ТО
            ПеренестиВРег(уб)
          КОН;
          родвб:=родва;
          уб.вид:=уа.вид
        АЕСЛИ родвб В Данные.множВещ ТО
          ЦелВВещ(уа)
        АЕСЛИ родвб # Данные.вЦел32 ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вВещ32:
        ЕСЛИ родвб В Данные.множЦелых ТО 
          ЦелВВещ(уб)
        АЕСЛИ родвб # Данные.вВещ32 ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вПусто:
        ЕСЛИ НЕ (родвб В {Данные.вДоступ,Данные.вЗадача}) ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вДоступ:
        ЕСЛИ родвб = Данные.вДоступ ТО
          ЕСЛИ НЕ Родня(уа.вид.овид,уб.вид.овид) ТО
            Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
          КОН
        АЕСЛИ родвб # Данные.вПусто ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    | Данные.вЗадача:
        ЕСЛИ родвб # Данные.вПусто ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
        КОН
    |  Данные.вНеопр,Данные.вРяд,Данные.вОРяд,Данные.вЦепь,Данные.вОЦепь:
    ИНАЧЕ
      Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМЫЕ_ВИДЫ)
    КОН
  КОН;
  ВЫБРАТЬ действие ИЗ
    Слово.умножить:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          а:=уа.a;
          б:=уб.a;
          ЕСЛИ (а = 0) ИЛИ (б = 0) ИЛИ
               (а > 0) И (б > 0) И ( б <= МАКС(ЦЕЛ) ДЕЛИТЬ   а) ИЛИ
               (а > 0) И (б < 0) И ( б >= МИН(ЦЕЛ)  ДЕЛИТЬ   а) ИЛИ
               (а < 0) И (б > 0) И ( а >= МИН(ЦЕЛ)  ДЕЛИТЬ   б) ИЛИ
               (а < 0) И (б < 0) И (-а <= МАКС(ЦЕЛ) ДЕЛИТЬ (-б)) ТО
            уа.a:=а*б;
            ОпредЦелВид(уа)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШОЕ_ПРОИЗВЕДЕНИЕ)
          КОН
        ИНАЧЕ
          ЕСЛИ (уа.роду = уПост) И Степень2(уа.a) ТО
            ПеренестиВРег(уб);
            ЕСЛИ степень2 # 0 ТО
              Код.ОД(Код.MOV,уб.ро,0,уб.ро,Код.LSL,степень2+16)
            КОН;
            уа:=уб;
            уб.роду:=уПустой (* защита от освобождения регистра *)
          АЕСЛИ (уб.роду = уПост) И Степень2(уб.a) ТО
            ПеренестиВРОН(уа);
            ЕСЛИ степень2 # 0 ТО
              Код.ОД(Код.MOV,уа.ро,0,уа.ро,Код.LSL,степень2+16)
            КОН
          ИНАЧЕ
            ПеренестиВРОН(уа);
            ПеренестиВРег(уб);
            Код.Умн(Код.MUL,уа.ро,уб.ро,уа.ро,0)
          КОН
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          в1:=ОБХОД.Значение(ВЕЩ,уа.a);
          в2:=ОБХОД.Значение(ВЕЩ,уб.a);
          ключ:=МОДУЛЬ(в2) <= 1.0;
          ЕСЛИ ключ ИЛИ (МОДУЛЬ(в1) <= МАКС(ВЕЩ)/МОДУЛЬ(в2)) ТО
            уа.a:=ОБХОД.Значение(ЦЕЛ,в1*в2)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШОЕ_ПРОИЗВЕДЕНИЕ)
          КОН
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Вещ32Умножить")
        КОН
      АЕСЛИ родва = Данные.вМнож ТО
        ОД(Код.AND,уа,уб)
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.УМНОЖЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.косая:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЦелВВещ(уа);
        ЦелВВещ(уб);
        родва:=Данные.вВещ32;
        родвб:=Данные.вВещ32
      КОН;
      ЕСЛИ родва = Данные.вВещ32 ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          в1:=ОБХОД.Значение(ВЕЩ,уа.a);
          в2:=ОБХОД.Значение(ВЕЩ,уб.a);
          ключ:=МОДУЛЬ(в2) >= 1.0;
          ЕСЛИ ключ ИЛИ (МОДУЛЬ(в1) <= МАКС(ВЕЩ)*МОДУЛЬ(в2)) ТО
            уа.a:=ОБХОД.Значение(ЦЕЛ,в1/в2)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.ДЕЛЕНИЕ_НА_НОЛЬ)
          КОН
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Вещ32Делить")
        КОН
      АЕСЛИ родва = Данные.вМнож ТО
        ОД(Код.EOR,уа,уб)
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.ДЕЛЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.делить:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уб.роду = уПост) И (уб.a = 0) ТО
          Ошибка.Отметить(Ошибка.ДЕЛЕНИЕ_НА_НОЛЬ)
        КОН;
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          уа.a:=уа.a ДЕЛИТЬ уб.a;
          ОпредЦелВид(уа)
        АЕСЛИ (уб.роду = уПост) И Степень2(уб.a) ТО
          ПеренестиВРОН(уа);
          Код.ОД(Код.MOV,уа.ро,0,уа.ро,Код.ASR,степень2+16) (* MOV уа.ро,уа.ро ASR степень2 *)
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Делить")
        КОН
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.ДЕЛИТЬ_НЕПРИМЕНИМО)
      КОН
  | Слово.остаток:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уб.роду = уПост) И (уб.a = 0) ТО
          Ошибка.Отметить(Ошибка.ДЕЛЕНИЕ_НА_НОЛЬ)
        КОН;
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          уа.a:=уа.a ОСТАТОК уб.a;
          уа.вид:=уб.вид
        АЕСЛИ (уб.роду = уПост) И Степень2(уб.a) ТО
          уб.a:=Асм.ЗнаковыйСдвиг(-1,степень2);
          ПеренестиВРОН(уа);
          Код.ОД1(Код.BIC,уа.ро,уа.ро,уб.a)
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Остаток")
        КОН
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.ОСТАТОК_НЕПРИМЕНИМО)
      КОН
  | Слово.и:
      ВыставитьКУ(уб);
      ЕСЛИ уа.ро # Код.NV ТО
        уа.ро:=уб.ро
      КОН;
      уа.a:=уб.a
  | Слово.или:
      ВыставитьКУ(уб);
      ЕСЛИ уа.ро # Код.AL ТО
        уа.ро:=уб.ро
      КОН;
      уа.b:=уб.b
  | Слово.плюс:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ (уб.a >= 0) И (уа.a <= МАКС(ЦЕЛ)-уб.a) ИЛИ
               (уб.a <  0) И (уа.a >= МИН(ЦЕЛ) -уб.a) ТО
            УВЕЛИЧИТЬ(уа.a,уб.a);
            ОпредЦелВид(уа)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШАЯ_СУММА)
          КОН
        ИНАЧЕ
          ПеренестиВРОН(уа);
          ОД(Код.ADD,уа,уб)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          в1:=ОБХОД.Значение(ВЕЩ,уа.a);
          в2:=ОБХОД.Значение(ВЕЩ,уб.a);
          ключ:=(в2 >= 0.0) И (в1 <= МАКС(ВЕЩ)-в2);
          ЕСЛИ ключ ИЛИ (в2 < 0.0) И (в1 >= -(МАКС(ВЕЩ)+в2)) ТО
            уа.a:=ОБХОД.Значение(ЦЕЛ,в1+в2)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШАЯ_СУММА)
          КОН
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Вещ32Сложить")
        КОН
      АЕСЛИ родва = Данные.вМнож ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          уа.a:=ОБХОД.Значение(ЦЕЛ,ОБХОД.Значение(МНОЖ,уа.a)+
                                   ОБХОД.Значение(МНОЖ,уб.a))
        ИНАЧЕ
          ОД(Код.ORR,уа,уб)
        КОН
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.ПЛЮС_НЕПРИМЕНИМ)
      КОН
  | Слово.минус:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ (уб.a >= 0) И (уа.a >= МИН(ЦЕЛ) +уб.a) ИЛИ
               (уб.a <  0) И (уа.a <= МАКС(ЦЕЛ)+уб.a) ТО
            УМЕНЬШИТЬ(уа.a,уб.a);
            ОпредЦелВид(уа)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШАЯ_РАЗНОСТЬ)
          КОН
        ИНАЧЕ
          ОД(Код.SUB,уа,уб)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          в1:=ОБХОД.Значение(ВЕЩ,уа.a);
          в2:=ОБХОД.Значение(ВЕЩ,уб.a);
          ключ:=(в2 >= 0.0) И (в1 >= -МАКС(ВЕЩ)+в2);
          ЕСЛИ ключ ИЛИ (в2 < 0.0) И (в1 <= МАКС(ВЕЩ)+в2) ТО
            уа.a:=ОБХОД.Значение(ЦЕЛ,в1-в2)
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.БОЛЬШАЯ_РАЗНОСТЬ)
          КОН
        ИНАЧЕ
          ВызовСреды2(уа,уб,"Вещ32Вычесть")
        КОН
      АЕСЛИ родва = Данные.вМнож ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          уа.a:=ОБХОД.Значение(ЦЕЛ,ОБХОД.Значение(МНОЖ,уа.a)-
                                   ОБХОД.Значение(МНОЖ,уб.a))
        ИНАЧЕ
          ОД(Код.BIC,уа,уб)
        КОН
      АЕСЛИ родва # Данные.вНеопр ТО
        Ошибка.Отметить(Ошибка.МИНУС_НЕПРИМЕНИМ)
      КОН
  | Слово.равно:
      ЕСЛИ родва В {Данные.вНеопр,Данные.вЯчейка,Данные.вКлюч,Данные.вЗнак,
                    Данные.вЦел8,Данные.вЦел16,Данные.вЦел32,Данные.вМнож,
                    Данные.вПусто,Данные.вДоступ,Данные.вЗадача}
      ТО
        ЕСЛИ (уа.роду = уПост)
            И
             (уб.роду = уПост)
        ТО
          ЕСЛИ уа.a = уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.EQ)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32Равно");
        уа.вид:=Данные.ключвид
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.EQ)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.неравно:
      ЕСЛИ родва В {Данные.вНеопр,Данные.вЯчейка,Данные.вКлюч,Данные.вЗнак,
                    Данные.вЦел8,Данные.вЦел16,Данные.вЦел32,Данные.вМнож,
                    Данные.вПусто,Данные.вДоступ,Данные.вЗадача}
      ТО
        ЕСЛИ (уа.роду = уПост)
            И
             (уб.роду = уПост)
        ТО
          ЕСЛИ уа.a # уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.NE)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32Неравно");
        уа.вид:=Данные.ключвид
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.NE)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.меньше:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ уа.a < уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.LT)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32Меньше");
        уа.вид:=Данные.ключвид
      АЕСЛИ родва = Данные.вЗнак ТО
        Сравнить(уа,уб,Код.CC)
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.CC)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.мравно:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ уа.a <= уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.LE)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32МРавно");
        уа.вид:=Данные.ключвид
      АЕСЛИ родва = Данные.вЗнак ТО
        Сравнить(уа,уб,Код.LS)
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.LS)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.больше:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ уа.a > уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.GT)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32Больше");
        уа.вид:=Данные.ключвид
      АЕСЛИ родва = Данные.вЗнак ТО
        Сравнить(уа,уб,Код.HI)
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.HI)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  | Слово.бравно:
      ЕСЛИ родва В Данные.множЦелых ТО
        ЕСЛИ (уа.роду = уПост) И (уб.роду = уПост) ТО
          ЕСЛИ уа.a >= уб.a ТО
            СоздатьКУ(уа,Код.AL)
          ИНАЧЕ
            СоздатьКУ(уа,Код.NV)
          КОН
        ИНАЧЕ
          Сравнить(уа,уб,Код.GE)
        КОН
      АЕСЛИ родва = Данные.вВещ32 ТО
        ВызовСреды2(уа,уб,"Вещ32БРавно");
        уа.вид:=Данные.ключвид
      АЕСЛИ родва = Данные.вЗнак ТО
        Сравнить(уа,уб,Код.CS)
      АЕСЛИ Цепочки() ТО
        СравнитьЦепочки(уа,уб,Код.CS)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.СРАВНЕНИЕ_НЕПРИМЕНИМО)
      КОН
  КОН;
  Освободить(уб)
КОН Действие;


(********* Встроенные (локальные) задачи **************************************)


(******************************************************************************)
ЗАДАЧА Образ(ир,пр,рр:ЦЕЛ);
(* Цель: переписывает
 * До:   ир - регистр с адресом источника данных 
 *       пр - регистр с адресом приёмника данных
 *       рр - регистр с заданным размером *)
ПЕР
  мВыход:ЦЕЛ;
УКАЗ
  мВыход:=Код.ПолучитьМетку();
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.CMP,0,рр,0);
  Код.ПереходПоКУ(мВыход,Код.LE); (* на выход, если рр <= 0 *)
  Код.ПереписатьПамять(ир,пр,рр);
Код.ПоставитьМетку(мВыход)
КОН Образ;

(******************************************************************************)
ЗАДАЧА Списать(уи+,уп+:Узел.нВид);
(* Цель: переписывает цепочку, в конце приёмника всегда ставит 0
 * До:    уи  - узел источника данных 
 *        уп  - узел приёмника данных
 * После: СПИСАТЬ(уи,уп) *)
ПЕР
  ури:Узел.нВид; (* узел размера источника *)
  урп:Узел.нВид; (* узел размера приёмника *)
  ир:ЦЕЛ;  (* регистр с адресом источника данных  *)
  пр:ЦЕЛ;  (* регистр с адресом приёмника данных  *)
  рир:ЦЕЛ; (* регистр с размером источника данных *)
  рпр:ЦЕЛ; (* регистр с размером приёмника данных *)
  зр:ЦЕЛ;  (* регистр с прочитанным знаком *)
  мПовтор,мВыход,мУменьшение:ЦЕЛ; (* метки *)
УКАЗ
  (* загрузим размеры в новые регистры *)
  ури:=уи;
  урп:=уп;
  РазмерРяда(ури);
  РазмерРяда(урп);
  ПеренестиВРОН(ури);
  ПеренестиВРОН(урп);
  рир:=ури.ро;
  рпр:=урп.ро;
  (* загрузим адреса в регистры *)
  АдресВРег(уи);
  АдресВРег(уп);
  ир:=уи.ро;
  пр:=уп.ро;
  (* получим метки *)
  мПовтор:=Код.ПолучитьМетку();
  мУменьшение:=Код.ПолучитьМетку();
  мВыход:=Код.ПолучитьМетку();
  (* рир:=МИН(рир,рпр) *)
  Код.будетS:=ВКЛ;
  Код.ОД(Код.CMP,0,рир,рпр,0,0);
  Код.будетКУ:=Код.GT;
  Код.ОД(Код.MOV,рир,0,рпр,0,0);
  зр:=рпр;
  (* на выход, если рир <= 0 *)
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.CMP,0,рир,0);
  Код.ПереходПоКУ(мВыход,Код.LE);
  (* на уменьшение рир *)
  Код.ПереходНа(мУменьшение);
Код.ПоставитьМетку(мПовтор);
  Код.ПЗС1(Код.LDRHp,зр,ир,2);
  Код.ПЗС1(Код.STRHp,зр,пр,2);
Код.ПоставитьМетку(мУменьшение);
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.SUB,рир,рир,1);
  Код.ПереходПоКУ(мПовтор,Код.NE); (* идём на мПовтор, если рир # 0 *)
  Код.ПЗС1(Код.STRH,рир,пр,0);     (* записываем в конце 0 (рир=0)  *)
Код.ПоставитьМетку(мВыход);
  Освободить(ури);
  Освободить(урп)               
КОН Списать;

(******************************************************************************)
ЗАДАЧА Длина(уи+:Узел.нВид);
(* Цель: нахождение длины цепочки
 * До:    уи - узел источника данных 
 * После: уи - ДЛИНА(уи) *)
ПЕР
  ури:Узел.нВид; (* узел размера источника *)
  ир:ЦЕЛ;  (* регистр с адресом источника данных  *)
  рир:ЦЕЛ; (* регистр с размером источника данных *)
  зр:ЦЕЛ;  (* регистр с прочитанным знаком *)
  рхр:ЦЕЛ; (* регистр с размером хвоста *)
  мПовтор,мВыход:ЦЕЛ; (* метки *)
УКАЗ
  (* загрузим размеры в новые регистры *)
  ури:=уи;
  РазмерРяда(ури);
  ПеренестиВРОН(ури);
  рир:=ури.ро;
  (* загрузим адреса в регистры *)
  АдресВРег(уи);
  ир:=уи.ро;
  (* получим метки *)
  мПовтор:=Код.ПолучитьМетку();
  мВыход:=Код.ПолучитьМетку();
  (* получим регистры *)
  Рег.ЗанятьРОН(зр); 
  Рег.ЗанятьРОН(рхр); 
  (* подготовимся *)
  Код.ОД(Код.MOV,рхр,0,рир,0,0);
Код.ПоставитьМетку(мПовтор);
  Код.ПЗС1(Код.LDRHp,зр,ир,2);
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.CMP,0,зр,0);
  Код.ПереходПоКУ(мВыход,Код.EQ);  (* идём на мВыход, если зр = 0 *)
  Код.будетS:=ВКЛ;
  Код.ОД1(Код.SUB,рхр,рхр,1);
  Код.ПереходПоКУ(мПовтор,Код.NE); (* идём на мПовтор, если рхр # 0 *)
Код.ПоставитьМетку(мВыход);
  Код.ОД(Код.SUB,ир,рир,рхр,0,0);
  Освободить(ури);
  Рег.ОсвободитьРОН(зр); 
  Рег.ОсвободитьРОН(рхр); 
  уи.вид:=Данные.цел32вид
КОН Длина;

(******************************************************************************)
ЗАДАЧА ВстрСоздать(у+:Узел.нВид);
(* Цель:  встроенная задача СОЗДАТЬ
 * До:    <> - 
 * После: <> - 
 * Ответ: 
 *)
ПЕР
  уд:Узел.нВид;   (* дополнительный узел размера источника оряд или ОВ набора *)
  овид:Данные.ДкВиду;
УКАЗ
  овид:=у.вид.овид;
  ЕСЛИ у.роду В {Узел.уПост,Узел.уВид..Узел.уВстрЗадача} ТО
    Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПЕРЕМЕННАЯ)
  АЕСЛИ (у.вид.родв # Данные.вДоступ) ИЛИ
    НЕ (овид.родв В {Данные.вНабор,Данные.вРяд,Данные.вОРяд}) ТО
    Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
  АЕСЛИ у.толькочт ТО
    Ошибка.Отметить(Ошибка.ПЕР_ДЛЯ_ЧТЕНИЯ)
  КОН;
  (* ОВ *)
  ЕСЛИ овид.родв = Данные.вНабор ТО
    уд.роду:=уРон;
    Рег.ЗанятьРОН(уд.ро);
    Код.ЗагрузитьОВ(уд.ро,овид);
    уд.вид:=Данные.цел32вид;
    ВСтог(уд)
  ИНАЧЕ
    ЦелВСтог(0)
  КОН;
  (* размер *)
  ЦелВСтог(овид.размер);
  (* адрес *)
  АдресВРег(у);
  ВСтог(у);          
  (* вызов *)
  Код.ВызовСреды("Создать");
  у.вид:=Данные.нетвид
КОН ВстрСоздать;

(******************************************************************************)
ЗАДАЧА Увеличить-(уа+,уб+:Узел.нВид);
(* Цель:  уа:=уа+уб *)
УКАЗ
  ОДсОбрЗап(Код.ADD,уа,уб)
КОН Увеличить;

(******************************************************************************)
ЗАДАЧА Уменьшить-(уа+,уб+:Узел.нВид);
(* Цель:  уа:=уа-уб *)
УКАЗ
  ОДсОбрЗап(Код.SUB,уа,уб)
КОН Уменьшить;

(******************************************************************************)
ЗАДАЧА ВстрПриёмник0-(задача:ЦЕЛ; у0+:Узел.нВид);
(* ошибки надо отметить сразу *)
ПЕР
  родв:ЦЕЛ; 
  в:ВЕЩ;
УКАЗ
  родв:=у0.вид.родв;
  ВЫБРАТЬ задача ИЗ
  | Данные.зСоздать:
      ВстрСоздать(у0)
  | Данные.зОбнулить:
      ЕСЛИ НЕ (родв В {Данные.вНабор,Данные.вРяд}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      (* работа! *)
  | Данные.зМодуль:
      ЕСЛИ родв В Данные.множЦелых ТО
        ЕСЛИ у0.роду = уПост ТО
          у0.a:=МОДУЛЬ(у0.a)
        ИНАЧЕ
          ПеренестиВРОН(у0);
          Код.будетS:=ВКЛ;
          Код.ОД1(Код.CMP,0,у0.ро,0);
          Код.будетКУ:=Код.LT;
          Код.ОД1(Код.RSB,у0.ро,у0.ро,0)
        КОН
      АЕСЛИ родв = Данные.вВещ32 ТО
        ЕСЛИ у0.роду = уПост ТО
          у0.a:=ОБХОД.Значение(ЦЕЛ,МОДУЛЬ(ОБХОД.Значение(ВЕЩ,у0.a)))
        ИНАЧЕ
          ВызовСреды1(у0,"Вещ32Модуль")
        КОН
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зЦелЧасть:
      ЕСЛИ родв = Данные.вВещ32 ТО
        ЕСЛИ у0.роду = уПост ТО
          у0.a:=ОБХОД.Значение(ЦЕЛ,ЦЕЛЧАСТЬ(ОБХОД.Значение(ВЕЩ,у0.a)))
        ИНАЧЕ
          ВызовСреды1(у0,"Вещ32ЦелЧасть")
        КОН
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зВЦел:
      ЕСЛИ НЕ (родв В {Данные.вЗнак,Данные.вЯчейка}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ у0.роду # уПост ТО
        ПеренестиВРег(у0)
      КОН;
      у0.вид:=Данные.цел32вид
  | Данные.зВЗнак:
      ЕСЛИ НЕ (родв В {Данные.вЯчейка,Данные.вЦел8,Данные.вЦел16,Данные.вЦел32}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ у0.роду # уПост ТО
        ПеренестиВРег(у0)
      КОН;
      у0.вид:=Данные.знаквид
  | Данные.зЧет:
      ЕСЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ПеренестиВРег(у0);
      Код.ОД1(Код.TST,0,у0.ро,1);
      Освободить(у0);
      СоздатьКУ(у0,Код.EQ)
  | Данные.зПолучитьАдрес:
      АдресВРег(у0);
      у0.вид:=Данные.цел32вид
  | Данные.зМин:
      ЕСЛИ у0.роду # уВид ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      КОН;
      у0.роду:=уПост;
      ВЫБРАТЬ родв ИЗ
        Данные.вКлюч:
          у0.a:=0
      | Данные.вЗнак:
          у0.a:=Настрой.МинЗнак
      | Данные.вЦел8:
          у0.a:=Настрой.МинЦел8
      | Данные.вЦел16:
          у0.a:=Настрой.МинЦел16
      | Данные.вЦел32:
          у0.a:=Настрой.МинЦел32
      | Данные.вМнож:
          у0.a:=Настрой.МинМнож;
          у0.вид:=Данные.цел32вид
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зМакс:
      ЕСЛИ у0.роду # уВид ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      КОН;
      у0.роду:=уПост;
      ВЫБРАТЬ родв ИЗ
        Данные.вКлюч:
          у0.a:=1
      | Данные.вЗнак:
          у0.a:=Настрой.МаксЗнак
      | Данные.вЦел8:
          у0.a:=Настрой.МаксЦел8
      | Данные.вЦел16:
          у0.a:=Настрой.МаксЦел16
      | Данные.вЦел32:
          у0.a:=Настрой.МаксЦел32
      | Данные.вМнож:
          у0.a:=Настрой.МаксМнож;
          у0.вид:=Данные.цел32вид
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зВШирЦел:
      ЕСЛИ родв = Данные.вВещ32 ТО
        ЕСЛИ у0.роду = уПост ТО
          в:=ОБХОД.Значение(ВЕЩ,у0.a);
          ЕСЛИ (в < Настрой.МинЦел32) ИЛИ (в > Настрой.МаксЦел32) ТО
            Ошибка.Отметить(Ошибка.БОЛЬШОЕ_ЧИСЛО)
          КОН;
          у0.a:=ОБХОД.Значение(ЦЕЛ,УЗК(ВШИРЦЕЛ(в)));
          ОпредЦелВид(у0)
        ИНАЧЕ
          ВызовСреды1(у0,"Вещ32ВЦел32")
        КОН  
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зУзк,Данные.зОУзк:
      ЕСЛИ (родв = Данные.вЦел16) ИЛИ (родв = Данные.вЦел32) ТО
        ЕСЛИ у0.роду # уПост ТО
          ПеренестиВРег(у0);
          ЕСЛИ родв = Данные.вЦел32 ТО
            у0.вид:=Данные.цел16вид
          ИНАЧЕ
            у0.вид:=Данные.цел8вид
          КОН
        КОН 
      АЕСЛИ родв = Данные.вВещ32 ТО (* наверное это ШИРВЕЩ *)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зДлина:
      ЗнакВЦепь(у0);
      ЕСЛИ НЕ (у0.вид.родв В {Данные.вЦепь,Данные.вОЦепь}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      ЕСЛИ у0.роду = уПост ТО
        СоздатьЦелПост(у0,ДЛИНА(у0.пон.достцепь^))
      ИНАЧЕ
        Длина(у0)
      КОН
  | Данные.зЗадано:
      ЗнакВЦепь(у0);
      ЕСЛИ НЕ ((у0.вид.родв = Данные.вЦепь) И (у0.роду = уПост)) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      у0.вид:=Данные.ключвид;
      ЕСЛИ Настрой.ЕстьКлюч(у0.пон.достцепь^) ТО
        у0.a:=1
      ИНАЧЕ
        у0.a:=0
      КОН
(* остались *)  
  | Данные.зИзПамяти,Данные.зВПамять,Данные.зОбраз:
      ЕСЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зЗначение:
      ЕСЛИ у0.роду # уВид ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      КОН
  | Данные.зСписать:
      ЗнакВЦепь(у0);
      ЕСЛИ НЕ (у0.вид.родв В {Данные.вЦепь,Данные.вОЦепь}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зПоставить,Данные.зСместить:
      ЕСЛИ родв # Данные.вБегунок ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зУвеличить,Данные.зУменьшить:
      ЕСЛИ у0.роду >= уПост ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зРазмер:
      ЕСЛИ НЕ (родв В {Данные.вРяд,Данные.вОРяд,Данные.вЦепь,Данные.вОЦепь,Данные.вОЯчейки}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.МНОГО_ИСТОЧНИКОВ)
  КОН
КОН ВстрПриёмник0;

(******************************************************************************)
ЗАДАЧА ВстрПриёмник1-(задача:ЦЕЛ; у0+,у1+:Узел.нВид);
ПЕР
  родв:ЦЕЛ; 
УКАЗ
  родв:=у1.вид.родв;
  ВЫБРАТЬ задача ИЗ
  | Данные.зИзПамяти:
      ПеренестиВРег(у0);
      у0.роду:=уАдрС;
      у0.a:=0;
      ЕСЛИ у1.роду >= уПост ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПЕРЕМЕННАЯ)
      АЕСЛИ у1.вид.родв В {Данные.вНеопр..Данные.вЦел32,Данные.вМнож,Данные.вДоступ,Данные.вЗадача,Данные.вВещ32} ТО
        у0.вид:=у1.вид;
        Переписать(у0,у1)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН; 
      у0.вид:=Данные.нетвид
  | Данные.зВПамять:
      ПеренестиВРег(у0);
      у0.роду:=уАдрС;
      у0.a:=0;
      ЕСЛИ у1.вид.родв В {Данные.вНеопр..Данные.вЦел32,Данные.вМнож,Данные.вДоступ,Данные.вЗадача,Данные.вВещ32} ТО
        у0.вид:=у1.вид;
        Переписать(у1,у0)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      у0.вид:=Данные.нетвид
  | Данные.зЗначение:
      ЕСЛИ (у0.вид.размер > у1.вид.размер) И (у1.роду В {уАдрС,уАдрСАдрС,уАдрЗС}) ТО
        (* возможны трудности с выравниванием *)
        ЕСЛИ ((у1.роду В {уАдрС,уАдрЗС}) И (у1.a ОСТАТОК у0.вид.размер # 0))
           ИЛИ
             ((у1.роду = уАдрСАдрС)      И (у1.b ОСТАТОК у0.вид.размер # 0))
        ТО
          Ошибка.Отметить(Ошибка.НЕТ_ВЫРАВНИВАНИЯ)
        КОН
      КОН;
      у1.вид:=у0.вид;
      у0:=у1
  | Данные.зСписать:
      ЕСЛИ НЕ (родв В {Данные.вЦепь,Данные.вОЦепь}) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН;
      Списать(у0,у1);
      у0.вид:=Данные.нетвид
  | Данные.зСместить:
      ЕСЛИ (у1.роду # уПост) ИЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.ИСТОЧНИК_НЕ_ЦЕЛАЯ_ПОСТ)
      КОН;
      (* работа ! ! *)
(* остались *)
  | Данные.зПоставить:
      ЕСЛИ родв # Данные.вРяд ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зОбраз:
      ЕСЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
      КОН
  | Данные.зУвеличить,Данные.зУменьшить:
      ЕСЛИ у1.вид # у0.вид ТО
        ЕСЛИ родв В Данные.множЦелых ТО
          у1.вид:=у0.вид
        ИНАЧЕ
          Ошибка.Отметить(Ошибка.ИСТОЧНИК_НЕ_ЦЕЛАЯ_ПОСТ)
        КОН
      КОН
  | Данные.зРазмер:
      ЕСЛИ (у1.роду # уПост) ИЛИ НЕ (родв В Данные.множЦелых) ТО
        Ошибка.Отметить(Ошибка.ИСТОЧНИК_НЕ_ЦЕЛАЯ_ПОСТ)
      КОН
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.МНОГО_ИСТОЧНИКОВ)
  КОН
КОН ВстрПриёмник1;

(******************************************************************************)
ЗАДАЧА ВстрПриёмник2-(задача:ЦЕЛ; у0+,у1+,у2+:Узел.нВид);
УКАЗ
  ЕСЛИ задача = Данные.зОбраз ТО
    ЕСЛИ НЕ (у2.вид.родв В Данные.множЦелых) ТО
      Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
    КОН; 
    ПеренестиВРег(у0);
    ПеренестиВРег(у1);
    ПеренестиВРег(у2);
    Образ(у0.ро,у1.ро,у2.ро);
    у0.вид:=Данные.нетвид
  АЕСЛИ задача = Данные.зПоставить ТО
    ЕСЛИ НЕ (у2.вид.родв В Данные.множЦелых) ТО
      Ошибка.Отметить(Ошибка.НЕ_СОВМЕСТИМО_С_ЗАДАЧЕЙ)
    КОН; 
(*  работа!
    ПеренестиВРег(у0);
    ПеренестиВРег(у1);
    ПеренестиВРег(у2);
    Образ(у0.ро,у1.ро,у2.ро);
*)
    у0.вид:=Данные.нетвид
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.МНОГО_ИСТОЧНИКОВ)
  КОН
КОН ВстрПриёмник2;

(******************************************************************************)
ЗАДАЧА ВстрПриёмникN-(    задача,
                      приёмников :ЦЕЛ;
                     у0+,у1+,у2+ :Узел.нВид);
ПЕР
  размерность:ЦЕЛ;
УКАЗ
  ВЫБРАТЬ задача ИЗ
  | Данные.зУвеличить,Данные.зУменьшить:
      ЕСЛИ приёмников = 1 ТО
        СоздатьЦелПост(у1,1)
      КОН;
      ЕСЛИ задача = Данные.зУвеличить ТО
        Увеличить(у0,у1)
      ИНАЧЕ
        Уменьшить(у0,у1)
      КОН;
      у0.вид:=Данные.нетвид
  | Данные.зРазмер:
      ЕСЛИ приёмников = 1 ТО
        размерность:=0
      ИНАЧЕ
        размерность:=у1.a
      КОН;
      ПОКА размерность > 0 ВЫП
        у0.вид:=у0.вид.овид;
        ЕСЛИ НЕ (у0.вид.родв В {Данные.вРяд,Данные.вОРяд,Данные.вЦепь,Данные.вОЦепь,Данные.вОЯчейки}) ТО
          Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_РАЗМЕРНОСТЬ)
        КОН;
        УМЕНЬШИТЬ(размерность)
      КОН;
      РазмерРяда(у0)
  ИНАЧЕ
  КОН
КОН ВстрПриёмникN;

КОН Узел.
