Desplazamientos en 2 registros de 32 bits

void rotate( unsigned long mask[], int rotateCnt ); 

Esta función rota la máscara actual de 64 bits (máscara[]) rotateCnt lugares. Si el rotateCnt es positivo, girar a la izquierda; Si el rotateCnt es negativo, gire a la derecha. Sólo los 6 bits inferiores del rotateCnt debe usarse para el rotateCnt.

Pero tengo que hacer la rotación, en 2 registros de 32 bits que simulan 1 registro de 64 bits, realizando lógicamente operaciones de 64 bits en dos registros de 32 bits. Me dijeron que hiciera 2 bucles, pero no puedo resolver esto. Cualquier h

preguntado el 03 de mayo de 12 a las 16:05

Creo que parte de tu pregunta ha sido cortada. Aunque parece que querías que terminara con "¿Alguna ayuda?" -

No ha especificado con qué CPU está trabajando. -

Estoy trabajando con un procesador x86 SunOS 5.10 -

¿Supongo que esto es tarea? -

@Skizz: pero aprender a ensamblar es lo que debe ocurrir antes de que pueda usar el ensamblado de manera efectiva. Tienes que aprender a caminar antes de poder correr. Y esa puede ser la etapa en la que se encuentra esta clase. -

4 Respuestas

Mientras usa x86, eche un vistazo a shld y shrd. No necesitará bucles (no entiendo por qué pidieron bucles).

Noticias

Aquí hay una función de estilo DevStudio 2005 que usa un ensamblador en línea para hacer lo que quiere. No presente esto como una solución sin comprender completamente cómo funciona todo (especialmente cómo los números negativos giran a la derecha) porque será increíblemente fácil para sus profesores detectar que copió esto sin saber cómo funciona (es decir, Profesor: " ¿Cómo funciona esto?", Tú: "Errr..." => FALLA).

void Rotate
(
  unsigned *value, // pointer to two 32bit integers
  int count        // number of bits to rotate: >= 0 left, < 0 = right
)
{
  __asm
  {
    mov esi,value
    mov eax,[esi]
    mov edx,[esi+4]
    mov ecx,count
    mov ebx,eax
    shld eax,edx,cl
    shld edx,ebx,cl
    test cl,32
    jz noswap
    xchg edx,eax
noswap:
    mov [esi],eax
    mov [esi+4],edx
  }
}

contestado el 03 de mayo de 12 a las 17:05

Quieren que lo implementemos usando dos bucles, uno si el rotarCnt es positivo rotarlo a la izquierda; si el rotarCnt es negativo rotar a la derecha. - brasa619

@Brasa619: Sí, pero ¿por qué un bucle? El x86 tiene cambios y rotaciones de varios bits. - esquizo

Estoy de acuerdo con skizz, shld/shrd es una respuesta mucho mejor si vas a escribir código ensamblador real. De lo contrario, "shld 1" se puede simular fácilmente usando rol y rcl (rotar con acarreo a la izquierda), y un ciclo le permitirá hacer N bits. Del mismo modo para shrd. - Ira Baxter

Supongo que el requisito del ciclo está ahí por razones similares a las que se enseña la multiplicación como una suma repetida. O tal vez la iteración, el manejo de acarreos y/o el almacenamiento seguro de valores temporales pueden ser el punto del ejercicio más que cuál es la forma más eficiente de rotar. - miguel rebabas

Probablemente haya instrucciones más rápidas para esto, pero esta es la idea... Si gira a la izquierda:

  1. tomar lo más significativo rotateCnt bits del registro de orden superior, desplácelos a la derecha 32-rotateCnt bits, y guardar el resultado en algún lugar

  2. desplazar el registro de orden superior a la izquierda por rotateCnt los bits

  3. tomar lo más significativo rotateCnt bits del registro de orden inferior, desplácelos a la izquierda 32-rotateCnt bits, y agregue el resultado al registro de orden superior

  4. desplazar los bits restantes en el registro de orden inferior dejado por rotateCnt bits y agregue los bits que guardó en el paso 1

Estoy seguro de que puede ver cómo extender este proceso a cualquier número de registros. Si rotateCnt puede tener más de 32 bits, tendrá que trabajar un poco más, especialmente en el caso general (n registros en lugar de solo 2). Una cosa que puede ayudar es notar que desplazar a la izquierda n bits es lo mismo que desplazar a la derecha (tamaño n) bits.

Por tus comentarios, veo que se supone que debes usar un bucle. Siempre puede aplicar el procedimiento de rotación descrito anteriormente 1 bit a la vez para iteraciones de rotarCnt. En ese caso, obviamente cambiarías rotateCnt en la descripción anterior para 1.

contestado el 03 de mayo de 12 a las 16:05

Una rotación de un solo bit es simplemente un cambio de un solo bit con acarreos de una palabra que se aplica a la siguiente palabra con un caso especial en el que se aplica un acarreo de la palabra alta a la palabra baja.

Puede ser útil considerar una imagen de lo que debe suceder en ciertos escenarios. Usaré palabras de 4 bits a continuación y asumiré que la rotación es hacia la izquierda; los mismos conceptos se aplican a cualquier tamaño de palabra que pueda usar:

// Note '-' in the carry column means "don't care"
//
// starting value (in binary):

              'high'             'low'
     carry     word     carry     word

        -     1 0 0 0     -     1 0 0 1

//  after shift left of each word:

        1     0 0 0 0      1    0 0 1 0

//  apply the carry out of the low word
//      to the high word:

        1     0 0 0 1      -    0 0 1 0    

//  apply the carry out of the high word
//      to the low word

        -     0 0 0 1      -    0 0 1 1    

Para utilizar esta operación básica para rotar varias posiciones, simplemente realice un bucle el número adecuado de veces.

Tenga en cuenta que esto se puede hacer sin ningún bucle aplicando el conjunto correcto de máscaras de bits y cambios. Básicamente, puede obtener todos los bits que se llevarán a cabo de una palabra de una sola vez sin bucles. Una versión en bucle es probablemente más sencilla de implementar; puede considerar hacer eso primero y usarlo como una prueba de verificación si decide mejorarlo a una versión sin bucle.

contestado el 03 de mayo de 12 a las 16:05

piense en cómo haría esto en C, por ejemplo, luego tradúzcalo a asm.

Usar variables de 32 bits para hacer un desplazamiento de un solo bit a la izquierda, por ejemplo, asumiendo que ra son los 32 bits superiores y rb los inferiores

if(rb&0x80000000) { ra<<=1; ra|=1; rb<<=1 }
else              { ra<<=1; rb<<=1; }

Para una rotación, puede hacer algo en este sentido

if(rb&0x80000000)
{
  if(ra&0x80000000) { ra<<=1; ra|=1; rb<<=1: rb|=1; }
  else              { ra<<=1; ra|=1; rb<<=1; }
}
else
{
  if(ra&0x80000000) { ra<<=1; rb<<=1: rb|=1; }
  else              { ra<<=1; rb<<=1; }
}

Luego puede envolver un bucle alrededor de uno de esos y hacerlo N veces.

O diga un cambio de 8 bits a la izquierda

ra=(ra<<8)|(rb>>(32-8));
rb<<=8;

O diga un cambio de bit N a la izquierda

ra=(ra<<=n)|(rb>>(32-n));
rb<<=n;

O una rotación de n bits a la izquierda (que es lo mismo que una rotación de 32 n bits a la derecha) (hay una razón por la cual algunos procesadores solo tienen una rotación a la derecha y la izquierda es virtual o viceversa).

temp=ra>>(32-n);
ra=(ra<<=n)|(rb>>(32-n));
rb=(rb<<<=n)|temp;

Luego mire el conjunto de instrucciones y vea lo que está disponible y coincide con lo que está haciendo.

En resumen, para cambiar bits, debe tomar el bit de un lado y colocarlo en el siguiente bit. Si se alinea en algún límite como una variable o registro, no hay diferencia, toma el bit de un lado y lo cambia al otro, puede tomar más código ya que el conjunto de instrucciones o el lenguaje de programación no lo admiten directamente, no significa que no pueda hazlo. Al igual que puede realizar una multiplicación de 2048 bits en un procesador de 8 bits sin instrucción de multiplicación, solo requiere más código que otros procesadores, pero es muy factible.

contestado el 03 de mayo de 12 a las 18:05

Mi pregunta principal es cómo desplazar los bits hacia la izquierda o hacia la derecha teniendo en cuenta el giratorioCnt que está entre -63 y +63. - brasa619

¿Cómo tomamos eso en cuenta en la arquitectura SPARC ya que solo tiene ld y st. ¿Cómo almaceno ese bit que se lleva desde el MSB de un registro al LSB del otro registro? - brasa619

Si el número es negativo, hágalo positivo y cambie una dirección; si es positivo, cambie la otra dirección... Tal vez los dos bucles provengan de un bit a la vez, un bucle para la izquierda y otro bucle para la derecha. - viejo contador de tiempo

¿Está insinuando que los procesadores SPARC no pueden ejecutar programas en C? No se puede ejecutar Unix o Linux, etc. porque no pueden implementar una operación AND, o comparar con cero o un cambio (el desplazamiento a la izquierda se puede implementar con suma o multiplicación por cierto, el desplazamiento a la derecha con una división o con un bucle usando desplazamientos a la izquierda y comparaciones) ). hay una miríada de maneras de resolver este problema. elige uno. - viejo contador de tiempo

Acabo de mostrarte cómo hacerlo, mira el código, if (rb&0x80000000) then rb<<=1; rb|=1; Estos son muy simples de implementar en casi todos los lenguajes ensambladores. Si es un procesador de 8 bits, solo tienes que hacerlo 8 veces. Por cierto, el ensamblaje lo hace mucho más fácil si tiene un cambio de rotación a través del transporte y desea ir un poco a la vez. si no, simplemente impleméntelo de una de las otras maneras. - viejo contador de tiempo

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.