Почему 16-битный регистр используется с инструкцией BSR в этом фрагменте кода? - PullRequest
0 голосов
/ 30 ноября 2009

В этой хардкорной статье есть функция find_maskwidth(), которая в основном определяет количество битов, необходимых для представления itemCount точных значений:

unsigned int find_maskwidth( unsigned int itemCount )
{
    unsigned int maskWidth, count = itemCount;
    __asm {
        mov eax, count
        mov ecx, 0
        mov maskWidth, ecx
        dec eax
        bsr cx, ax
        jz next
        inc cx
        mov maskWidth, ecx
    next:
    }
    return maskWidth; 
} 

вопрос в том, почему они используют регистры ax и cx вместо eax и ecx?

Ответы [ 5 ]

2 голосов
/ 30 ноября 2009

Я могу только догадываться, что они ожидают когда-либо иметь дело только с полями, которые имеют не более 16 бит. Поскольку он используется для определения количества битов, которые можно использовать для сообщения таких вещей, как количество ядер или логических процессоров в пакете, вероятно, пройдет некоторое время, прежде чем он переполнится выше 65535.

Я просто надеюсь, что кто-то не решит использовать рутину для более общего назначения.

И просто к сведению - если вы хотите сделать что-то подобное, не переходя на сборку x86 (хотя я предполагаю, что для цели статьи непереносимость в значительной степени само собой разумеющееся), страница Bit Twiddling Хаки покрыл ли ты.

1 голос
/ 15 марта 2010

Я бы сказал, что это потому, что автор этого кода, вероятно, не знал, что он делает :-). 16-битные версии этих инструкций длиннее и не быстрее. Фактически, они, вероятно, приведут к частичному сбою регистра в следующей инструкции, которая использует ECX (то есть MOV).

Также обратите внимание, что переход может быть безопасно перемещен одной инструкцией ранее (после DEC), так как DEC уже устанавливает ZF, когда его выход равен нулю. Это может немного упростить код.

Так вот, как бы я написал этот фрагмент кода:

  mov eax, [count]
  xor ecx, ecx
  dec eax
  jz next
  bsr ecx, eax
  inc ecx
next:
  mov [maskWidth], ecx

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

В GCC эквивалентная функция будет выглядеть следующим образом:

unsigned int find_maskwidth(unsigned int itemCount)
{
   if(itemCount <= 1)
      return 0;
   else
      return 32 - __builtin_clz(itemCount - 1);
}

Намного более читабельно, не так ли?

1 голос
/ 30 ноября 2009

Процедура в основном определяет двоичный (основание два) логарифм itemCount.

Он выдаст совершенно неправильные значения, если itemCount> 2 ^ 16. Это не насыщает или что-то, это просто неправильно. Входной параметр "unsigned int", что делает его еще более неправильным. Так что перестанет работать на более 65536 ядер.

Я предполагаю, что кто-то из Intel выкопал какой-то действительно древний кусок кода, датируемый 16-битными разами, не понимая его, и использовал его, потому что 65536 будет достаточно навсегда, точно так же, как 640 КБ памяти будет достаточно навсегда или так как двухзначных чисел года будет достаточно до конца времени.

1 голос
/ 30 ноября 2009

Учитывая тот факт, что этот код действительно очень плохо написан (например, абсолютно не нужны переменные maskWidth и count - кроме того, что код запутан), я думаю, вы можете быть уверены, что это просто еще один " плохо "в этом коде.

1 голос
/ 30 ноября 2009

Полагаю, исходные данные имеют ширину всего 16 бит. Поскольку cx получает битовое число, нет никаких шансов, что оно все равно может быть больше очень маленького числа.

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

...