You are on page 1of 11

MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

1

UNIVERSIDAD DE EL SALVADOR
FACULTAD MULTIDISCIPLINARIA PARACENTRAL
DEPARTAMENTO DE INFORMATICA



MICROPROGRAMACIN

LLAMADO DE PROCEDIMIENTOS
DE ENSAMBLADOR DESDE C
CATEDRATICO:
ING. HERBERT MONGE
INTEGRANTES:
JAVIER ARMANDO OCHOA CERON
EDWIN ANTONIO AMAYA GONZALEZ
ROBERTO AVELAR GARCIA

SAN VICENTE, JUNIO DE 2009

MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

2

La invencin de los lenguajes de alto nivel represent un paso evolutivo muy
importante en la programacin ya que al poder expresar las instrucciones en una
forma ms natural, el programador pudo concentrarse ms en el problema a resolver
y menos en cmo hacer que la computadora resolviera el problema. En un principio,
ciertos inconvenientes limitaban el uso de los lenguajes de alto nivel:

Algunos lenguajes de alto nivel estn diseados para resolver cierto tipo de
problemas. Por ejemplo el lenguaje FORTRAN esta enfocado a resolver
problemas de clculos numricos cientficos mientras que el lenguaje COBOL
se emplea para resolver problemas administrativos y contables.

Los programas escritos en lenguajes de alto nivel no eran muy eficientes en
trminos de tamao y velocidad.

Con la invencin de los lenguajes de propsito general como el BASIC y Pascal se
populariz ms el uso de los lenguajes de alto nivel debido a la gran gama de
problemas que se podan resolver. Sin embargo en la programacin de sistemas,
donde se requiere interactuar con el hardware de la computadora, el lenguaje
ensamblador sigui siendo necesario. Con la llegada del lenguaje C que permite un
acceso directo a la memoria y al hardware y debido al cdigo eficiente que genera, el
uso del lenguaje ensamblador se redujo an ms.

Porque utilizar C y Ensamblador?
El lenguaje C es sin duda el ms apropiado para la programacin de sistemas,
pudiendo sustituir al ensamblador en muchos casos. Sin embargo, hay ocasiones en
que es necesario acceder a un nivel ms bajo por razones de operatividad e incluso de
necesidad (programas residentes que economicen memoria, algoritmos rpidos para
operaciones crticas, etc.). Es entonces cuando resulta evidente la necesidad de poder
emplear el ensamblador y el C a la vez.

El cdigo en ensamblador puede mezclarse con cdigo en lenguajes de alto nivel como
C, Pascal, Basic, etc. En este tema se estudiar las formas de mezclar C y ensamblador.
La mejor forma de la mejor de mezclar C y ensamblador es utilizar los conceptos de
programacin modular y funcional para mantener separado el cdigo en C del cdigo
en ensamblador. Esto es, el cdigo que sea necesario escribir en ensamblador se
escribir como procedimientos. Adicionalmente los procedimientos escritos en
ensamblador estarn en uno o ms mdulos los cuales sern ensamblados y sus
cdigos objeto sern ligados con los mdulos objeto resultantes de compilar los
mdulos en C.

En las siguientes secciones se describe la forma de escribir un procedimiento en
ensamblador que pueda ser llamado desde un programa en C.

Llamado De Procedimientos En Ensamblador Desde C
Para escribir un procedimiento en ensamblador para ser llamado desde C deben
considerarse los siguientes puntos:
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

3

Modelos de memoria
Al compilar los mdulos en C debe usarse el mismo modelo de memoria que el
empleado para ensamblar los mdulos en ensamblador.

Nomenclatura de los segmentos en los programas en C
Los nombres de los segmentos en los que se almacenan los mdulos del cdigo en
ensamblador deben ser los empleados por los mdulos en C. Turbo C utiliza la misma
nomenclatura empleada por Microsoft. Los nombres de los segmentos para los
diferentes modelos de memoria aparecen en la tabla 9-1.


El uso de las directivas ideal, dosseg y model le indican a Turbo Assembler que emplee
la nomenclatura y el ordenamiento de los segmentos empleados por Microsoft, Turbo
C y muchos de los fabricantes de compiladores.

Cdigo De Inicio: El cdigo de inicio de un programa en ensamblador para el 8086
tiene como propsito declarar los nombres de los segmentos en los que se almacenar
el cdigo del programa, los datos y la pila. Tambin establece el modelo de memoria
bajo el que se ensamblar el programa y el tamao de la pila. El cdigo de inicio consta
de un conjunto de directivas. En el programa de ejemplo tenemos:

Ideal: El modo ideal es una notacin que emplea el ensamblador Turbo Assembler de
Borland International para simplificar la sintaxis del cdigo inicial de un programa. La
directiva ideal le dice a Turbo Assembler que utilice el modo ideal. Si se omite se
utiliza la notacin empleada por la mayora de los ensambladores, por ejemplo el de
Microsoft.

Dosseg: Esta directiva que forma parte del modo ideal, le instruye al ensamblador que
nombre y ordene los segmentos del programa de la misma forma en que lo hacen los
compiladores de alto nivel. Esto es adecuado para la mayora de los programas en
ensamblador y sobre todo en las rutinas de ensamblador que se van a ligar a un
programa en alto nivel.

Model: Esta directiva que debe ir despus de la directiva dosseg, selecciona uno de los
6 modos diferentes que tiene Turbo Assenbler de generar el cdigo de un programa
dependiendo del tamao que tiene el cdigo y los datos. Estos modos llamados
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

4

modelos de memoria, difieren en el tipo de apuntadores que el compilador genera por
omisin y por lo tanto en la rapidez de ejecucin del cdigo. Los seis modelos de
memoria son: Pequeito (tiny), pequeo (small), medio (medium), compacto
(compact), grande (large) y extenso (huge).

Nomenclatura de los nombres de variables y funciones en los programas en C
La mayora de los compiladores de C, entre ellos Turbo C, le agregan a los nombres de
funciones y variables externas el prefijo _, carcter de subraya. Por lo tanto, en el
cdigo en ensamblador todas las referencias a funciones y variables de los mdulos en
C deben empezar con el carcter de subraya. Tambin todos los nombres de los
procedimientos y variables en los mdulos en ensamblador que van a ser
referenciados en el cdigo en C deben declararse como pblicos y empezar con el
carcter de subraya.
C hace distincin entre maysculas y minsculas. El lenguaje ensamblador no hace
distincin entre maysculas y minsculas. Para hacer que Turbo Ensamblador haga
distincin entre maysculas y minsculas en los nombres declarados como pblicos o
externos hay que utilizar la opcin del ensamblador /mx.

Tipos de datos en C y en ensamblador
La tabla 9-2 muestra la correspondencia entre los tipos de datos en C y en
ensamblador:



Mecanismo de paso de parmetros en C
C pasa los parmetros a las funciones en la pila. Antes de llamar a la funcin, C inserta
los parmetros para esa funcin en la pila, empezando con el parmetro de ms a la
derecha y terminando con el parmetro de ms a la izquierda. Por ejemplo, considere
un programa con la funcin f() declarada como:
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

5

int f(int param1, int param2);

Si el programa se compila usando los modelos de memoria pequeito, pequeo o
compacto, inmediatamente despus de ejecutada la llamada a la funcin f():

f(arg1, arg2)

el estado de la pila es el mostrado en la figura 9-1a, mientras que si el programa se
compila usando los modelos de memoria medio, grande o gigante, el estado de la pila
es el mostrado en la figura 9-1b.

Si la definicin de la funcin se escribe en ensamblador se puede accesar a los
parmetros recibidos en la pila con referencia al registro BP. Para ello, una vez dentro
del procedimiento, lo primero que se hace es preservar el valor del registro apuntador
de base, BP, insertndolo en la pila. A continuacin se hace que BP apunte al tope de la
pila, ya que a partir de esa posicin se ubicarn los parmetros. Las instrucciones para
obtener lo anterior son:


push bp
mov bp, sp

El estado de la pila, despus de estas instrucciones se muestra en la figura 9-2a si se
usan los modelos de memoria pequeito, pequeo o compacto o en la figura 9-2b si se
usan los modelos de memoria medio, grande o gigante.

Los parmetros se identifican en la figura con los nombres: arg1 y arg2. Sin embargo
el acceso a los parmetros es mediante sus direcciones las cuales son: BP + 4 y BP + 6,
respectivamente para los modelos de memoria pequeito, pequeo o compacto o BP
+ 6 y BP+ 8 si se usan los modelos de memoria medio, grande o gigante.

Al regresar de la funcin, los parmetros que fueron insertados en la pila siguen ah,
pero ya no son de utilidad. Por lo que, inmediatamente despus de cada llamada a una
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

6

funcin, C ajusta el apuntador a la pila al valor que tena antes de que se insertaran los
parmetros en la pila.


Uso de los registros
Desde el punto de vista de C, un procedimiento escrito en ensamblador y llamado
desde C puede hacer lo que sea siempre y cuando preserve los valores de los registros
SI, DI, BP, SP, CS, DS y SS, esto es, si el procedimiento utiliza esos registros
internamente, debe dejarlos a los valores que tenan antes de la llamada al
procedimiento.

Mecanismo de regreso de valores de C
Un procedimiento en ensamblador a ser llamado desde C debe usar el mismo
mecanismo para regresar valores que una funcin en C. Los valores son regresados en
los registros AX y DX como se muestra en la tabla 9-3:






MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

7

EJEMPLOS
El siguiente programa en C que lea dos nmeros enteros largos, los sume y despliegue
el resultado. El programa llama a una funcin escrita en ensamblador para sumar los
nmeros.

#include <stdio.h>
long sumando(long dato1, long dato2);
int main(void)
{
long dato1, dato2, suma;
clrscr();
printf("\nDato 1: ");
scanf("%ld", &dato1);
printf("\nDato 2: ");
scanf("%ld", &dato2);
suma = sumando (dato1, dato2);
printf("\nLa suma es %ld", suma);
getch();
return 0;
}

Si se utiliza el modelo de programacin pequeo, el mdulo en ensamblador con la
funcin que suma los enteros largos se muestra en el siguiente listado:

;****** CODIGO DE INICIO ************************************
ideal
dosseg
model small
;****** CODIGO DEL PROGRAMA *********************************
codeseg
public _sumando
;****** PROCEDIMIENTOS **************************************
; long s2dw(long dato1, long dato2)
;
; Este procedimiento regresa la suma de dato1 y dato2.
; Parmetros:
; [BP+4] = dato1
; [BP+8] = dato2
; Regresa:
; DX:AX = suma
;************************************************************
proc _sumando
push bp ; Preserva BP
mov bp, sp
mov ax, [bp+4] ; suma = dato1
mov dx, [bp+6]
add ax, [bp+8] ; suma += dato2
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

8

adc dx, [bp+10]
pop bp ; Restaura BP
ret ; return suma
endp _sumando
;****** CODIGO DE TERMINACION *******************************
end _sumando

El siguiente programa en C lee un conjunto de enteros y los almacena en un arreglo,
luego encuentra y despliega el mayor de los datos. El programa llama a una funcin
escrita en ensamblador para encontrar el mayor de los nmeros.

#include <stdio.h>
int leeDatos(int *pDatos);
int mnw(int *pDatos, int nDatos);
int main(void)
{
int n, mayor;
int datos[50];
n = leeDatos(datos);
mayor = mnw(datos, n);
printf("\nEl mayor es %d", mayor);
getch();
return 0;
}
/***********************************************************
* int leeDatos(int *pDatos)
*
* Esta funcin lee una serie de enteros y los almacena en el arreglo dado por pDatos. La
*funcin regresa el numero de datos ledos.
***********************************************************/
int leeDatos(int *pDatos)
{
int nDatos, i;
printf("\nNumero de datos: ");
scanf("%d", &nDatos);
for(i = 0; i < nDatos; i++)
{
printf("\nDato %d: ", i+1);
scanf("%d", pDatos+i);
}
return nDatos;
}

El siguiente listado muestra el mdulo en ensamblador, utilizando el modelo de
programacin pequeo, con la funcin que encuentra el mayor del conjunto de
Enteros:
MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

9

;****** CODIGO DE INICIO ************************************
ideal
dosseg
model small
;****** CODIGO DEL PROGRAMA *********************************
codeseg
public _mnw
;****** PROCEDIMIENTOS **************************************
; int mnw(int *pDatos, int nDatos)
;
; Este procedimiento regresa el mayor de un conjunto de
; nDatos datos de tipo palabra almacenados dentro del arreglo
; pDatos.
; Parmetros:
; [BP+4] = pDatos
; [BP+6] = nDatos
; Regresa:
; AX = mayor
;************************************************************
proc _mnw
push bp ; Preserva BP
mov bp, sp
push si ; Preserva SI
mov cx, [bp+6] ; CX = nDatos-1
dec cx
sal cx, 1
mov bx, [bp+4] ; BX = pDatos
mov ax, [bx] ; mayor = pDatos[0]
xor si, si ; i = 0
@@whi: cmp si, cx ; while(i < nDatos-1)
jbe @@endwhi ; {
inc si ; si++
inc si
cmp ax, [bx+si] ; if(mayor >= pDatos[i])
; continue
jge @@whi
mov ax, [bx+si] ; mayor = pDatos[i]
jmp @@whi ; }
@@endwhi:
pop si ; Restaura SI, BP
pop bp
ret ; return mayor
endp _mnw
;****** CODIGO DE TERMINACION *******************************
End

El programa C acepta valores desde el teclado para el regln y la columna y los pasa al
subprograma en ensamblador. El programa a su vez coloca el cursor y regresa al
modulo en C.

MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

10

#include<stdio.h>
int main(void)
{
int temp_row, temp_col;

printf("Enter cursor row: ");
scanf("%d",&temp_row);

printf("Enter cursor col: ");
scanf("%d",&temp_col);

set_curs(temp_row, temp_col);
printf("New cursor location\n");
getch();
}

El siguiente listado muestra el mdulo en ensamblador, utilizando el modelo de
programacin pequeo, con la funcin que posiciona el cursor en pantalla:

_DATA segment word 'DATA'
row equ [bp+4]
col equ [bp+6]
_DATA ends

_TEXT SEGMENT BYTE PUBLIC 'CODE'
DGROUP GROUP _DATA
ASSUME CS:_TEXT, DS:DGROUP, SS:DGROUP

PUBLIC _set_curs
_set_curs PROC NEAR
push bp
mov bp,sp

mov ah,02h
mov bx,0
mov dh,row
mov dl,col
int 10h

pop bp
ret
_set_curs ENDP
_TEXT ENDS
END


MICROPROGRAMACION [LLAMADO DE PROCEDIMIENTOS EN ENSAMBLADOR DESDE C]

11

Generacin de un programa ejecutable
Para generar un programa ejecutable a partir de los mdulos en C y en ensamblador
se sigue el siguiente procedimiento:

1. Ensamblar cada uno de los mdulos por separado. Para ensamblar cada uno de los
mdulos teclear en la lnea de comando:
tasm /mx /l /zi nomArch

/mx Hace todos los nombres sensibles a maysculas y minsculas.

/l Crea un listado de archivo normal.

/zi Incluye informacin acerca de nmeros de lnea e informacin simblica
en el archivo objeto para CodeView, TurboDebugger o SYMDEB.

por ejemplo, para ensamblar el mdulo S2DWP_S.ASM, se teclea en la lnea de
comando:
tasm /mx /l /zi s2dwp_s.asm

2. Crear un proyecto con la lista de los archivos con el cdigo objeto de los mdulos en
ensamblador y la lista de los mdulos en C. Un proyecto es un archivo texto,
almacenado en un archivo con la extensin .PRJ, empleado por el compilador Turbo
C para construir un programa ejecutable. Por ejemplo, el proyecto para generar el
cdigo ejecutable del programa que suma dos nmeros enteros largos podra llamarse
S2DW_AS.PRJ y contener las siguientes dos lneas:

s2dwp_s.obj
s2dwppal.c

3. En el sistema Turbo C, seleccionar el proyecto seleccionando en el men principal la
opcin: Project/Project name.

4. Asegurar que en el sistema Turbo C, la opcin: Options/Compiler/Model contenga el
modelo de memoria igual al empleado en los mdulos en ensamblador.

5. Crear el programa ejecutable seleccionando en el sistema Turbo C la opcin:
Compile/Make EXE file o la opcin: Compile/Build all. El programa ejecutable tendr el
mismo nombre que el archivo con el proyecto.

You might also like