В статье разбирается реверс битов в Simatic Step 7 STL, где штатной команды для этого нет. Приводится реализация на основе алгоритма бинарного обмена для DWORD, WORD и BYTE, включая ускоренный вариант с командой CAD.
- Реверс битов — это отображение содержимого регистра относительно середины слова, то есть обратный порядок битов.
- В STL нет команды реверса битов; команды CAW и CAD реверсируют байты в слове и двойном слове, преобразуя форматы little-endian и big-endian.
- За основу реализации взят алгоритм бинарного обмена, описанный в книге Генри Уорена «Алгоритмические трюки для программистов» 2014 года.
- Для DWORD алгоритм реализован в FC12 с использованием только внутренних регистров и команд PUSH, TAK, AD, SLD, SRD, OD.
- Ускоренный вариант для DWORD сокращает алгоритм: после реверса отдельных байтов команда CAD делает две последние строки ненужными.
- Для WORD и BYTE приведены отдельные реализации алгоритма бинарного обмена с командами CAW и без неё соответственно.
- STL
- CAW
- CAD
- DWORD
- WORD
- BYTE
- little-endian
- big-endian
Кому полезно: Инженерам АСУ ТП, программирующим ПЛК Siemens на STL.
- Статья Siemens STL 03 — Цикличный сдвиг DWORD
- Статья Simatic S7-1200 TIA Portal V19 работа с битами переменной word
- Статья Классификация систем CAD/CAM/CAE
Первоисточник: we.easyelectronics.ru
Выжимка составлена редакцией сайта с помощью ИИ по тексту статьи.
Под операцией реверса битов понимается отображение содержимого регистра относительно середины слова, т.е. отображение битов в слове в обратном порядке.
В языке Simatic STL такой команды нет, имеющиеся CAW, CAD реверсируют байты в слове и двойном слове, т.е. преобразуют между форматами little-endian и big-endian. В стандартной библиотеке подобной функции так же нет. Для реализации был выбран алгоритм реверсирования на основе бинарного обмена из книги Генри Уорена «Алгоритмические трюки для программистов», 2014 г.
Его реализация на С для DWORD выглядит так:
x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
Это тот же алгоритм бинарного поиска (применялся для подсчета единичных бит), в котором операции сложения заменены на операции обмена. Его реализация на STL при расчетах использует только внутренние регистры:
FUNCTION FC12: VOID
TITLE = "Реверс двойного слова"
AUTHOR: Anakost //
FAMILY: SOHO //
NAME: RevrBits // Revers Bits
VERSION: 1.0 //
VAR_INPUT
INPUT: DWORD;
END_VAR
VAR_OUTPUT
OUTPUT: DWORD;
END_VAR
BEGIN
NETWORK
TITLE = Алгоритм бинарного обмена DWORD
L #INPUT;
// x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
PUSH; // копия ACCU1 в ACCU2
AD DW#16#55555555; // ACCU1 and 0x55555555
SLD 1; // ACCU1 << 1
TAK; // ACCU1 <-> ACCU2
AD DW#16#AAAAAAAA; // ACCU1 and 0xAAAAAAAA
SRD 1; // ACCU1 >> 1
OD; // ACCU1 <- ACCU1 or ACCU2
// x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
PUSH; //
AD DW#16#33333333; //
SLD 2; //
TAK; //
AD DW#16#CCCCCCCC; //
SRD 2; //
OD; //
// x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
PUSH; //
AD DW#16#0F0F0F0F; //
SLD 4; //
TAK; //
AD DW#16#F0F0F0F0; //
SRD 4; //
OD; //
// x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
PUSH; //
AD DW#16#00FF00FF; //
SLD 8; //
TAK; //
AD DW#16#FF00FF00; //
SRD 8; //
OD; //
// x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
PUSH; //
AD DW#16#0000FFFF; //
SLD 16; //
TAK; //
AD DW#16#FFFF0000; //
SRD 16; //
OD; //
//------------------
T #OUTPUT; //
END_FUNCTION
Алгоритм довольно быстрый, но используя вышеупомянутую команду CAD его можно значительно упростить и убыстрить. Достаточно только отреверсить отдельные байты, т.е. две последние строчки алгоритма будут не нужны.
NETWORK
TITLE = Алгоритм бинарного обмена FastDWORD
L #INPUT;
// x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1;
PUSH; // копия ACCU1 в ACCU2
AD DW#16#55555555; // ACCU1 and 0x55555555
SLD 1; // ACCU1 << 1
TAK; // ACCU1 <-> ACCU2
AD DW#16#AAAAAAAA; // ACCU1 and 0xAAAAAAAA
SRD 1; // ACCU1 >> 1
OD; // ACCU1 <- ACCU1 or ACCU2
// x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2;
PUSH; //
AD DW#16#33333333; //
SLD 2; //
TAK; //
AD DW#16#CCCCCCCC; //
SRD 2; //
OD; //
// x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4;
PUSH; //
AD DW#16#0F0F0F0F; //
SLD 4; //
TAK; //
AD DW#16#F0F0F0F0; //
SRD 4; //
OD; //
//-----------------------
CAD; // реверс байтов в DWORD
//-----------------------
T #OUTPUT; //
Реверс битов для WORD:
VAR_INPUT
INPUT: WORD;
END_VAR
...
NETWORK
TITLE = Алгоритм бинарного обмена WORD
L #INPUT;
PUSH;
SRW 1;
AW W#16#5555;
TAK;
SLW 1;
AW W#16#AAAA;
OW;
PUSH;
SRW 2;
AW W#16#3333;
TAK;
SLW 2;
AW W#16#CCCC;
OW;
PUSH;
SRW 4;
AW W#16#0F0F;
TAK;
SLW 4;
AW W#16#F0F0;
OW;
CAW;
T #OUTPUT;
Реверс битов для BYTE:
VAR_INPUT
INPUT: BYTE;
END_VAR
...
NETWORK
TITLE = Алгоритм бинарного обмена BYTE
L #INPUT;
PUSH;
SRW 1;
AW B#16#55;
TAK;
SLW 1;
AW B#16#AA;
OW;
PUSH;
SRW 2;
AW B#16#33;
TAK;
SLW 2;
AW B#16#CC;
OW;
PUSH;
SRW 4;
AW B#16#0F;
TAK;
SLW 4;
AW B#16#F0;
OW;
T #OUTPUT;
Источник: http://we.easyelectronics.ru/plc/simatic-step-7-stl-revers-bit.html