Пример оптимизации кода или как быстро проверить на правильность 8 BCD чисел.
Дата: 2016-06-18
Добавлено: komatic
Тема: SCL
Проверять 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;
Результаты - размер кода приблизительно в половину меньше.
Аналог в 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
Комментарии к материалу
Ваш будет первым.
Добавить комментарий