Professional Documents
Culture Documents
19 DE MAYO DE 2017
LAB05: USO DEL
LENGUAJE
ENSAMBLADOR CON EL
COMPLILADOR C.
PORCENTAJE NOTA
1) INTRODUCCION 5%
2) OBJETIVOS 5%
3) MARCO TEORICO 10%
4) DESARROLLO DE LA PRACTICA 10%
5) ASIGNACIONES 40%
ASIGNACION 1 8%
ASIGNACION 2 8%
ASIGNACION 3 8%
ASIGNACION 4 8%
ASIGNACION 5 8%
CONCLUSIONES 30%
NOTA FINAL
ESTUDIANTES:
Tabla de contenido
INTRODUCCION ................................................................................................................................... 2
OBJETIVOS ........................................................................................................................................... 3
ASIGNACIONES .................................................................................................................................... 8
CONCLUSIONES ................................................................................................................................. 15
1
INTRODUCCION.
El lenguaje ensamblador sirve para muchos propósitos, como mejorar la velocidad del
programa, reducir la memoria necesaria y supervisar el hardware. Pero hoy día, pocos
programas están escritos completamente en ensamblador. Los compiladores son muy buenos
en convertir código de alto nivel en un código de máquina eficiente. Ya que es mucho más
fácil escribir código en un lenguaje de alto nivel, es más popular. Además, el código de alto
nivel es mucho más portátil que el ensamblador. Cuando se usa ensamblador, se usa a
menudo solo para pequeñas partes de código. Esto se puede hacer de dos maneras: llamando
rutinas de ensamblador desde C o ensamblado en línea.
2
OBJETIVOS
General:
Conocer las estructuras básicas para la combinación del lenguaje ensamblador con
lenguaje de alto nivel C, así como las diferentes maneras en las que se puede usar esta
mezcla para la creación de programas más eficientes.
Específicos:
3
MARCO TEORICO.
La palabra ASM
Este es un mecanismo de escape que permite escribir código ensamblador para el hardware
dentro de un programa en C. A menudo es capaz de referenciar variables C dentro del código
ensamblador, lo que significa que se puede comunicar fácilmente con el código C y limitar
el código ensamblador a lo necesario para ajustes eficientes o para utilizar instrucciones
especiales del procesador. La sintaxis exacta que se debe usar cuando se escribe en lenguaje
ensamblador es dependiente del compilador y se puede encontrar en la documentación del
compilador. La sentencia ASM permite incluir código ensamblador dentro del programa C,
utilizando los mnemónicos normales del ensamblador. Sin embargo, el uso de esta
posibilidad está más o menos limitado según la versión del compilador. En Turbo C 2.0, los
programas que utilizan este método es necesario salir a la línea de comandos para compilarlos
con el tradicional compilador de línea, lo cual resulta poco atractivo. Sin embargo, es a partir
del Borland C++ cuando se puede trabajar a gusto: en concreto, la versión Borland C++ 2.0
permite ensamblar sin rodeos código ensamblador incluido dentro del listado C. El único
inconveniente es la limitación del hardware disponible: para un PC/XT, el Turbo C 2.0 es el
único compilador aceptablemente rápido. Sin embargo, en un 286 es más recomendable el
Turbo C++, mientras que en un 386 modesto (o incluso en un 286 potente) resulta más
interesante emplear el Borland C++ 2.0: las versiones 3.X de este compilador son las más
adecuadas para un 486 o superior (bajo DOS). Como ejemplo del uso de esta sentencia se
muestra las siguiente instrucciones que permiten cambiar el modo de video de la pantalla a
un modo VGA estándar con código ensamblador, es mucho más sencillo:
4
DESARROLLO DE LA PRÁCTICA
1. #include <stdio.h>
2. /*
3. Este ejemplo muestra como combinar el codigo en lenguaje
4. Ensamblador con codigo C
5. Realiza las operaciones basicas suma, resta, multiplicacion y
6. Division con dos numeros de 8 bits
7. */
8. int main()
9. {
10. int dato1, dato2, suma, resta, multiplicacion,division;
11. printf("Multiplicación de dos numeros \n");
12. printf("\nPrimer numero: ");
13. scanf("%d", &dato1);
14. printf("Segundo número: ");
15. scanf("%d", &dato2);
16.
17. asm{
18. push dx //Introduciendo los registros a la
pila
19. push cx
20. push bx
21. push ax
22.
23. //Suma
24. mov ax,dato1
25. add ax,dato2
26. mov suma,ax
27.
28. //Resta
29. mov ax,dato1
30. sub ax,dato2
31. mov resta,ax
32.
33. //Multiplicacion
34. mov ax,dato1
35. imul dato2
36. mov multiplicacion , ax
37.
38. //Division
39. mov ax,dato1
40. div dato2
41. mov ah,0
42. mov division,ax
43.
44. pop ax
45. pop bx
46. pop cx
5
47. pop dx //Devolviendo los registros de la
pila
48.
49. }
50. printf("\nSuma: %d\n", suma);
51. printf("Diferencia: %d\n",resta);
52. printf("Producto: %d\n", multiplicacion);
53. printf("Cociente: %d\n", division);
54. return 0;
55. }
Al compilar el codigo anterior en Borland C se puede observar que el programa realiza las
cuatro operaciones basicas, con dos numeros ingresados por el usuario como muestra la
figura 1.
1. #include <stdio.h>
2.
3. main()
4. {
5. //El siguiente programa representa un ejemplo de una
6. //transmision de bytes de datos utilizando sus bits de paridad
7. //aunque los datos solo se miran en pantalla, en la
8. //practica se utiliza un puerto y la paridad para detectar
9. //errores en la recepcion.
10.
11. int byte1,byte2, paridad;
12. printf("introdusca el primer byte en hexadecimal \n");
13. scanf("%x", &byte1);
14. printf("introdusca el segundo byte en hexadecimal \n");
15. scanf("%x", &byte2);
6
16.
17. asm{
18. push ax //Guardamos los registros que usaremos
19. push bx //Por razones de seguridad
20. mov paridad,0
21. mov ax,0
22. mov bx,byte1
23. and bx,0ffh //Operacion logica que activa la bandera de
paridad
24. pushf //Guardamos el registro de banderas en la pila
25. pop ax //Y lo recuperamos sin alterarlo
26. and ax,04h //Probamos la bandera de paridad
27. cmp ax,04h
28. jne seguir
29. inc paridad //Incrementamos el resultado si hay bit de
paridad
30. }
31. seguir:
32. asm{
33. mov bx,byte2 //Repetimos lo mismo que hicimos
34. and bx,0ffh //con el primer byte
35. pushf
36. pop ax
37. and ax,04h
38. cmp ax,04h
39. jne final
40. add paridad, 2h
41. }
42. final:
43. asm{
44. pop bx //Recuperacion de los registros antes
45. pop ax //De terminar las lineas de ensamblador
46. }
47. printf("\n byte con la paridad junto a los dos bytes
originales:\n");
48. printf("%X%X%X\n",paridad,byte2,byte1);
49. return 0;
50. }
Fig. 2: Compilación del código del Apéndice B, obtiene paridad para detectar errores de transmisión .
7
ASIGNACIONES.
Programar la mayor parte del código en un lenguaje de alto nivel, lo que permite
reducir el tamaño del código en general además de hacerlo más portable y eficiente.
Permite obtener una mayor velocidad de los programas, esto ya que las instrucciones
de ensamblador se ejecutan más rápidas que las de C, además Permite acceso directo
a hardware para controladores de dispositivos.
Programas que requieran acceso directo a periféricos de entrada y salida pueden ser
programados en C con instrucciones de ensamblador.
8
Aplicaciones que requieran una alta velocidad de ejecución, pueden ser programadas
en C y por medio de instrucciones de ensamblador aumentar la velocidad de
operaciones realizadas. Un ejemplo pueden ser aplicaciones de tabulación de datos
en tiempo real.
Código:
1. #include <stdio.h>
2.
3. int main()
4. {
5. int pos1 = 14, pos2 = 10, pos3 = 50, pos4 = 69, pos5 = 99;
6. int dato;
7. char mensaje1[] = "USTED ES UN GANADOR";
8. char mensaje2[] = "SUERTE LA PROXIMA VEZ";
9.
10. asm{
11. mov ah,06h //Borrando la pantalla
12. mov cx,0000
13. mov dx,2379
14. int 10h
15.
16. mov ah,02H //Posicionando el cursor en pantalla
17. mov dh,10
18. mov dl,10
19. mov bh,0
20. int 10h
21. }
22.
23. printf("INTRODUZCA UN NUMERO DEL 1 AL 100 Y DESCUBRA SI ES UN
GANADOR\n");
24.
25. asm{
26. mov ah,02H //Posicionando el cursor
27. mov dh,12
9
28. mov dl,40
29. mov bh,0
30. int 10h
31. }
32. scanf("%d",&dato); //Leyendo el dato del usuario
33.
34. asm{
35. mov ah,02H //Posicionando el cursor
36. mov dh,15
37. mov dl,31
38. mov bh,0
39. int 10h
40. }
41.
42. asm{
43.
44. mov cx,dato //Comparando el dato contra
45. mov ax,pos1 //la primer posicion de memoria
46. cmp ax,cx
47. je ganador
48.
49. mov ax,pos2 //Comparando el dato contra
50. cmp ax,cx //la segundo posicion de memoria
51. je ganador
52.
53. mov ax,pos3 //Comparando el dato contra
54. cmp ax,cx //la tercera posicion de memoria
55. je ganador
56.
57. mov ax,pos4 //Comparando el dato contra
58. cmp ax,cx //la cuarta posicion de memoria
59. je ganador
60.
61. mov ax,pos5 //Comparando el dato contra
62. cmp ax,cx //la quinta posicion de memoria
63. je ganador
64. jmp fin //Salta a fin si no se encuentra
65. } //igualdad en las posiciones de memoria
66.
67. ganador:
68. printf("%s",mensaje1);
69. return 0;
70.
71. fin:
72. printf("%s",mensaje2);
73. return 0;
74. }
10
Fig. 3: Programa escrito en lenguaje C, con instrucciones de ensamblador para la asignación 3,muestra un
mensaje para un numero invalido.
Fig. 4: Programa escrito en lenguaje C, con instrucciones de ensamblador para la asignación 3, muestra un
mensaje para un numero valido.
11
Asignación 4: Hacer un programa que espere una clave desde consola por ejemplo
“programables”; el programa debe comprobar la clave tecleada con la que se encuentra
en una variable, y si coinciden encender un led verde, si son diferentes encender un led
rojo. Puede utilizar el puerto paralelo. Hágalo con instrucciones de C para escribir en
el puerto, y también hágalo accesando el puerto con lenguaje ensamblador. Comente
diferencias.
Descripción del código: Para este código escrito en C, se hace uso de instrucciones en
ensamblador para validar una clave ingresada y mostrar en pantalla el mensaje de validación.
Código:
1. #include <stdio.h>
2.
3. int main ()
4. {
5. char clave1[12]="programables";
6. char clave[12];
7. printf ("\nBienvenido\n");
8. printf("Introduzca la contrasena\n");
9. scanf("%s",&clave);
10.
11. asm{
12. push dx
13. push cx
14. push bx
15. push ax
16.
17. cld
18. mov si, offset clave1
19. mov di, offset clave
20. mov cx,12
21. repne cmpsb //comparando los caracteres ingresados
22. jcxz wrong //contra la contraseña almacenada
23. jmp right
24.
25. }
26. right:
27. printf("\nLa contrasena ingresada es correcta\n");
28. asm {
29. mov dx,378h
30. mov al,01h //asumiendo que el LED verde esta en el bit o del
puerto
31. out dx,al
32. jmp fin
33. }
34. wrong:
35. printf("\nLa contrasena ingresada es incorrecta\n");
36. asm {
37. mov dx,378h
38. mov al,02h //asumiendo que el LED rojo esta en el bit 1 del
puerto
39. out dx,al
40. jmp fin
12
41. }
42. fin:
43. asm {
44. pop ax
45. pop bx
46. pop cx
47. pop dx
48. }
49. return 0;
50. }
Fig. 5: Programa de validación de clave escrito en C con instrucciones de ensamblador para la asignación 4.
Existen diferentes herramientas para utilizar lenguaje ensamblador en Linux. Entre ellas se
encuentra el programa ensamblador GAS (AS), en el cual se debe escribir el programa con
sintaxis de AT&T, que tiene las siguientes características:
Se debe indicar el tamaño de los operandos (byte [b], palabra [w], etc.) en cada
opcode.
Se preceden los registros con un “%” y los literales con el signo “$”.
13
Código ejemplo:
14
CONCLUSIONES
Las aplicaciones que requieren alta velocidad de ejecución deben tener estrictamente
instrucciones de ensamblador ya que ningún otro lenguaje puede acceder
directamente a la memoria de la maquina.
15