Práctica: Interfaz C S.E.T.I. 1

Anuncio
Práctica: Interfaz C
S.E.T.I. 1
Enunciado:
Queremos realizar un programa en C que maneje ventanas emergentes, pero queremos que el
dibujado de las mismas sea lo más rápido posible, por lo que nos hemos decidido a escribir la rutina en
ensamblador.
El fichero Makefile contiene lo siguiente:
#Fichero makefile.
windows.exe: main.obj fastwin.obj
bcc –ml -v -ewindows.exe main.obj fastwin.obj
main.obj: main.c
bcc –ml –v -c main.c
fastwin.obj: fastwin.asm
nasm –g -fobj fastwin.asm
donde tenemos que tener cuidado en introducir tabuladores para sangrar el texto.
El fichero main.c simplemente comprueba el funcionamiento de dicha rutina haciendo aparecer
unas 2000 ventanas de posición y color variables. Notar cómo la subrutina en cuestión se declara como
externa para ser enlazada posteriormente.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Función externa realizada en ensamblador, que será enlazada
// con este código
extern void windows_at(long int, long int, long int, long int,
int);
void main()
{
int i;
randomize();
for( i=0;i<2000;i++ )
windows_at(random(40), random(10), 30, 10, random(127));
}
Para la realización de la subrutina en ensamblador hemos de tener en cuenta algunos detalles:
El nombre de las funciones en C van precedidas de un guión bajo (_). Así en nuestro caso deberemos
declarar como global la etiqueta _windows_at en el programa ensamblador y sin guión bajo en el
programa en C.
El esqueleto del programa en ensamblador (fastwin.asm) se muestra a continuación:
[section .text]
[global _windows_at]
; La función es:
; windows_at(long int x, long int y, long int sizex,
;
long int sizey, int attribute);
;
; donde:
;
ebp + 0 EBP viejo
;
ebp + 4 Dirección de retorno far
;
ebp + 8 Primer parámetro (4 bytes)
;
ebp + 12 Segundo parámetro (4 bytes)
;
ebp + 16 Tercer parámetro (4 bytes)
;
ebp + 20 Cuarto parámetro (4 bytes)
;
ebp + 24 Quinto parámetro (2 bytes)
; Ojo: En el compilador Borland C de MSDOS
;
;
Tipo C
Tamaño
; -------------------------------------------------------;
char
2
Ocupa 1 pero se alinea a dos byte
;
int
2
(en Linux es 4)
;
long int
4
;
short
2
;
int*
4
primero el desplazamiento
;
de 16 bits y el selector 16 bits
;
de donde se encuentra la variable
_windows_at:
push ebp
mov ebp,esp
pushad
....
Ej:
....
popad
pop ebp
retf
; Guardo el puntero base
; Apunto a la cima de la pila
; Guardo los registros que uso
mov eax,[ebp+20] ; Lee sizey
; Recupero los registros que uso
; Recupero el puntero base
; Retorno far
Si la rutina devolviera un valor entero lo haría modificando el registro EAX. Dado que la rutina del
ejemplo no devuelve ningún valor, EAX recupera su valor al salir. Notar que el C utiliza una llamada lejana
(far) para acceder a nuestra función, luego hay que hacer un retorno far (retf)
Para acceder a la pantalla en modo texto (80x25 caracteres) hay que saber que está situada en la
dirección 0B800h:0000h, luego habrá que apuntar al segmento correspondiente y calcular el
desplazamiento correcto. Cada palabra que se escribe representa lo siguiente:
Byte bajo: el código ASCII que queremos pintar. El espacio es el código 32.
Byte alto: atributos de color del carácter calculado como sigue:
Atributo = 128*Parpadeo + 16*Color_fondo + Color_primer_plano
donde Parpadeo = 0 ó 1, Color_Fondo = 0..7, Color_primer_plano = 0..15
Primeramente realizar la subrutina windows_at() de forma que rellene un recuadro situado a
partir de la posición (x,y) y con un tamaño (sizex,sizey) escribiendo caracteres en blanco con el atributo de
color seleccionado.
Intentar que la ventana esté recuadrada con una línea sencilla. Para ello podéis emplear los
caracteres: 218, 196, .., 196, 191 para el marco superior; 179, 32, .., 32, 179 para la zona intermedia; y 192,
196, .., 196, 217 para el marco inferior.
Descargar