Зеркальное отражение встроенной сборки Byte / X86 (в visual studio 2010) - PullRequest
2 голосов
/ 12 ноября 2010

У меня проблемы с зеркальным отображением байта, и я не могу найти какие-либо методы через Google.Я пытаюсь выполнить зеркальное отображение содержимого байта, иначе: 10000000 = 00000001 10010111 = 11101001 и т. Д. *

Я использую сборку, встроенную в C в Visual Studio 2010.время и помощь

Редактировать: Скорость не нужна, извините, что не указал на это.Это ДОЛЖНО быть написано на ассемблере.

Ответы [ 6 ]

5 голосов
/ 12 ноября 2010

Пока вы не заботитесь о скорости, вы можете повернуть вправо с помощью переноса (rcr) от вашего источника и повернуть влево с помощью переноса (rcl) в пункте назначения (или наоборот).

Если вы хотите, чтобы он был быстрым, просто воспользуйтесь поиском в таблице (поскольку вам нужен только один байт за раз, это будет только таблица из 256 байт).

2 голосов
/ 12 ноября 2010

Для байта используйте справочную таблицу. Таблица поместится в кэш L1 и будет быстрой.

Для более длинных значений можно использовать сдвиг и маскировку способами, которые ускоряют процесс, а не делают это по одному биту за раз. Например, для 32-битных значений:

uint32_t bit_reverse_32(uint32_t x)
{
    x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555);
    x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333);
    x = ((x & 0x0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F);
    x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF);
    x = (x << 16) | (x >> 16);
    return x;
}

Преобразование этого кода C в сборку оставлено в качестве упражнения или, что еще лучше, оставлено в качестве задания для компилятора C, который делает такие вещи для жизни.

0 голосов
/ 12 ноября 2010

Вот не рекомендуемое решение, просто для удовольствия. Я проверил несколько конверсий, но не все. Определенно, поиск таблиц - это именно то, что нужно, и принятый ответ на поворот и перенос - это то, что я использовал в прошлом.

В приведенном ниже решении используется умножение, чтобы разделить младшие 4 бита на старшие биты, а затем модуль 2 ** n-1 для свертывания битов обратно.

Вот версия за один шаг, но использует 64-битное умножение: http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv

#include <stdlib.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
    int x, y;

    for (x=0; x<256; x++)
    {

        // magic number / bit distribution way of flipping 4 bits
        // y = ((x * 0x00082082 & 0x01122408) % 255) >> 2;
        _asm 
        {
            mov ecx, x          // get operand
            mov eax, ecx        // get lower 4 bits into eax
            and eax, 0x0f
            mov ebx, 0x82082    // get magic multiplier into ebx
            imul eax, ebx       // distribute lower into upper bits
            and eax, 0x1122408  // and out the bits we want
            mov edx, 0          // initilialize upper DX:AX bits
            mov edi, 0xff       // modulo divisor
            idiv edi            // divide, leaving remainder in DX
            shr edx, 2          // adjust result
            mov esi, edx        // stash first half of flipped bits
            shl esi, 4

            // repeat with upper bits
            mov eax, ecx
            shr eax, 4
            imul eax, ebx
            and eax, 0x1122408
            mov edx, 0
            idiv edi
            shr edx, 2
            or edx, esi

            mov y, edx
        };

        printf("x %08x reverse %08x\n", x, y);
    }   

    return 0;
}
0 голосов
/ 12 ноября 2010

Разделите и победите: разделите байт пополам, переверните левую половину, переверните правую половину, затем переверните обе половины.например, 10000100

деление: 1000 0100

слева: 0001

справа: 0010

оба: 0010 0001

00100001

Это уменьшает размер таблицы с 256 байт до 16 байт, поэтому вы можете легко проверить, правильно ли она выполняет переворот, за счет дополнительных вычислений.

0 голосов
/ 12 ноября 2010

Я не уверен, если вам нужно использовать сборку.Поскольку вы уже встраиваете сборку в C, вы можете создать простую справочную таблицу в C и вообще пропустить сборку ...

byte const mirror[256] = {
0x00, 0x80, 0x40, 0xc0, ...
};
0 голосов
/ 12 ноября 2010

Я предполагаю из того факта, что вы опустились до уровня ассемблера, что вы после скорости.Если это так, самый быстрый способ сделать это через справочную таблицу.В этот момент вам не понадобится ассемблер (потому что он будет так же быстр в C).

Обратите внимание, что многие встроенные платформы (обычно DSP) будут иметь собственную команду обратного бита.Но это, вероятно, бесполезно для вас!

...