PDF de programación - Práctica 2 Paso de lenguaje de alto nivel a ensamblador

Imágen de pdf Práctica 2 Paso de lenguaje de alto nivel a ensamblador

Práctica 2 Paso de lenguaje de alto nivel a ensambladorgráfica de visualizaciones

Publicado el 5 de Diciembre del 2018
587 visualizaciones desde el 5 de Diciembre del 2018
403,3 KB
23 paginas
Creado hace 15a (09/03/2009)
Práctica 2

Paso de lenguaje de alto nivel a

ensamblador

2

2.1. Objetivos

En la práctica anterior hemos estudiado los conceptos básicos de la arquitectura ARM y
de su programación en lenguaje ensamblador. En esta práctica profundizaremos en nuestros
conocimientos sobre la programación en ensamblador analizando su interacción con un
lenguaje de alto nivel como C. Los principales objetivos son:

Conocer el convenio de paso de parámetros a funciones.

Comprender los distintos ámbitos de variables, local y global.

Comprender los tipos estructurados propios de los lenguajes de alto nivel.

Comprender el código generado por el compilador gcc.

2.2. La Pila de llamadas

Como hemos visto en la práctica anterior, el mapa de memoria de un proceso se divide
en secciones de distinto propósito, generalmente, código (text), datos con valor inicial (data)
y datos sin valor inicial (bss). El resto de la memoria puede utilizarse de distintas maneras.
Una zona de memoria de especial importancia es la denominada pila de llamadas (call
stack o simplemente stack ).

Esta región de memoria, cuyos accesos siguen una política LIFO (Last-In-First-Out,
sirve para almacenar información relativa a las rutinas activas del programa. Por ejemplo
si en un programa, una rutina FunA invoca a una rutina FunB, cuando FunB comience su
ejecución, habrá al menos dos rutinas activas y la pila mantendrá la información de ambas.
La gestión de tipo LIFO se lleva a cabo mediante un puntero al último elemento (cima
de la pila) que recibe el nombre de stack pointer (SP) y habitualmente es almacenado en
un registro arquitectónico. En el caso de ARM se suele emplear el registro R13 para este
propósito.

La pila suele organizase en sub-regiones denominadas marcos de activación o simple-
mente marcos de pila. Cada uno de estos marcos contiene la información de una rutina
activa y su contenido depende tanto de la arquitectura del procesador como del tipo de
código que se desee generar. Por ello, para poder combinar códigos compilados por sepa-
rado, es necesario recurrir a estándares o convenios. El marco de una rutina generalmente
contiene información tanto del estado de ejecución de la rutina (parámetros de la llamada
y las variables locales, esencialmente) como información necesaria para restaurar el estado
de la rutina que la invocó.

Para facilitar el acceso a la información contenida en el marco, es habitual utilizar un
puntero adicional denominado frame pointer (FP) que apunta a una posición preestablecida
del mismo, por ejemplo a aquella en la que se almacena la dirección de retorno de la rutina.
Habitualmente los parámetros quedan almacenados en direcciones superiores a la apuntada
por FP y las variables locales de la rutina, en direcciones inferiores al FP. Es también
habitual que los compiladores hagan uso del FP para direccionar tanto los parámetros
como las variables locales de la rutina. Siguiendo el ejemplo anterior, si la rutina FunA
invoca a la rutina FunB, la estructura de la pila sería similar a la descrita en la figura 2.1.

2.3. ESTÁNDAR DE LLAMADAS A PROCEDIMIENTOS PARA ARM

3

Figura 2.1: Estructura de la pila cuando la rutina funA ha invocado a la rutina funB.

2.3. Estándar de llamadas a procedimientos para ARM

En la práctica anterior hemos utilizado una rutina muy sencilla para realizar una pe-
queña tarea, pasando sus argumentos a través de registros. Si queremos poder ensamblar
esta rutina de forma que otros puedan utilizarla en sus programas a partir del fichero obje-
to, debemos indicar cómo han de que pasarse los argumentos a la rutina. Lo mismo sucede
si queremos invocar la rutina desde un código C, aunque este sea propio. El compilador
debe saber cómo pasar los parámetros para traducir correctamente la llamada a la rutina.

Si cada rutina de cada desarrollador se comporta de forma diferente es imposible com-
binar los distintos códigos. Es por lo tanto necesario un estándar que homogeneice su com-
portamiento y garantice la interacción entre ellos. El ATPCS (ARM-Thumb Procedure
Call Standard) es el estándar que regula las llamadas de procedimientos en la arquitectura
ARM [atp]. Especifica una serie de normas para que las rutinas puedan ser compiladas
y ensambladas por separado, y que a pesar de ello, puedan interactuar entre ellas. En
definitiva, supone un contrato entre la rutina que invoca y la rutina invocada que define:

Obligación para la rutina que invoca de crear un estado de memoria a partir del cual
la rutina invocada pueda comenzar su ejecución (ej. paso de parámetros).

Obligación para la rutina invocada de preservar, a lo largo de su ejecución, una parte
del estado de memoria de la rutina que la invocó.

Derechos de la rutina invocada a modificar parte del estado de memoria de la rutina
que la invocó (ej. retorno de resultados).

El estándar define una serie de variantes que responden a distintas prioridades para la

generación de código:

4

Tamaño de código.

Rendimiento del programa.

Funcionalidad (por ejemplo facilidad de depuración, comprobaciones en tiempo de
ejecución o soporte para bibliotecas de enlace dinámico).

Sin embargo, nosotros analizaremos exclusivamente el estándar básico. Para ampliar la
información sobre las diversas variantes es preciso consultar el documento de referencia de
ATPCS [atp].

2.3.1. Modelo de memoria

El estándar está diseñado para programas compuestos de un solo hilo de ejecución
o proceso (en nuestro contexto, consideraremos ambos términos intercambiables). Cada
hilo, o proceso, tiene un estado de memoria definido por el contenido de los registros
arquitectónicos y el contenido de la memoria que puede direccionar, que puede ser de los
siguientes tipos:

Memoria de sólo lectura.

Memoria de lectura y escritura asignada estáticamente (i.e. antes de ejecución).

Memoria de lectura y escritura asignada dinámicamente (i.e. durante ejecución).

Pila de llamadas.

La memoria que un proceso puede direccionar/acceder puede variar a lo largo de su
ejecución. No obstante, la pila de llamadas siempre estará presente. Esta zona de memoria
se distingue de las demás zonas de lectura y escritura por su importancia y especificidad.

Según el estándar ATPCS la pila debe ser de tipo Full Descending, lo que quiere de-
cir que el puntero de pila apunta a la última posición ocupada de la pila, y que la pila
crece hacia direcciones menos significativas, tal y como ilustrada la figura 2.2. La pila
es una zona contigua de memoria dentro de la región comprendida entre la base (sta-
ck base) y el límite (stack limit). La zona ocupada de la pila está comprendida en el
intervalo [stack pointer , stack base], mientras que la parte libre se define por el intervalo
[stack limit , stack pointer ). Es preciso aclarar, que no es estrictamente necesario que la pila
ocupe la misma región de memoria en todo instante, y, que los valores de stack base y stack
limit no tienen por qué están disponibles para el propio proceso.

En caso de haber varios procesos en ejecución, el estándar establece que un proceso no
puede modificar la memoria de lectura/escritura de otro proceso ni la parte ocupada de su
pila. Sin embargo, permite que la parte libre de la pila pueda ser escrita inesperadamente,
previsiblemente debido a una rutina de tratamiento de excepciones.

2.3.2. Registros

La Tabla 2.1 muestra los registros visibles en modo usuario y describe su uso habitual

definido por el estándar ATPCS.

2.3. ESTÁNDAR DE LLAMADAS A PROCEDIMIENTOS PARA ARM

5

Figura 2.2: Ilustración de una pila Full Descending.

Los registros r0-r3 se utilizan para pasar parámetros a la rutina, para recoger el valor
devuelto por está y para almacenar resultados temporales durante su ejecución. El registro
r12, también llamado IP, se utiliza también para almacenar resultados temporales. Los
registros r4-r11 se utilizan típicamente para almacenar el valor de variables locales de la
rutina, por lo que también reciben los nombres v1-v8. Los registros r12-r15 juegan un
papel especial, por el que reciben su nombre alternativo: IP, SP, LR y PC respectivamente.
En algunas variantes del ATPCS los registros r9 y r10 también ejercen roles especiales,
recibiendo en estos casos los nombres de SB y SL respectivamente. En el estándar básico,
las rutinas deben preservar los valores de los registros r4-r11 y r13 (SP), pero no tienen
obligación de preservar los de los registros r0-r3, r12 (IP) y r14 (LR).

Aunque también existen registros de punto flotante, por el momento los ignoraremos.
Para más información sobre ellos es preciso consultar el documento de referencia del es-
tándar [atp, arm].

2.3.3. Llamada a subrutina

La llamada a una rutina puede hacerse con cualquier secuencia de instrucciones que
lleve al registro LR (r14) la dirección de retorno y al PC (r15) la dirección de comienzo de
la rutina. Las dos principales alternativas son1:

Convencional Utilizando la instrucción BL que permite realizar un salto relativo al PC:

BL FUNC

@ La dirección se traduce en ensamblado por FUNC - (PC + 8)
@ BL guarda en LR el valor PC - 4

1Es preciso recordar que, debido a la segmentación, cuando una instrucción lee el registro PC, este

contiene la dirección de la propia instrucción incrementada en 8 bytes (i.e. dos inst.).

6

Tabla 2.1: Descripción del uso de los registros arquitectónicos según el estándar ATPCS.
Registro Sinónimo Especial Descripción

r0
r1
r2
r3
r4
r5
r6
r7
r8
r9

r10
r11

r12

r13
r14

r15

a1
a2
a3
a4
v1
v2
v3
v4
v5
v6

v7
v8

Argumento 1/Resultado/Scratch
Argumento 2/Resultado/Scratch
Argumento 3/Resultado/Scratch
Argumento 4/Resultado/Scratch
Variable 1.
Variable 2.
Variable 3.
Variable 4.
Variable 5.
Variable 6. Puntero base utilizado con bibliote-
cas dinámicas.
Variable 7. Puntero límite de pila
Variable 8. Puntero marco de pila (Frame Poin-
ter ).
Registro auxiliar utilizado en las llamadas a su-
brutina (Intra-Procedure scratch).
Puntero de pila (Stack Pointer ).
Registro de enlace (Link Register ) utilizado para
almacenar la dirección de r
  • Links de descarga
http://lwp-l.com/pdf14422

Comentarios de: Práctica 2 Paso de lenguaje de alto nivel a ensamblador (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad