Битовые операции на с++ с помощью __asm

Помогите не могу понять как сделать это с ассемблерной вставкой Переписать в массив те элементы массива слова, которого имеют парную количество единичных битов в пределах от 5-го до и 10-го разрядов

.

#include<iostream>
#include<string>

using namespace std;

int main() {

    string mas[4] = { "sad","213","dwer","we234" };

    string mas2[4];

    _asm {
      }

      for (int i = 0; i < 4; i++) {
        cout << mas2[i] << endl;
      }

        system("pause");
    }

Ответы (2 шт):

Автор решения: KoVadim

Разобъем задачу на несколько кусков - посчитать биты в числе, проверить их четность, сделать цикл.

Начнем с подсчета битов.

Есть два способа сделать эту задачу. Можно взять и посчитать от 5 до 10 разряда биты.

int c = 0; // счетчик
unsigned int n = 1000; // наше число

for (int i  = 5; i <10; i++) {
  unsigned int r = 1 << i;
  if (n & r > 0) {c++;}
}

возможно, в условии нужно написать i<=10, в зависимости от того, "включая 10 бит или нет".

Не думаю, что это будет сложно перевести на ассемблер.

Но можно сделать проще и легче. Есть такая инструкция popCount и она доступна в ассемблерном коде. И вся задача сводиться к двум действиям - вначале все биты, которые не входят в наш диапазон зануляем, а потом с помощью popCount считаем оставшиеся единичные биты. popCount доступна в Intel/AMD процессорах с 2008 года, так что сойдет.

unsigned int n = 1000; // наше число
n = n &  0x07E0; // 0'0111'1110'0000 // c 5 по 10 включительно
int r = popcount(n);

на ассемблерном коде это где то так

    and     eax, 2016
    popcnt  eax, eax
    ret

В случае Visual Studio нужно подключить #include <intrin.h> и сама функция называется __popcnt.

Если по какой то причине так просто нельзя, можно взять готовый алгоритм подсчета единичных битов

Теперь у нас есть функция, которая умеет считать биты. Проверить, четное ли количество очень просто - по последнему биту (он должен быть нулевым для парного) или использовать % 2 == 0

В принципе, осталось завернуть в цикл и готово решение.

P.S. преподаватель может по другому считать биты (слева на право или с единицы, а не нуля, да и я мог в коде промазать), так что лучше уточнить этот момент персонально, благое дело, это очень легко поправить в коде.

→ Ссылка
Автор решения: Алексей Гончаров

Вариант который мне скинули на кибер форуме

#include<iostream>
#include<string>
 
using namespace std;
 
int main() {
 
    string mas[4] = { "sad","213","dwer","we234" };
 
    string mas2[4];
    size_t size2 = 0;   //размер второго массива
 
    for (int i = 0; i < 4; ++i)
    {
        //берем два последних байта, т.к. в них находятся биты с 5 по 10
        // будем считать, что нумерация битов и байтов начинается с правого края
        // при чтении предпоследний символ попадет в младший байт uint16_t, а последний - в старший
        // поэтому маска "перевернута"!
        uint16_t x = *((uint16_t*) &mas->c_str()[mas[i].size() - 2]);   //читаем 2 последних символа, как 16-ричное число
        bool f;                             //признак четности указанных бит
        _asm
        {
            and x, 1110000000000111b        //выделяем биты (см выше)
            lahf                            //читаем флажки, нас интересует флаг четности P
            and ah, (1<<2)                  //выделяем бит P
            mov f, ah                       //и результат сохраняем в f
        }
        if (f)
            mas2[size2++] = mas[i];         //если не 0, то сохраняем слово в новый массив
    }
 
    for (size_t i = 0; i < size2; i++) {
        cout << mas2[i] << endl;
    }
 
    system("pause");
}
→ Ссылка