Entendiendo la instrucción ARM para el literal numérico

3

He hecho un seguimiento de instrucciones al intentar encontrar un error en un Cortex M3. Hay una parte del comando que no puedo entender.

STRB R1, [R3], #+0x01

Según documentación ARM , esto almacena un byte en R1.

Pensaría que R3 se almacena en R1, pero no puedo averiguar qué hace el # + 0x01.

He visto esta notación en otra parte de mi rastreo, y si bien entiendo # 0x01, no puedo entender qué hace el "+" con un literal. ¿Qué significa "# + 0x01"?

A continuación se muestra una captura de pantalla de mi rastro de instrucciones tomado de Ozono de Seggar.

    
pregunta Frankie

2 respuestas

3

Actualizado

Como lo señaló @ChrisStratton en los comentarios, la respuesta a continuación ignoró el hecho de que el procesador en uso no admite el conjunto de instrucciones ARM de 4 bytes, y solo ejecuta el código "Thumb". Según esta información y el hecho de que el depurador que se muestra en la pregunta aparentemente está decodificando instrucciones de 4 bytes (según el incremento de las direcciones para cada instrucción), parece que el depurador está mal configurado. Debería haber una configuración para forzarlo a desensamblar el código como instrucciones para el pulgar; esto debe habilitarse cuando se trabaja con procesadores Cortex M3.

He dejado la respuesta original a continuación, ya que responde a la pregunta como se hace (cómo interpretar la instrucción en particular que informa el depurador), pero se debe tener en cuenta que esta instrucción no aparece en su código, y solo es se muestra debido a la configuración incorrecta del depurador.

Respuesta original

Estás malinterpretando la documentación de ARM. La instrucción es:

STRB reg1, [reg2], #offset

donde el desplazamiento es un desplazamiento flexible .

El significado de esta instrucción es que los contenidos de reg1 se almacenan en la memoria en la dirección reg2 + offset . En este caso, R1 se almacena en el byte en la dirección 1 más alta que la dirección señalada por R3 .

Para ayudar a entender esto, tenga en cuenta que ARM es (predominantemente) una arquitectura de procesador de carga / almacenamiento, lo que quiere decir que distingue entre operaciones que mueven datos a la memoria ("registro de tienda", abreviado en el mnemotécnico como STR ), desde la memoria ("registro de carga", abreviado como LDR ) y otras operaciones que (generalmente) usan solo registros y no memoria (aunque con excepciones porque ARM no es una arquitectura de carga / almacenamiento pura). Las referencias a "cargar" o "almacenar" siempre se refieren a la memoria, y siempre se tratan en esa dirección. Una instrucción que copia los datos de un registro a otro no recibirá ese nombre (de hecho, en ARM sería MOV para el traslado).

Además, el enlace que proporcionó está en la sección incorrecta de la documentación de ARM. Eso describe las instrucciones disponibles en el conjunto de instrucciones "ARM Thumb", pero su programa parece estar usando el conjunto tradicional de instrucciones ARM completo (los programas "Thumb" tienen 2 bytes por instrucción, mientras que su programa tiene 4 bytes por instrucción, a juzgar por el direcciones mostradas en la salida del depurador). La sección correcta es la que comienza aquí . (Elimina esta sección porque es completamente incorrecta)

    
respondido por el Jules
3

Sin los códigos de operación originales, no es posible decir con total confianza si esta secuencia se está decodificando con precisión.

Sin embargo, una posibilidad que sería legítima en un Cortex M3 sería esta instrucción Thumb-2 de 32 bits descodificada por arm-none-eabi-objdump:

f803 1b01   strb.w  r1, [r3], #1

Este es del tipo que ARM Holdings llama "Sintaxis del pulgar (ancho, v6T2)" y un formato alternativo que se acerque más a la vista de su depurador sería:

STRB    Rt, [Rn], #-255…255

En este caso, el byte bajo del valor en r1 se almacenaría en la dirección en r3, y luego r3 sería (como se señaló por primera vez por @old_timer) incrementado en 1.

Este es un significado bastante plausible, ya que la traza de depuración hace que parezca que esto es parte de la implementación de la función memset() , que llena la memoria con un valor de byte.

Si este fuera el caso, entonces el pseudocódigo real sería algo así como:

//r0=memset(r0, r1, r2)
  Copy target address from r0 to working register r3
  Add length in r2 to target address in r0 or r3 and save in r2
another:
  if r3 equals r2 goto end
  store byte from r1 to address in r3, then increment r3 by one byte
  goto another
end:
  return instruction, with the un-incremented target address in r0

Como nota adicional, el rango de incremento para esta instrucción es de +/- 255 unidades, donde la unidad en este caso es un byte. Un byte completo de la instrucción de 32 bits está disponible para almacenar la magnitud del desplazamiento, mientras que el signo se almacena por separado.

La copia de la dirección base de r0 a r3 es necesaria porque memset() debe devolver la dirección base sin modificar, y convenientemente, en la misma r0 en la que se pasó.

    
respondido por el Chris Stratton

Lea otras preguntas en las etiquetas