No es necesario (?) cargar el registro de PC con la siguiente dirección de instrucción en ARM

1

Estoy tratando de comprender el código de inicio del ensamblador para mi procesador ARM7TDMI. Conseguí la mayor parte, pero hay una cosa que me molesta. Encontré esta línea:

//------------------------------------------------------------------------------
/// Initializes the chip and branches to the main() function.
//------------------------------------------------------------------------------
            .section    .text
            .global     entry

entry:
resetHandler:

/* Dummy access to the .vectors section so it does not get optimized */
        ldr     r0, =resetVector

/* Set pc to actual code location (i.e. not in remap zone) */
       ldr     pc, =1f

/* Perform low-level initialization of the chip using LowLevelInit() */
1:
        ldr     r4, =_sstack
        (...)

El que no entiendo es ldr pc, =1f . ¿Es necesario? ¿Por qué alguien cargaría explícitamente la siguiente dirección de instrucciones? ¿No se leería automáticamente si se omitiera la línea?

        ldr     r0, =resetVector   

/* Perform low-level initialization of the chip using LowLevelInit() */
1:
        ldr     r4, =_sstack
        (...)

¿Cuál es la diferencia? ¿Tiene algo que ver con la vinculación o la reasignación de memoria?

EDITAR:

Bien, gracias a los comentarios a continuación, creo que lo tengo. Mirando todo el código:

125 resetHandler:
126 
127 /* Dummy access to the .vectors section so it does not get optimized */
128         ldr     r0, =resetVector
129 
130 /* Set pc to actual code location (i.e. not in remap zone) */
131         ldr     pc, =1f
132 
133 /* Perform low-level initialization of the chip using LowLevelInit() */
134 1:
135         ldr     r4, =_sstack
136         mov     sp, r4
137         ldr     r0, =LowLevelInit
138         mov     lr, pc
139         bx      r0

El flash tiene primero un alias de 0x0 (y se puede acceder en cualquier momento a 0x100000). La memoria RAM está en 0x200000, y se volverá a asignar a 0x0 más adelante (en la función LowLevelInit). Por lo tanto, la línea 131 carga el pc con la dirección en flash de modo que la instrucción en la línea 135 se ejecute directamente desde flash. Si no fuera por eso, la instrucción 138 cargaría el registro lr con el valor pc del espacio con alias (0x0 - ...). Y debido a que LowLevelInit realiza la reasignación, sin la etiqueta 1: , se cargaría lr con un valor inadecuado (que apunta a la RAM después de la reasignación). Entonces, cuando regresemos de LowLevelInit ( bx r0 ) terminaríamos en un lugar diferente al de donde queríamos comenzar. ¿Es eso correcto?

    
pregunta Bart

2 respuestas

2

Esos chips pueden (bajo el control del software) reubicar el área de vectores en un lugar diferente en la memoria. Esto se aplica a una parte limitada de la memoria, que podría no incluir ese código de inicialización de bajo nivel. Por lo tanto, cuando se activa el vector de reinicio reubicado, el código de inicio no es "después" del vector. La reubicación de ara probablemente esté demasiado alejada del código de inicio para un salto normal (¿IIRC con solo 24 bits de compensación?), Por lo que se usa una carga explícita de PC.

Para decirlo de otra manera: el autor sabía (o pensó, quizás se equivocó ...) que las dos primeras líneas del código que se muestran se pueden asignar (alias) a dos lugares diferentes en la memoria, pero El siguiente código estaría solo en un lugar. El "ldr pc, = 1f" salta de ambas asignaciones posibles a la que (también) contiene las siguientes instrucciones.

Esto es importante solo cuando el vector de restablecimiento está activado (el chip se restablece) a través de la dirección del vector reasignada.

    
respondido por el Wouter van Ooijen
1

La sintaxis ldr pc, =1f es pseudocódigo para cargar un valor del conjunto constante para esta función. Se expande a

    ldr pc, c1-.[pc]
1:
    ...

c1:
    .dw 1b

Entonces, esta es una carga de 32 bits, con una dirección absoluta generada con un registro de reubicación. Cuando este código esté vinculado, los datos en .dw pseudo-op se reubicarán de modo que apunten a la dirección absoluta de la etiqueta l .

Esto es útil si el código se asigna varias veces en la memoria, por ejemplo. una vez en la dirección cero (de modo que forma una tabla de vectores primitivos con solo un vector de restablecimiento), y una vez en la dirección final, y debe ejecutarse desde la dirección final para que las direcciones de la tabla de vectores puedan volver a asignarse a la RAM.

El área de datos que contiene c1 se genera cuando el ensamblador ve una rama incondicional, un cambio a otra sección, el final del archivo de entrada o una pseudo instrucción para emitir la agrupación constante. El área de datos debe vivir en un desplazamiento fijo y no demasiado grande del código que lo utiliza, ya que se trata en relación con la PC.

    
respondido por el Simon Richter

Lea otras preguntas en las etiquetas