GOOGLE ADS

martes, 19 de abril de 2022

se requiere un registro no desplazado: el ensamblador arroja un error en la instrucción TST

Actualmente estoy reescribiendo un algoritmo de C para ensamblar (CPU ARM Cortex M4).

¿Qué hace mi código?

Este algoritmo toma un número de 8 bits como entrada y comenzando desde la derecha nos dice cuál es el primer bit que es 0. Aquí hay algunos ejemplos:

Entrada: B01111111 Salida: 7

Entrada: B01110111 Salida: 3

Entrada: B11111110 Salida: 0

Aquí está el código C original que logró esto:

uint8_t find_empty(uint32_t input_word)
{
for (uint8_t searches=7; searches>=0; searches--)
{
if ((input_word&1)==0)
{
return 7-searches;
}

input_word=input_word>>1;
}
return 255;
}

Y aquí está mi intento de principiante de reescribir esto en el ensamblaje ARM (Cortex M4).

.global findEmpty
findEmpty:
mov r1, r0 //Move input_word to r1

//Config
mov r0, #7 //search through 8 (7+1) bits. <-searches
FindLoop:
tst r1, #1 //ANDs input_word with 1, sets the Z flag accordingly.

beq NotFoundYet //didn't get a 0, jump forward
rsb r0, r0, #7 //searches=7-searches <- which bit is 0?
bx lr //Return found bit number

NotFoundYet:
lsr r1, r1, #1 //input_word=input_word>>1
sub r0, r0, #1 //Decrement searches
cmp r0, #0
bpl FindLoop //If searches>=0, do the loop again.
mov r0, #255 //We didn't find anything. Return 255 to signal that
bx lr

Nota rápida:
usé r1 como una variable aquí, lo que escuché que no debe hacer como compilador (estoy vinculando mi archivo de ensamblaje ".S" a un archivo C con gcc) usa r0-r3 para pasar datos a y recibir datos de las funciones. Sin embargo, debido a eso, no usa estos registros para cosas importantes, por lo que no tengo que lidiar con empujar cosas a la pila, lo que ahorra ciclos.

¿Cuál es el problema?

Cuando trato de compilar mi proyecto, gcc me da un error de ensamblador en la línea TST:

Mensajes del ensamblador:
Error: se requiere registro no desplazado -- `tst r1, #1'

Esto es muy confuso para mí, ya que busqué en el sitio de Keil tanto la instrucción TST como la instrucción LSR que estoy usando más tarde para cambiar r1 por 1. Sin embargo, ninguno de ellos dice nada sobre no poder trabajar juntos. He buscado en línea para otras discusiones sobre este tema. Me encontré con esta discusión en la que la gente decía que le dijera al compilador que compilara en modo ARM, pero mi código ya se está ejecutando en modo ARM, no en Thumb. Lo confirmé creando otra subrutina.global e intentando agregar un 7 inmediato a un número y, por supuesto, no funciona, como no debería hacerlo si la CPU está en modo ARM.

.global illegal_add
illegal_add:
add r0, r0, #20
bx lr

Sé muy poco y no tengo ideas sobre cómo tratar de abordar este problema. Si alguien tiene alguna idea con cosas para probar, por favor hágamelo saber. Gracias por la ayuda.


Solución del problema

No me queda 100% claro cuál es el problema. Lo más probable es que haya olvidado configurar el ensamblaje correctamente. Para solucionar esto, emita estas directivas al principio del archivo:

.syntax unified
.cpu cortex-m4
.thumb

Si los coloco delante de su código, se ensambla perfectamente en mi máquina.

Algunos consejos generales:


  • lea qué instrucciones son codificables en 16 bits e intente elegir las instrucciones de estas. Las instrucciones de 16 bits se ejecutan más rápido y consumen menos memoria. Por ejemplo, puede usar lsrs r1, r1, #1en lugar de lsr r1, r1, #1para obtener una instrucción de 16 bits.

  • sé más inteligente con las manipulaciones de banderas. Muchas instrucciones ya te marcan la situación y, si eres inteligente, es probable que puedas evitar todas las tstinstrucciones cmp. Por ejemplo, si usa subs r0, r0, #1en lugar de sub r0, r0, #1guardar un byte (instrucción de 16 bits) y ya configuró el indicador Z de acuerdo con r0, guardándose la siguiente cmpinstrucción.

No hay comentarios.:

Publicar un comentario

Flutter: error de rango al acceder a la respuesta JSON

Estoy accediendo a una respuesta JSON con la siguiente estructura. { "fullName": "FirstName LastName", "listings...