¿Cómo se asignan los datos en un lenguaje ensamblador usando el conjunto de instrucciones?

Considere el siguiente extracto del código ensamblador escrito para la arquitectura del procesador integrado Nios II :

    .section .data
    .align 2
va:   .long 0x0
vb:   .long 0x11223344
vc:   .long 0x55667788

Se debe hacer lo siguiente:

  • Asigne suficiente memoria para las tres variables
  • Asegúrese de que la memoria asignada sea contigua
  • Traducir instrucciones que usan el nombre de una variable en instrucciones que usan la dirección de la variable

No veo cómo se puede hacer esto a través del conjunto de instrucciones y esperaba alguna idea sobre cómo se produce la traducción del código anterior al conjunto de instrucciones.

El enlazador no hace los dos primeros elementos.
@IgnacioVazquez-Abrams ¿Ese sería el trabajo del ensamblador?
No. No es trabajo de nadie. Las directivas del ensamblador no asignan memoria, y no es necesario que la memoria sea contigua independientemente.
@ IgnacioVazquez-Abrams ¿Qué quiere decir con "las directivas del ensamblador no asignan memoria"? Pensé que todo el punto del código anterior era asignar memoria. En segundo lugar, me enseñaron que la memoria se asigna de forma contigua.
Eso no es del todo exacto. Esas directivas establecen que los bytes arbitrarios deben colocarse en las ubicaciones de memoria actuales y siguientes; la "asignación" ocurre porque se han agregado más bytes al ensamblado, no porque se estén usando esas directivas.
En cuanto al tema de "contiguo", mientras que cada directiva especifica un bloque de memoria contiguo, no es necesario que la memoria sea contigua sobre todas las directivas.

Respuestas (2)

Esto ES asignar la memoria, y no tiene nada que ver con el conjunto de instrucciones. Los ensambladores son increíblemente simples: las líneas en el archivo de ensamblaje corresponden casi exactamente al binario de salida, se realiza muy poca reorganización. La línea ".long 0x0" solo significa 'dame cuatro bytes aquí y cárgalos con el valor 0x0'. Los datos se 'asignan' de la misma manera que las instrucciones. Una línea 'MOV R12, R11' simplemente significa 'dame cuatro bytes aquí y cárguelos con la codificación binaria para MOV R12, R11'. Los datos son contiguos por la misma razón por la que sus instrucciones son contiguas: las escribió en líneas contiguas en el archivo ensamblador. El "va:" simplemente significa 'llamar a la ubicación de estos cuatro bytes "va"'. Esto solo se usa dentro del ensamblador. Dondequiera que hagas referencia a 'va' en el código, el ensamblador insertará la dirección de los cuatro bytes de datos a los que se refiere 'va', que es solo un número. Tenga en cuenta que esto no lo puede hacer el ensamblador, sino el enlazador. Sin embargo, la cadena 'va' nunca aparecerá en el binario de salida.

Básicamente, el ensamblaje es casi una representación directa del contenido de la memoria. Las sucesivas líneas de montaje terminarán en direcciones sucesivas. La única excepción es cuando cambias de sección (.section). Cualquier dato ubicado explícitamente en el código será contiguo si es contiguo en el archivo de ensamblado. Ahora, las secciones joden un poco con esto. Es posible que todo .data termine en una parte de la memoria y todo .text termine en otra parte. Sin embargo, los bloques no se dividirán; si son contiguos en el archivo de ensamblaje, serán contiguos en la salida.

Datos como este no se "asignan" de la misma manera.

Lo que sucede es que, cuando ejecutas un programa, ese programa se carga en la memoria. Si ese programa contiene 0x000000001122334455667788 en alguna parte, entonces esas ubicaciones de memoria (12 en total a menos que haya contado mal) contendrán esos valores. Cuando compila su código, todos los NOMBRES se traducen en direcciones de memoria. A partir de ese momento, no se ejecuta ninguna instrucción para que esto suceda: la memoria está allí, está "asignada" (se asigna suficiente memoria para contener todo el programa, variables estáticas como esta y todas), y debido a que todo el programa se coloca en esa memoria se inicializan las variables.

Luego, cuando diga "cargue la variable va en el registro 'X'", el código compilado (que dice "cargue la dirección 0x84573412 en el registro 'X'") obtendrá el bit de datos correcto.

Los nombres de las variables solo están ahí para su conveniencia; de lo contrario, tendría que asignar direcciones específicas usted mismo.