Версия для печати

Пример оптимизации кода или как быстро проверить на правильность 8 BCD чисел.

Дата: 2016-06-18

Добавлено: komatic

Тема: SCL



optimization





Проверять BCD имеет смысл всегда, так как в случае неправильного числа при преобразовании его в формат INT командой BTI контроллер получит программную ошибку, попытается вызвать OB121 и в случае отсутсвия этого организационного блока перейдет в режим STOP, что обычно является нежелательным поведением ).
В контроллере BCD числа часто используются при работе с датами и временем, функция чтения даты времени контролллера возвращает данные в BCD формате.



Способ был найден в Standard Library -> IEC Function Blocks -> FC8 (DT_TOD), который выполняет преобразование из формата DATE_AND_TIME в формат TIME_OF_DAY, автор Siemens.





Немного теории - BCD число занимает четыре бита, и является валидным если оно не больше 9



Самый простой способ проверки - использвать 8 компараторов, которые совместно с операторами сдвига сгенерируют довольно много кода как показано ниже.





      L     B [AR1,P#0.0];
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#0.0];
      SLW   4;
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#1.0];
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#1.0];
      SLW   4;
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#2.0];
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#2.0];
      SLW   4;
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#3.0];
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
      L     B [AR1,P#3.0];
      SLW   4;
      SRW   4;
      L     9;
      >I    ;
      JC    fehl;
 
fehl: NOP   0; // ERROR



Оптимизация кода от Siemens использует тот факт, что если старший бит в тетраде (3 бит если счтить с нуля) установлен - то 2 и/или 1 бит не могут быть равны единице иначе число будет больше 9ти в любом случае.



результирующий код выглядит следующим образом.





L     D [AR1,P#3.0];
      T     #l_z_sp;
      AD    DW#16#66666666;         // sind die Bits 1 oder 2 der Tetrade gesetzt?
      PUSH  ;
      JZ    next;                   // wenn Bit 1 und 2 nicht gesetzt dann kein Fehler mцglich
      SLD   1;                      // es kann als Ergebnis des Bit 1 und/oder 2 gesetzt sein
      L     #l_z_sp;
      AD    ;                       // Ergebnismaske links schieben um herauszufinden ob das Bit
      AD    DW#16#88888888;         // zusдtzlich gesetzt ist
      JN    fehl;                   // wenn ja, dann Fehler
      TAK   ;                       // Maske aus Verundung 66666666 zurьckholen
      AD    DW#16#44444444;
      SLD   1;                      // Ergebnismaske schieben um herauszufinden ob Bit 3 gesetzt ist
      L     #l_z_sp;
      AD    ;                       // ist das Bit 3 auch gesetzt
      JN    fehl;                   // wenn ja, dann Fehler
next: NOP   0;                      // letztes Nibble prьfen
fehl: NOP   0;



opt

Результаты - размер кода приблизительно в половину меньше.



Аналог в SCL, выглядит чуть понятнее )





 
FUNCTION FC400 : VOID
 
VAR_TEMP
    BCDs : DWORD;
    Error : BOOL;
END_VAR
 
   IF    (BCDs AND SHL(IN:=BCDs,N:=1) AND DW#16#88888888) <> 0 THEN
        Error:=true;
   ELSIF (BCDs AND SHL(IN:=BCDs,N:=2) AND DW#16#88888888) <> 0 THEN
        Error:=true;
   END_IF;
 
END_FUNCTION



Результат компиляции





      L     #BCDs;
      SLD   1;
      L     #BCDs;
      AD    ;
      L     DW#16#88888888;
      AD    ;
      L     DW#16#0;
      <>D   ;
      JCN   A7d0;
      SET   ;
      =     #Error;
      JU    A7d2;
A7d0: L     #BCDs;
      SLD   2;
      L     #BCDs;
      AD    ;
      L     DW#16#88888888;
      AD    ;
      L     DW#16#0;
      <>D   ;
      JCN   A7d2;
      SET   ;
      =     #Error;
A7d2: CLR   ;









Просмотров: 3232

Комментарии к материалу

Ваш будет первым.

Добавить комментарий

Ваше имя:

Текст комментария (4000 max):

Введите сумму с картинки: