Вы находитесь на странице: 1из 15

2.

2 Subrutinas
2.2.1 Introduccin
Como ya se ha explicado a lo largo de los captulos anteriores, las instrucciones se guardan en posiciones
consecutivas de memoria y se ejecutan en ese orden secuencial. Sin embargo, si se quiere modificar dicho
orden, se debe alterar el flujo mediante instrucciones de ruptura de secuencia o instrucciones de salto. Como
se puede observar en la Figura 2.2., en funci!n de si el "C retoma el valor de la siguiente instrucci!n a la
de salto o no, la ruptura de la secuencia puede ser sin retorno #saltos condicionales o incondicionales$ o con
retorno. %as instrucciones de salto utili&adas has ahora han sido saltos sin retornos ' b, beq ...' puesto
que el programa no vuelve al punto en el que se ha producido el salto. Sin embargo, cuando se ejecutan
saltos con retorno ' bl, bleq, call ... ', despu(s de ejecutar una serie de instrucciones, el
programa recupera el flujo de ejecuci!n original #para ello se ha guardado la direcci!n de la siguiente
instrucci!n a la instrucci!n de salto$. )l objetivo de este capitulo es estudiar saltos con retorno, o lo que es
lo mismo, las subrutinas.

tiempo
"C
"C "C
secuenciamiento continuo saltos sin retorno saltos con retorno
subrutinas
tiempo tiempo
salto
salto
retorno
retorno
salto
salto
salto
Figura 2.2.1. Saltos sin retorno y con retorno.
)l lenguaje m*quina se hace eco del uso por parte de los lenguajes de alto nivel de funciones y
procedimientos, incluyendo el concepto de subrutina. +na subrutina es un conjunto de instrucciones de
lenguaje m*quina que reali&a una tarea especfica y que puede ser activada #llamada para su ejecuci!n$
desde cualquier punto de un programa o subrutina o desde la propia subrutina. Se habla as de activaci!n
externa #cuando es activada desde el programa principal o desde otra subrutina$ y de activaci!n interna
#cuando se activa desde la propia subrutina$.
%a utili&aci!n de subrutinas implica una serie de ventajas e inconvenientes. ,entro de las ventajas podemos
destacar-
)l c!digo del programa ocupa menos espacio en memoria si la subrutina se activa desde
diferentes puntos de dicho programa, ya que s!lo se almacena una ve&. %as subrutinas
tienen asociado el concepto de reutili&aci!n de c!digo.
)l c!digo del programa est* m*s estructurado. )sto supone facilidad de puesta a punto y
depuraci!n, facilidad de modificaci!n, posibilidad de utili&ar libreras, etc.
"ero el uso de subrutinas tambi(n supone algunas desventajas-
.umenta el tiempo de ejecuci!n de los programas, debido a las instrucciones de llamada
y retorno de subrutina, y al paso de informaci!n entre el programa que llama y la
subrutina #paso de par*metros/devoluci!n de resultados$.
/0
Estructura de Computadores
.umenta la complejidad del procesador, ya que se ha de a1adir hard2are especial para que la
gesti!n de subrutinas sea eficiente.
%o cierto es que cualquier ayuda que pueda ofrecer el procesador para la gesti!n de subrutinas ser*
importante- se ha estimado que las llamadas y retornos de subrutinas constituyen entre un 3 y un 45 de las
instrucciones que ejecuta un procesador, porcentaje nada despreciable.
2.2.2 Clasificacin de las subrutinas
"or su forma de activacin se pueden clasificar en-
Uninivel- dentro de la subrutina no se activan otras. +n ejemplo de dos activaciones consecutivas de
una misma subrutina se puede ver en la Figura 2.2.2, en la que los n6meros representan el orden en
que se va ejecutando el c!digo en el tiempo.
Multinivel- dentro de la subrutina se activan otras #Figura 2.2.3$.
Recursivas- la subrutina se llama a s misma #Figura 2.2.7$, bien de forma directa o indirecta.
Programa principal Subrutina SUB1

0
8
call SUB1
3
7
2
9
:
;
ret
call SUB1
Figura 2.2.2. Subrutina uninivel.
7

call SUB1
8
Programa principal Subrutina SUB1
Subrutina SUB2

0
9
2
: ;
ret
3
ret
call SUB2
Figura 2.2.3. Subrutina multinivel.
,esde el punto de vista de su utilizacin se distinguen-
Reentrantes- subrutinas que pueden ser llamadas por diversos programas a la ve& sin necesidad de
que las ejecuciones previas hayan terminado. )stas subrutinas son muy 6tiles en sistemas
multiprogramados como rutinas del sistema operativo, compiladores, etc. "ara que esto pueda ser as
se ha de cumplir- #a$ la subrutina no ha de contener c!digo automodificable #aunque esta opci!n
apenas se utili&a actualmente$ y #b$ toda la informaci!n asociada a las diferentes llamadas ha de estar
almacenada en lugares diferentes.
2/0
Estructura de Computadores
No reentrantes- no tienen las restricciones de las anteriores, ya que no van a volver a ser activadas hasta que
no haya terminado la ejecuci!n de la activaci!n anterior.
call SUB1
Programa principal Subrutina SUB1

0
:
2
3
7
4
ret
8 ;
salto condicional
call SUB1 9
Figura 2.2.4. Subrutina recursiva.
2.2.3 Anlisis de la ejecucin de una subrutina
"ara ejecutar una subrutina hay que reali&ar diversas acciones o pasos como son- pasar los par*metros con
los que va a trabajar la subrutina, llamarla para que realice el c*lculo asociado y retornar al programa que la
ha llamado, tomando los resultados calculados por ella. <abitualmente, toda la informaci!n asociada a la
ejecuci!n de una subrutina se recopila en una estructura de datos que se llama bloque de activacin de la
subrutina. =remos construyendo dicho bloque de activaci!n seg6n las necesidades que vayan surgiendo al
anali&ar la ejecuci!n de una subrutina.
>eamos ahora los pasos a seguir para la ejecuci!n de una subrutina de una manera m*s detallada, utili&ando
como ejemplo el ensamblador .?@.
2.2.3.1 Llamada y retorno
Se necesita una instrucci!n de llamada a subrutina que guarde la direcci!n de retorno #Aretorno$ o direcci!n
de la siguiente instrucci!n a la de llamada #en el caso de la m*quina .?@, PC_llamada+4$ y rompa la
secuencia de ejecuci!n #PC:=@subrutina, esto es, PC:=PC+desp_subrutina$. )sta instrucci!n
puede tomar diferentes nombres dependiendo del lenguaje ensamblador. ,e forma general utili&aremos
CALL nom_subrutina..
Bambi(n se necesita otra instrucci!n que al final de la ejecuci!n de la subrutina recupere la ejecuci!n del
programa llamador moviendo al registro "C la direcci!n de retorno guardada por la instrucci!n call,
PC:=@retorno. )sta instrucci!n suele ser la instrucci!n ret.
)n el lenguaje ensamblador .?@ no existe la instrucci!n ret, y por lo tanto, al final de una rutina se debe
cargar directamente la direcci!n de retorno en el registro "C.

4
7
;
2
9
24
call SUB1
ret
"rograma principal Subrutina S+C
4 D 7 D ; D 2 D 100 10 ! 10" ! 11# ! 11$ ! 1#0 D 9 D 24
%ontenido del P%
SUB1 "r. prin.
44
47
4;
2
9
24
"r. prin.
Figura 2.2.5. Llamada a subrutina.
3/0
Estructura de Computadores
,e esta manera se rompe el flujo secuencial de ejecuci!n #valores que va tomando el registro "C$, como se
muestra en la Figura 2.2.0, suponiendo que una instrucci!n ocupa cuatro posiciones de memoria #como en el
procesador .?@$.
"ara que tras la ejecuci!n de la subrutina se pueda retornar al programa que la ha llamado #el cambio de
valor del "C de 24 a 9 en el ejemplo$ es necesario guardar en alg6n sitio la direcci!n de retorno. "ara ello,
existen distintas alternativas-
a. En una posicin fija de memoria o en un mismo registro para todas las subrutinas.
,e esta manera, cuando un programa llama a una subrutina, no tiene m*s que guardar la direcci!n de retorno
en un registro o en una posici!n de memoria y tomarla de ah cuando termine la ejecuci!n de dicha
subrutina. ,ichas acciones las llevar*n a cabo las instrucciones call y ret de la m*quina indicada #Figura
2.2.9$.
Si se utili&a un registro el proceso ser* m*s r*pido que si es en memoria #por ejemplo, el =C@ 394 utili&a el
registro r7$. @uchas m*quinas actuales #@="S, "o2er"C,$ utili&an esta t(cnica mediante la instrucci!n
Eump .nd %inF, que permite saltar a una subrutina almacenando la direcci!n de retorno en un registroG por
ejemplo, la familia de procesadores @="S utili&a la instrucci!n E.% Asubrutina, que utili&a el registro r3.
)l procesador .?@ tambi(n utili&a una instrucci!n de este tipo para la llamada a subrutinas, concretamente
la instrucci!n se llama Cranch and %inF #C%$. )sta instrucci!n guarda en el registro r14 #que se conoce con
el nombre link register o lr$ la direcci!n de retorno.
.unque esta soluci!n no es general, como veremos a continuaci!n, es de ejecuci!n r*pida, por lo que se
utili&a en aquellos casos en los que no plantea problemas.

4
7
;
2
9
24
call SUB1
ret
"rograma principal
Subrutina SUB1
r1
9
call- r7 -H "C I 7
ret- "C -H r7
44
47
4;
2
9
24
4 D 7 D ; D 2 D 100 ! 10 ! 10" ! 11# ! 11$ ! 1#0 D 9 D24
%ontenido del P%
SUB1 "r. prin. "r. prin.
Figura 2.2.6. Gestin de la direccin de retorno en el IBM 3!.

4
7
;
2
9
24
call SUB1
"rograma principal
r1
9
call- r7 -H "C I 7
ret- "C -H r7
ret
Subrutina SUB2
ret
Subrutina SUB1
call SUB2
9
r1
44
47
4;
2
9
24
244
247
24;
22
29
224
Figura 2.2.7. "roblema #ue se presenta con la solucin a$ para subrutinas multinivel
)l problema de esta t(cnica es que si la subrutina llama a otras o a s misma se perdera la direcci!n de
retorno, ya que se reescribira el valor del registro #r7 en el ejemplo$ con el nuevo valor de retorno. )n la
Figura 2.2.: se puede observar c!mo se pierde la A9 de retorno al programa principal por el valor de
A9. Si se desea tener subrutinas multinivel guardando la direcci!n de retorno en un registro, antes de
llamar a otra subrutina se debe salvar en alg6n sitio #por ejemplo, en la memoria o en un registro$ la
direcci!n de retorno y restaurarla al volver #soluci!n soft2are$. "or ejemplo, en el =C@394 se hara como
indica la Figura 2.2.;.
7/0
Estructura de Computadores












call SUB1
"rograma principal Subrutina S+C Subrutina S+C2






















ret ret
call SUB2
salvar
r7
restaurar
r7
Figura 2.2.8. Gestin de subrutina multinivel en el IBM 3!.
b. En una posicin fija de memoria o registro! diferente para cada subrutina.
Cada subrutina utili&a una posici!n fija de memoria o un registro fijo donde se guarda la direcci!n de retorno
del programa o subrutina que la llam!. "or ejemplo, en el <" 244 se guarda la direcci!n de retorno en la
primera posici!n de la subrutina y a continuaci!n viene el c!digo. )n la Figura 2.2.8, se puede ver un
ejemplo de llamada multinivel con este mecanismo. )l ","D especificaba directamente en la llamada a la
subrutina el registro donde guardar la direcci!n de retorno.

4
7
;
2
9
24
call SUB1
ret
"rograma principal
Subrutina SUB1
ret
Subrutina SUB2
call SUB2
1$ 11$ 44
47
4;
2
9
24
244
247
24;
22
29
224
9 9
Figura 2.2.". Gestin de subrutina multinivel guardando la direccin de retorno al comien%o de cada
subrutina.
)ste m(todo soporta subrutinas uninivel y multinivel, pero no recursivas, ya que con esta soluci!n se pierde
la direcci!n de retorno #A9 en el ejemplo$ tras cada llamada recursiva #Figura 2.2.4$. Si se quiere
recursividad, se necesitar*, por ejemplo, construir una pila.

4
7
;
2
9
24
call SUB1
ret
"rograma principal Subrutina SUB1
call SUB1
1$ 11$
bne
44
47
4;
2
9
24
P%&
SUB1
1

"r. prin. "r. prin.
4 D 7 D ; D 2 D 10 ! 10" ! 11# ! & 11$ &1#0 D ' '!( & '!) & '' & '*! &
SUB1
2
SUB1
1

@J44K -H 9 @J44K -H 9
Figura 2.2.1#. "roblema en la gestin de la recursividad mediante la solucin b$.
0/0
Estructura de Computadores
c. En la pila.
+na pila es una estructura para almacenar datos. %a pila se guarda en memoria y se gestiona en modo %=FL
#Last In +irst ,ut$- el 6ltimo dato almacenado en la pila es el primero en salir. "ara leer o escribir en la pila
se utili&a un puntero especial, S" #puntero de pila, Stack "ointer$ y tambi(n instrucciones especiales- push y
pop.
)n este m(todo se utili&a una pila para almacenar las direcciones de retorno. ,e esta forma, se da soporte
directamente a subrutinas uninivel, multinivel y recursivas #Figura 2.2.$, puesto que las direcciones de
retorno se ir*n guardando en la pila una encima de la otra sin perder ninguna informaci!n. )l puntero S"
indicar* donde guardar esas direcciones de retorno en la pila. )s el m(todo utili&ado por la mayora de los
procesadores.

4
7
;
2
9
24
call SUB1
"rograma principal
ret
Subrutina SUB2
ret
Subrutina SUB1
call SUB2
44
47
4;
2
9
24
244
247
24;
22
29
224
call SUB2
bne
29
9
9
"=%.
S"
Figura 2.2.11. -lmacenamiento de la direccin de retorno en la pila.
=gual que la mayora de los procesadores, el procesador .?@ utili&a la pila para almacenar direcciones de
retorno. Sin embargo, como se ha indicado anteriormente, en el ensamblador del .?@ se utili&a la
instrucci!n bl para llamar a subrutinas y la instrucci!n bl guarda la direcci!n de retorno en el registro lr.
bl$ instruccin para llamar una subrutina%
bl nombre_sub lr = PC + 4 @ la direcci!n de retorno se guarda en el registro lr
PC := @nombre_sub @ se carga en el "C la direcci!n de la subrutina
Como en el ensamblador del .?@ tampoco hay una instrucci!n como ret, cuando finali&a la ejecuci!n de
una subrutina se debe recuperar la direcci!n de retorno de la pila y guardarla en el PC.
"ara solucionar el problema de las subrutinas multinivel y recursivas, al comien&o de la ejecuci!n de una
subrutina se guarda el valor del registro lr en pila y se recupera su valor de la pila cuando finali&a la
ejecuci!n de la subrutina.
Como se puede observar en la Figura 2.2.2 al comien&o del programa principal tambi(n se guarda el
contenido del registro lr en la pila. "ara que al finali&ar la ejecuci!n del programa principal se pueda
devolver el control al sistema se debe cargar la direcci!n de retorno en el "C. )sa direcci!n de retorno,
tambi(n en este caso, est* en el registro lr por lo que si no se almacena en la pila y el programa principal
hace una llamada a una subrutina, la llamada a la subrutina har* que se pierda el valor del registro lr . "or lo
tanto el programa principal tambi(n guarda al principio el valor del registro lr en la pila y lo recupera al
final.
9/0
Estructura de Computadores


29
9
9
A sis
4
7
;
2
9
24
bl SUB1

"rograma principal Subrutina SUB2
pop {pc}
Subrutina SUB1
bl SUB2
44
47
4;
2
9
24
244
247
24;
22
29
224
bl SUB2
bne
"=%.
S"
I
D
push {lr} push {lr}
pop {pc}
lr = 16 lr = 116 lr = 216
push {lr}
pop {pc}
Figura 2.2.12. La direccin de retorno #ue se encuentra en el registro lr se guarda en la pila en las
m.#uinas -/M.
Como se puede ver en la figura 2.2.2 se utili&a la instrucci!n push para introducir elementos en la pila y
la instrucci!n pop para recuperar e eliminar valores de la pila.
pus& 'rn(% guarda el contenido del registro rn en la cima de la pila. "ara ello, previamente actuali&a el valor
de S" #en este caso, restando 7 ya que la pila crece hacia direcciones m*s bajas de memoria y cada elemento
ocupa 7 posiciones$ para hacer sitio en la pila al dato que se va a cargar. . continuaci!n, guarda el contenido
del registro rn en el lugar indicado por el nuevo valor de S" #en la cima de la pila$.
push {rn} sp = sp - 4;
M[sp]= rn;
pop 'rn(- almacena el valor que est* en la cima de la pila en lel registro rn. . continuaci!n actuali&a el
puntero S" para apuntar a la nueva cima de la pila, ya que se ha eliminado un dato de la pila.
pop {rn} r1 = M[sp];
sp = sp + 4;
Banto la instrucci!n push como la instrucci!n pop pueden escribir/leer en pila m*s de un elemento en cada
instrucci!n-
push {r1,r2...rn} sp = sp - 4;
M[sp]= rn;
.....
sp = sp 4;
M[sp] = r1;
pop {r1,r2...rn} r1 = M[sp];
sp = sp + 4;
.....
rn = M[sp];
sp = sp + 4;
)stas mismas operaciones se pueden llevar a cabo con otras dos instrucciones en el ensamblador del .?@.
)l procesador .?@ dispone de dos instrucciones tipo load/store que reali&an multiples lecturas o escrituras
en memoria que resultan 6tiles para reali&ar operaciones sobre la pila. )stas instrucciones se llaman ldm y
stm y su formato es el siguiente-
<operacion>{cond}<modo> Rn{!}, <Rlist>
)l campo <modo> controla como se actuali&a el registro Rn y proporciona distintas opciones
dependiendo de si se est* accediendo a la pila o a otra &ona de memoria-
a.D cuando se accede a cualquier &ona de memoria-
<operacion>ia incrementar despu(s
<operacion>ib incrementar antes
:/0
Estructura de Computadores
<operacion>da decrementar despu(s
<operacion>db decrementar antes
b.D especificos para la pila-
MoperacionNfd incrementar despu(s
MoperacionNed incrementar antes
MoperacionNfa decrementar despu(s
MoperacionNea decrementar antes
)n este caso la a indica que la pila es ascendente, la d que es descendente, la f #0ull$ que S" apunta al
6ltimo elemento introducido en la pila y e #empty$ que S" apunta a la primera posici!n libre de la pila #la
siguiente posici!n al 6ltimo elemento introducido en la pila$.
"or otra parte, si se utili&a la opci!n OPQ, la 6ltima direcci!n se escribe en el registro ?n. Considera los
siguientes ejemplos-
ldmia sp!, {r1, r2} ldmfd sp!, {r1, r2}
r1 = M[sp];
r2 = M[sp +4];
sp = sp + 8; @ debido a !
)stas instrucciones y la instrucci!n pop {r1,r2} son equivalentes.
stmdb sp!, {r1, r2} stmfd sp!, {r1, r2}
M[sp-4] = r1;
M[sp-8] = r2;
sp = sp - 8; @ debido a !
)stas instrucciones y la instrucci!n push {r1,r2} son equivalentes.
Si no se indica el modo en el nombre de la instrucci!n #instrucciones ldm y stm$ la opci!n que se utili&a por
defecto es ia.
)l registro utili&ado para guardar el S" en el .?@ es r13.
2.2.3.2 Paso de parmetros y devolucin de resultados
Como ya se ha comentado, los par*metros son datos que necesita la subrutina para su ejecuci!n. )sta
informaci!n, as como el resultado que devuelve la subrutina, se puede pasar de dos formas-
una copia del dato #el dato original no se puede modificar$ paso por )alor
la direcci!n del dato #el dato original s se puede modificar$ paso por referencia.
"or ejemplo, en el lenguaje de programaci!n .,., los par*metros pasados como in se corresponden con los
par*metros pasados por valor, mientras que los par*metros pasados como in out u out se corresponden con
los par*metros por referencia. Bambi(n se pasan por referencia estructuras de datos como vectores o
matrices, ya que resulta m*s eficiente que hacer una copia de los mismos en la pila. Si programanos en C y
queremos pasar un par*metro por referencia debemos pasar directamente la direcci!n de ese par*metro o
variable.
)l programa que llama colocar* los par*metros en lugares a los que pueda acceder la subrutina, de la misma
manera que la subrutina devolver* el resultado en lugares a los que pueda acceder el programa que la llam!.
Siguiendo el an*lisis reali&ado en el apartado anterior, existen las mismas tres posibilidades- #a$ una &ona fija
de memoria o registro para todas las subrutinas, #b$ una &ona fija de memoria o registro para cada subrutina,
o #c$ a trav(s de la pila.
;/0
Estructura de Computadores
"=%.
S" (retorno
par*metros
...
Figura 2.2.13. Blo#ue de activacin1 direccin de retorno y par.metros.
"or las ra&ones ya expuestas en el apartado anterior, toda la informaci!n asociada a la ejecuci!n de una
subrutina se va a situar en la pila formando una estructura denominada bloque de activacin, lo que permite
multinivel y recursividad. )n base a los pasos anali&ados hasta ahora en la ejecuci!n de una subrutina, el
bloque de activaci!n tendra la estructura de la Figura 2.2.3.
"ara acceder a los elementos de la pila se utili&a direccionamiento relativo al puntero de pila S".
Bras la ejecuci!n de la subrutina el programa llamador eliminar* los par*metros de la pila, aunque existen
otras alternativas, como, por ejemplo, que la propia instrucci!n de retorno se encargue de hacerlo #en el
i;4;9, ?)B n$.
%as m*quinas .?@ sigue la primera alternativa mediante la instrucci!n
add sp,sp,#num_param x 4 #suponiendo que los par*metros son de palabra o 7 bytes$.
Ejemplo 2.2.1
)n este ejemplo se reali&a una llamada a subrutina S+C desde el programa principal pas*ndole dos
par*metros, uno por valor y el otro por referencia.
void SUB (int i, int *j)
{
(*j)= i*i;
}
void main ()
{
int a=3;
int b=0;
SUB(a, &b);
}
.code 32
.global main, __cpsr_mask
main:
push {lr} @ guarda la dir. de retorno en la pila
ldr r1, a
adr r0, b @ obtine la dir. en memoria de b
push {r0,r1} @ empila los parmetros
bl SUB
add sp, sp, #8 @ elimina 2 parmetros de la pila
pop {pc} @ guarda dir. de retorno en PC}
a: .word 3
b: .word 0
SUB:
push {lr}
ldr r3, [sp, #8]
mul r5,r3,r3
ldr r6, [sp,#4]
str r5, [r6]
pop {pc}
8/0

PILA



lr - main sp
Rb - j sp I 7
a - i #3$ sp I ;
lr-sistema


"" variables
a. #3$
b #4$
...
Estructura de Computadores
,esde el programa principal se pasan dos par*metros a la subrutina S+C, a por valor y b por referencia.
"ara pasar b por referencia se necesita su direcci!n en memoria que se consigue con la instrucci!n adr
r0,b. "ara eliminar estos dos par*metros de la pila, despu(s de la ejecuci!n de S+C, se utili&a la instrucci!n
add sp, sp, #8 que elimina dos palabras de la pila.
)n la subrutina se utili&a direccionamiento relativo al S" para leer los par*metros de la pila. Como la pila
crece hacia direcciones m*s peque1as, se utili&an despla&amientos positivos respecto al S". "ara acceder al
par*metro pasado por referencia, hay que tener en cuenta que en la pila tenemos su direcci!n #@b$ y que por
lo tanto, debemos leer esa direcci!n de la pila para posteriormente escribir en esa direcci!n modificando la
variable original b.
)n el caso de que las subrutinas devuelvan alg6n resultado #concepto de funci!n en alto nivel$ el programa
llamador debe dejar espacio en la pila para devolver el valor de la funci!n #Figura 2.2.7$, justo antes de
empilar los par*metros. "ara ello se utili&ar* la instrucci!n sub sp, sp, #4 #suponiento que el resultado
es de una palabra o 7 bytes$. "osteriormente, tras eliminar los par*metros, el programa llamador podr* coger
el resultado devuelto en la pila mediante una instrucci!n pop {ri}.
"=%.
S" Aretorno
par*metros
esp. resultado
...
Figura 2.2.14. Blo#ue de activacin1 direccin de retorno2 par.metros y espacio para el resultado de la
0uncin.
Ejemplo 2.2.2
)ste ejemplo la subrutina S+C es una funci!n y por lo tanto deja el resultado en la pila.
int SUB (int i)
{
return (i*i);
}
void main ()
{
int a=3;
int result;
result=SUB(a);
}
.code 32
.global main, __cpsr_mask
main:
push {lr}
ldr r0, a
sub sp, sp, #4 @ dejar espacio para el resultado
push {r0} @ empilar parmetros
bl SUB
add sp, sp, #4 @ eliminar parmetros
pop {r0} @ recoger resultado
str r0, result
pop {pc}
a: .word 3
result: .word 0
4/0
PILA








lr - main sp
sp I 7 a- i #3$
sp I ; /esultado 34$
lr - sistema
...

Estructura de Computadores
SUB:
push {lr}
ldr r3, [sp, #4]
mul r5,r3,r3
str r5, [sp, #8] @ dejar resultado en el espacio reservado
pop {pc}
)n el programa principal, antes empilar los par*metros, deja espacio para el resultado en la pila
decrementando el S" (sub sp, sp, #4). %a subrutina dejar* en esa posici!n el resultado que calcula, y el
programa principal recoger* ese resultado #pop {r0}$ despu(s de eliminar los par*metros.
2.2.3.3 Salvar y restaurar el estado del programa que llama
)n los ejemplos 2.2. y 2.2.2 la subrutian S+C no utili&a los registros que ha utili&ado el programa principal
desde el que se reali&a la llamada #a excepci!n del registro lr$. ,e esta forma, no hay ning6n problema al
seguir con la ejecuci!n del programa principal, puesto que los registros que utili&a no han sigo modificados
en la subrutina a la que ha llamado. Sin embargo esta no es una buena soluci!n, ya que adem*s de tener que
conocer qu( registros no se deben usar en un subrutina, el n6mero de registros es limitado #por ejemplo,
pi(nsese en la cantidad de registros que no se podran utili&ar en una serie de llamadas recursivas$. "or ello
surge la necesidad de hacer transparente la ejecuci!n de la subrutina para el programa que la llama, es decir,
que la subrutina al terminar de ejecutarse debe dejar el estado de la m*quina #en particular, el estado de los
registros$ como estuvieran antes de su ejecuci!n. "ara ello se contemplan dos posibilidades-
+na ve& llamada, la propia subrutina, al comien&o de su ejecuci!n, guarda en la pila todos los
registros que ella utili&a y los restaura, con sus valores iniciales, justo antes de retornar el control al
programa llamador. ,e esta forma, a pesar de que la subrutina haya modificado alguno de los
registros del programa llamador, tras recuperar los valores iniciales, este 6ltimo los ve con su
contenido original. )sta t(cnica puede salvar registros que no contienen informaci!n relevante, ya
que el programa que llama a la subrutina no los utili&a.
.ntes de reali&ar la llamada a la subrutina, el programa llamador guarda los registros que (l utili&a y
restaura su valor justo tras finali&ar la ejecuci!n de la subrutina. )n este caso, la subrutina puede
utili&ar sin problemas cualquier registro de la m*quina, dejando la responsabilidad de transparencia
en la ejecuci!n al programa llamador. )n esta t(cnica puede ocurrir que la subrutina no utilice esos
registros, con lo que se est* salvando informaci!n que no corra riesgo de perderse.
)n nuestros programa utili&aremos la primera opci!n, con lo que el bloque de activaci!n quedara, por tanto,
como se muestra en la Figura 2.2.0.
"=%.
S"
registros
(retorno
par*metros
esp. resultado
...
Figura 2.2.15. Blo#ue de activacin1 espacio para el resultado de la 0uncin2 par.metros2 direccin de
retorno y estado del programa llamador.
/0
Estructura de Computadores
Ejemplo 2.2.3
El mismo programa #ue en el e5emplo *.*.* se implementa a6ora 6aciendo #ue la e5ecucin de la subrutina
sea transparente para el programa #ue reali%a la llamada..
.l comien&o de la ejecuci!n de la subrutina se guardan en la pila los valores de los registros a utili&ar por la
subrutina #r3 y r4$, y al final, se recuperan esos valores. ,e esta forma, se puede utili&ar cualquier
registro en la subrutina.
.code 32
.global main, __cpsr_mask
main:
push {lr}
ldr r0, a
sub sp, sp, #4
push {r0}
bl SUB
add sp, sp, #4
pop {r0}
str r0, resul
pop {pc}
a: .word 3
resul: .word 0
SUB:
push {r3,r4,lr}
ldr r3, [sp, #12]
mul r4,r3,r3
str r4, [sp, #16]
pop {r3,r4,pc}
2.2.3.4 Gestin del bloque de activacin
Si nos fijamos en el bloque de activaci!n del )jemplo 2.2.3, el valor del puntero S" depende del n6mero de
registros que se salven, as como del n6mero de variables locales y variables temporales que se guarden,
como se ver* en el siguiente apartado. )ste hecho dificulta el acceso a los elementos del bloque de activaci!n
mediante un acceso relativo a S". Como se puede ver en el ejemplo, el despla&amiento que debemos poner
para acceder a un mismo elemento del bloque de activaci!n depende del n6mero de registros que hayamos
salvado, por lo que si durante la programaci!n nos vemos obligados a salvar alg6n registro m*s deberemos
modificar todas las instrucciones que accedan a los par*metros.
"ara poder acceder a los elementos del bloque de activaci!n de manera independiente al valor del puntero
S", muchas m*quinas utili&an lo que se denomina )P #)rame Pointer$ o "untero al Cloque de .ctivaci!n.
)ste registro apunta a una posici!n fija del bloque de activaci!n durante toda la ejecuci!n de la subrutina, de
modo que ya no importa el valor que pueda tener el puntero S". )l puntero F" se puede activar por hard2are
o por soft2are en la primera instrucci!n de la subrutina y se mantiene fijo en esa posici!n hasta que se
reali&a el retorno. Bodos los accesos a la parte fija del bloque de activaci!n #espacio para el resultado y
par*metros$ se hacen a trav(s de F", utili&ando direccionamientos relativos a F".
)n algunos procesadores, el registro F" es un registro especfico de la m*quina #por ejemplo, el registro C"
en el i;4x;9$. )n el caso del procesador .?@, vamos a utili&ar el registro r11 como F". <ay que tener en
cuenta que el F" es un registro general de la m*quina que va a ser utili&ado por la subrutina y por tanto,
tendr* que ser salvado y restaurado por (sta, al igual que se hace con el resto de los registros para salvar el
estado del programa. Bras este punto, el bloque de activaci!n de una subrutina, queda como se muestra en la
Figura 2.2.9.
2/0
PILA



r3 sp
r7
lr - main
a- i #3$ sp I 2
/esultado 34$ sp I 9
lr - sistema
...


Estructura de Computadores
"=%.
S" #r3$ registros
F" anterior F" #r$
(retorno
par*metros
esp. resultado
...
)igura #*#*1$* Blo#ue de activacin salvando el +" anterior.
Ejemplo 2.2.4
Seguimos con el mismo programa de e5emplo. En esta implementacin se utili%a el puntero +" 3r''$ para
acceder a los par.metros de la pila.
.code 32
.global main, __cpsr_mask
main:
push {lr}
ldr r0, a
sub sp, sp, #4
push {r0}
bl SUB
add sp, sp, #4
pop {r0}
str r0, res
pop {pc}
a: .word 3
res: .word 0
SUB:
push {r11,lr} @ se empila el registro r11 antes de modificar su valor
mov r11, sp @ se copia el valor del sp en el registro r11
push {r3,r4}
ldr r3, [r11, #8] @ se utiliza r11 para acceder a la pila
mul r4,r3,r3
str r4, [r11, #12]
pop {r3,r4,r11,pc}
.l comien&o de la subrutina, antes de modificar su valor, se empila r11 junto con lr. ,espu(s, se copia el
valor del puntero S" en el registro r11. . partir de ese instante se utili&a direccionamiento relativo al
registro r11 para acceder a los elementos de la pila puesto que el valor de r11 no se modifica m*s durante
la ejecuci!n de la subrutina.
3/0
PILA


r3 sp
r7
r r #fp$
lr - main
sp I 9 a- i #3$ r I ;
sp I 24 /esultado 34$ r I 2
lr - sistema
...


Estructura de Computadores
Ejemplo 2.2.5
*rograma para cacular el factorial% la 0uncin +-C7 calcula de 0orma iterativa el 0actorial del n8mero #ue recibe
como par.metro.
int FACT (int i)
{
int b, k;
k = 1;
b = 1;
while (k<i)
{
k++;
b = b * k;
}
return (b);
}
void main ()
{
int n=3;
int res;
res = FACT(n);
printf (%d, res);
}
.code 32
.global main, __cpsr_mask
main:
push {lr}
sub sp, sp, #4
ldr r0, n
push {r0}
bl FACT
add sp, sp, #4
pop {r0}
str r0, res
pop {lr}
n: .word 3
res: .word 0
FACT:
push {r11,lr}
mov r11,sp
push {r3,r4,r5}
mov r3, #1
mov r4, #1
ldr r5, [r11, #8]
while: cmp r4, r5
bge fin
add r4,r4,#1
mul r3,r4,r3
b while
fin: str r3, [r11, #12]
pop {r3,r4,r5,r11,pc}
7/0
PILA/Bloque de activacin


r3 sp
r7
r0
r r
lr - main
n- i #3$ r I ;
/esultado 3$ r I 2
lr - sistema
...


Estructura de Computadores
Ejemplo 2.2.6
+ectores como par,metro% la 0uncin negativo devuelve el n8mero de elementos negativos e9istentes en el vector #ue
recibe como par.metro.
int NEGATIVO (int * vec; int numelem)
{
int i=0;
int cont=0;
for (i=0; i< numelem; i++)
if (vec[i]< 0) cont++;
return (cont);
}
void main ()
{
int v ={3, -3,-4,5,12,-5};
int res;
res = NEGATIVO(v,6);
printf (%d, res);
}
.code 32
.global main, __cpsr_mask
main:
push {lr}
sub sp, sp, #4
adr r1, v
mov r0, #6
push {r0,r1}
bl NEGATIVO
add sp, sp, #8
pop {r0}
str r0, res
pop {lr}
v: .word 3, -3,-4,5,12,-5;
res: .word 0;
NEGATIVO:
push {r11,lr}
mov r11, sp
push {r3-r7}
mov r5, #0
mov r3, #0
ldr r4, [r11,#8]
ldr r6, [r11, #12]
for: cmp r4, r3
beq finfor
ldr r7, [r6, r3, lsl#2]
add r3, r3, #1
blt nega
b for
nega: add r5, r5, #1
b for
finfor: str r5, [r11, #16]
pop {r3-r7,r11,pc}
0/0

PILA/Bloque de activacin


r3
r7
r0
r9
r:
r r
lr - main
numelem #9$ r I ;
Rvec r I 2
/esultado #3$ r I 9
lr - sistema

Вам также может понравиться