¿Por qué se utiliza un registro de 16 bits con la instrucción BSR en este fragmento de código?

StackOverflow https://stackoverflow.com/questions/1818374

  •  10-07-2019
  •  | 
  •  

Pregunta

En este artículo hardcore hay una función < code> find_maskwidth () que básicamente detecta la cantidad de bits necesarios para representar los valores dictinct de 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; 
} 

la pregunta es ¿por qué usan los registros ax y cx en lugar de eax y ecx ?

¿Fue útil?

Solución

Solo puedo suponer que esperan tratar solo con campos que no tengan más de 16 bits. Dado que se usa para determinar la cantidad de bits que se pueden usar para informar cosas como la cantidad de núcleos o procesadores lógicos en un paquete, probablemente pasará un tiempo antes de que se desborde por encima de 65535.

Solo espero que alguien no decida usar la rutina para un propósito más general.

Y solo un FYI: si desea hacer algo como esto sin pasar al ensamblado x86 (aunque supongo que para el propósito del artículo, ser no portátil es prácticamente un hecho), el La página de Bit Twiddling Hacks lo tiene cubierto.

Otros consejos

Supongo que los datos originales tienen solo 16 bits de ancho. Como cx está obteniendo un número de bit, no hay posibilidad de que sea mayor que un número muy pequeño de todos modos.

Es interesante observar que en un nivel los códigos de operación para las instrucciones ia32 de 16 y 32 bits son los mismos, excepto para el byte de prefijo, por lo que es más eficiente emitir instrucciones de 32 o 16 bits, dependiendo en qué modo estás. Supongo que por eso hiciste la pregunta ...

Dado el hecho de que este código está realmente muy mal escrito (no hay absolutamente ninguna necesidad de las variables maskWidth y count, por ejemplo, aparte de hacer que el código sea confuso), supongo que puede estar seguro de que es solo otro " ; cosa mala " en este código.

La rutina determina fundamentalmente el logaritmo binario (base dos) de itemCount.

Entregará valores completamente incorrectos, si itemCount > 2 ^ 16. No se satura o algo, simplemente está mal. El parámetro de entrada es "unsigned int", lo que lo hace aún más incorrecto. Entonces dejará de funcionar en más de 65536 núcleos.

Supongo que alguien en Intel desenterró una pieza de código muy antigua, que data de 16 bits, sin comprenderlo realmente, y la usó, porque 65536 será suficiente para siempre, exactamente como 640k de memoria será suficiente para siempre o como números de año de dos dígitos serán suficientes hasta el final de los tiempos.

Diría que es porque el autor de este código probablemente no sabía realmente lo que estaba haciendo :-). Las versiones de 16 bits de estas instrucciones son más largas y no más rápidas. De hecho, probablemente causarán un bloqueo parcial del registro en la próxima instrucción que use ECX (es decir, el MOV).

También tenga en cuenta que el salto se puede mover con seguridad una instrucción antes (después de DEC), ya que DEC ya establece ZF cuando su salida es cero. Esto puede simplificar un poco el código.

Entonces, así es como escribiría este fragmento de código:

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

Además, la motivación para pasar al ensamblaje aquí parece estar usando la instrucción BSR, que no tiene ningún equivalente en el lenguaje C o en la biblioteca. Puede evitar el uso del ensamblaje utilizando una función intrínseca específica del compilador para este propósito. Si bien estos son inherentemente no portables, tampoco lo es el ensamblaje en línea.

En GCC, la función equivalente se vería así:

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

Mucho más legible, ¿no?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top