La práctica consiste en la realización de dos tareas:
La práctica se valorará en función de la interacción entre el lenguaje C y el ensamblador, más que por un gran desarrollo en C.
No se permite el uso de código ensamblador insertado en funciones de C.
Es obligatorio el uso de paso de parámetros entre C y ensamblador.
Se recomienda dejar la implementación del formato .s19 para el final, una vez que ya esté todo funcionando para el formato binario.
Qué hay que hacer:
1. Escribir en ensamblador un programa aparte o una librería de conexión entre
la parte C y el driver. Este programa aparte o librería deberá incluir una
llamada a cada función
correspondiente a cada servicio del driver (cada AH distinto).
2. Escribir la interfaz en C (descrita en el inicio de
este documento).
3. "Linkar" el programa en C y la librería en ASM
en un programa.
4. Hacer un makefile que compile y haga el "linkado".
Ejemplo completo de programación mixta (ASM+C) paso a paso:
En muchas ocasiones se necesita el calculo a*b/c con números enteros. El
problema consiste en el posible desbordamiento del a*b incluso si el resultado
a*b/c cabe en un int. Por tanto, dicho calculo hay que hacerlo en ensamblador
o con tipo long, que es mas costoso. Se necesita hacer una función
en ensamblador, que calcula a*b/c.
1. Elegimos el prototipo de la función:
int mul_div(int a,int b,int c);
Escribimos dicho prototipo en el fichero mul_div.h
2. Necesitamos el esqueleto de esta función en ASM:
Escribimos en un fichero llamado mul_div.c:
int mul_div(int a, int b, int c) {
return a+b-c; // notar la diferencia en el func. Es un
stub
}
compilamos, generando ASM
tcc -S mul_div.c
3. Escribimos el programa en ensamblador, utilizando el esqueleto generado
por tcc en el paso previo:
edit mul_div.asm
En el cuerpo del programa cambiamos las instrucciones necesarias:
mul_div proc near
push bp
mov bp,sp
...
mov ...,[bp+4] ; el a
add ...,[bp+6] ; el b
sub ...,[bp+8] ; el c
...
pop bp
ret
mul_div endp
...
cambiamos a:
mul_div proc near
push bp
mov bp,sp
mov ax,[bp+4] ; el a
cwd
imul [bp+6] ; el b
idiv [bp+8] ; el c
pop bp
ret
mul_div endp
4. Compilamos el modulo ASM con opciones 'case sensitive'
4.1. Encontramos la opción:
tasm
4.2. Compilamos (los ... es la opción):
tasm -m... mul_div.asm
5. Escribimos un programa en C (muldiv.c) que comprueba la función:
#include <stdio.h>
#include "mul_div.h"
int main() {
for(;scanf("%d%d%d",&a,&b,&c)==3;) {
printf("%d %d\n",mul_div(a,b,c),a*b/c);
}
return 0;
}
5. Compilamos:
tcc muldiv.c
(mensaje de error por falta de la función mul_div)
tcc muldiv.c mul_div.obj
6. Comprobamos.
A>muldiv.exe
Comprobar con las entradas 2 3 2 y 512 512 10.
7. Hacer makefile:
Hemos ejecutado los comandos
tasm /mx mul_div
con entrada mul_div.asm y salida mul_div.obj y
tcc muldic.c mul_div.obj
con entrada muldiv.c, mul_div.obj y salida muldiv.exe.
muldiv.c contiene el ‘include’ de mul_div.h. Por tanto el makefile seria:
----------------------------------------------------------
muldiv.exe: muldiv.c mul_div.obj mul_div.h
tcc muldiv.c mul_div.obj
mul_div.obj: mul_div.asm
tasm /mx mul_div
----------------------------------------------------------
escribimos el makefile (edit makefile) y comprobamos:
del *.obj
make -f makefile
9. Ejercicios:
1. Quitar todo lo no necesario en el fichero mul_div.asm.
2. Hacer el link separado de la compilación en
el ejemplo.
3. Comprobar el programa con entrada 512 512 5 .
4. Hacer el programa mul_div con tipo unsigned. Comprobar
512 512 5.
5. Hacer mul_div en modelo de memoria large.
Notas de ayuda: El Universo Digital del PC: El ensamblador y el lenguaje C. Capítulo 13 de un buen libro digital