Actualizado el 21 de Marzo del 2018 (Publicado el 3 de Enero del 2018)
579 visualizaciones desde el 3 de Enero del 2018
91,6 KB
33 paginas
Creado hace 9a (23/11/2014)
Procedimientos
Índice
1. Definición y fundamentos
2. Uso en entorno x86-16bits
3. X86 calling conventions
4. Programación multimódulo
5. Librerías
1/66
Procedimientos
1. Definición y fundamentos
1. Definición y fundamentos
Índice
1. Concepto
2. Argumentos
3. Valor devuelto
4. Variables locales
5. Soporte hardware
6. ABI
2/66
1
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.1. Concepto
(cid:127) Términos sinónimos:
Subrutina
Subprograma
Función
Rutina
En algunos casos se reserva el término función para una
subrutina que devuelve un valor
3/66
Procedimientos
1.1. Concepto
(cid:127) Funcionalmente, un procedimiento es un
subalgoritmo de un algoritmo principal que resuelve
una tarea específica
(cid:127) En la práctica, un procedimiento es una fracción de
código separada de la secuencia principal que puede
ser invocado desde cualquier parte del programa, ya
sea desde el flujo principal o desde otro
procedimiento
4/66
2
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.1. Concepto
(cid:127) La invocación de un procedimiento supone una doble
transferencia de control (salto o bifurcación)
Primero al código de la subrutina; y
Posteriormente un retorno al código principal
Algunos compiladores detectan cuantas veces se llama
cada procedimiento y cuando son pocas sustituyen la
llamada por el código 1
Así se evitan la sobrecarga debida a las transferencias
de control (saltos) y al paso de parámetros
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
1 Inline expansion o inlining es una optimización que realiza el compilador
consistente en reemplazar la llamada a una subrutina por el código de la misma
5/66
Procedimientos
1.1. Concepto
(cid:127) Desde el punto de vista de la ingeniería del software
Un procedimiento se escribe una vez y se llama siempre
que haga falta
Facilita:
La vista del código
El mantenimiento del código
La modularidad del código 1
1 La programación estructurada y su “hija” , la programación modular,
consideran que un desarrollo de software òptimo sólo debe utilizar subrutinas
6/66
3
(cid:127) Elementos de una subrutina
Declaración
Nombre
Código
Argumentos o parámetros de entrada
Tipo de valor devuelto (si lo hay)
Procedimientos
1.1. Concepto
argumentos
subrutina
salida
7/66
Procedimientos
1.1. Concepto
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
(cid:127) Nomenclatura
El flujo de código que
invoca el procedimiento se
conoce como código
llamador (caller)
flujo principal
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
El flujo de código que se
ejecuta en el cuerpo del
procedimiento se conoce
como código llamado
(callee)
CALLER
llamada al
procedimiento
código del
procedimiento
CALLEE
8/66
4
Procedimientos
1.2. Argumentos
(cid:127) Son los datos que va a tratar el procedimiento
Podemos pasar argumentos
Por valor el argumento es el dato a tratar
Por referencia el argumento es un puntero a una
posición de memoria en la que está el dato a tratar
Los argumentos son datos de entrada pero también
pueden recibir resultados obtenidos como
consecuencia del procesamiento de la subrutina (si se
pasan como referencia)
9/66
Procedimientos
1.2. Argumentos
(cid:127) Ejemplos1:
int putchar(int char)
valor
Escribe en stdout el carácter pasado como argumento; si
tiene éxito devuelve el carácter y EOF en caso de error
char *strcpy(char *str1, const char *str2)
referencia
Copia (destructiva) de la cadena str2 en la cadena str1;
devuelve el puntero a str1 o NULL si error
1 Usaremos funciones de ANSI C como ejemplo
10/66
5
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.3. Valor devuelto
(cid:127) Un procedimiento puede (opcionalmente) devolver un
valor (que no es de la lista de argumentos)
A veces, es un entero que indica si el procesamiento ha
tenido éxito o se ha producido algún tipo de error
En estos casos, el valor devuelto puede NO usarse sin
que eso afecte a la funcionalidad del programa
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
En otros casos, el valor devuelto es el resultado
principal del procedimiento
11/66
Procedimientos
1.3. Valor devuelto
el valor devuelto puede indicar
si ha ocurrido un error
(cid:127) Modos de uso:
error = funcion(argumentos)
if (error = valor) then …
O mejor:
if (funcion(argumentos) = valor) then …
A veces:
funcion(argumentos) …
12/66
6
(cid:127) Ejemplos:
Procedimientos
1.3. Valor devuelto
el valor devuelto es el
resultado principal
FILE *fopen(const char *nombre, const char *modo)
Abre el fichero cuyo nombre pasamos como primer
argumento; si tiene éxito devuelve un puntero a un
descriptor de fichero y NULL en caso de error
int atoi(const char *str)
Convierte la cadena pasada como argumento a entero;
devuelve el entero ó 0 en caso de error
13/66
Procedimientos
1.4. Variables locales
(cid:127) Un procedimiento puede declarar y utilizar variables
locales, es decir, variables sólo accesibles desde la
subrutina, que se crean cuando se invoca y que
desaparecen cuando termina
Se dice que su ámbito es local y su tiempo de vida
limitado al procesamiento de la subrutina
¡Recordamos! que si el ámbito es local pero el tiempo
de vida es todo el tiempo de ejecución, es una variable
estática
14/66
7
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
(cid:127) Ejemplos:
int mifuncion(argumentos)
{
variable local
int i=10;
while(i)
i--;
…
…
return i;
}
valor devuelto
Procedimientos
1.4. Variables locales
15/66
Procedimientos
1.5. Soporte hardware
(cid:127) Control de flujo
Instrucciones específicas
Llamada salvaguarda de contexto y salto
incondicional a subrutina
Retorno recuperación de contexto y salto
incondicional a código ppal.
El contexto puede ser simplemente el PC o puede ser
una estructura de datos más compleja
Salvaguarda del contexto:
(cid:127) En registros
(cid:127) En la pila
16/66
8
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.5. Soporte hardware
(cid:127) Paso de argumentos
(cid:127) Valor devuelto
(cid:127) Variables locales
En registros
Organizados como banco de registros o
como ventanas de registros1
En la pila
Organización LIFO de memoria
1 Las ventanas de registros encuentran justificación en estudios que establecen
que, en promedio, el máximo número de argumentos es 6, el máximo número de
variables locales es 6 y la profundad máxima de las llamadas es 5
17/66
Procedimientos
1.5. Soporte hardware
(cid:127) Ventajas e inconvenientes:
En registros
Pocos registros hay que garantizar que no se sobreescriben1
No dan lugar a subrutinas reentrantes ni anidables
Los registros son rápidos
Generan pocas dependencias
criterio si se usan registros
En la pila
Acceso lento a memoria
Sobrecarga de dependencias y cálculo de direcciones
Las subrutinas son reentrantes y anidables
1 La salvaguarda de los registros se suele hacer en la pila. Esto genera un tráfico
con memoria en forma de PUSH y POP
18/66
criterio si se usa la pila
9
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.5. Soporte hardware
(cid:127) Teoría de compiladores (I):
Concepto de subrutina reentrante
En general, se dice que un código es reentrante si se
puede llamar simultáneamente desde varios puntos sin
alterar su funcionamiento
Concepto de subrutina anidable
O recursiva, es aquella que puede llamarse a sí misma
Una subrutina recursiva es reentrante
19/66
Procedimientos
1.5. Soporte hardware
(cid:127) Teoría de compiladores (II):
Desde un punto de vista práctico, el código reentrante
no usa variables estáticas en sucesivas llamadas
Para garantizar que un código es reentrante, todos los
datos que se deban mantener entre llamadas deberán
ser suministrados por el llamador (caller)
Una subrutina reentrante no puede usar registros para
pasar argumentos; es imperativo usar la pila
20/66
10
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.5. Soporte hardware
(cid:127) Teoría de compiladores (III):
El lenguaje C está orientado hacía el código reentrante
Las llamadas al sistema no son reentrantes ya que
pasan argumentos en registros (para que sean rápidas)
Para que un sistema operativo sea reentrante, debemos
deshabilitar las interrupciones durante cada llamada al
sistema; esto aumenta la latencia (ralentiza el sistema)
21/66
Procedimientos
1.6. ABI
(cid:127) El Application Binary Interface (ABI) describe la
interfase de bajo nivel que relaciona una aplicación con
el sistema operativo u otras aplicaciones
(cid:127) En concreto el ABI detalla:
Los tipos de datos, su tamaño y el alineamiento
La convenio de llamadas (calling convention) a subrutinas
El modo de realizar las llamadas al sistema
Opcionalmente, el formato de los ficheros OBJ y librerías
El ABI no debe confundirse con el API (librerías de
llamadas al sistema)
El ABI debe cumplirlo el compilador
22/66
11
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
z
e
p
ó
L
o
c
R
i
l
f
e
a
a
R
©
Procedimientos
1.6. ABI
(cid:127) Convenio de llamadas indica:
Cómo se pasan los argumentos
Pila orden (RTL right to left ó LTR left to right)
Registros cuales se usan y en qué orden
funcion (arg_1, arg_2, . . . arg_n)
pila arg_1 arg_2 . . . arg_n
pila arg_n . . . arg_2 arg_1
reg_1 arg_1
reg_2 arg_2
reg_n arg_n
Cómo se comunican los valores devueltos
Quién limpia la pila al terminar
Caller clean-up o callee clean-up
23/66
Procedimie
Comentarios de: Procedimientos (0)
No hay comentarios