Você está na página 1de 0

Rodolfo Gallardo-Rosales

Tutorial
Turbo C Avanzado


Programacin en Lenguaje C avanzado

Universidad de Colima











Colima, Col.












Copyright 2001 por Rodolfo Gallardo-Rosales
rodolfo@gallardo.cc
http://www.gallardo.cc


Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
Programacin en Lenguaje C avanzado

Estado del presente documento

Se edita el presente documento como un complemento a un tutorial de Turbo C. En este, se
podr encontrar tcnicas, mtodos y conocimientos sobre programacin en Turbo C que
no son muy comunes y que vendrn a completar el estudio de lenguaje de programacin
para aqul que ya se ha introducido al C.
Tabla de contenidos
1. Ordenacin y bsqueda

1.1. Ordenacin por el mtodo de la burbuja
1.2. Ordenacin por seleccin
1.3. Ordenacin por insercin
1.4. Ordenacin Shell
1.5. La ordenacin rpida
1.6. Ordenaciones genricas frente a ordenaciones especficas

2. Colas, pilas, listas enlazadas y rboles binarios
2.1. Colas
2.2. Cola circular
2.3. Pilas
2.4. Listas simplemente enlazadas
2.5. Listas doblemente enlazadas
2.6. Arboles binarios

3. C y el 8086[8]
3.1. Bases
3.2. El ensamblador de Microsoft
3.3. Interfaz con rutinas en lenguaje ensamblador
3.4. Creacin de una funcin en lenguaje ensamblador
4. Parmetros del sistema de disco
5. Hora y fecha
6. Grficos
7. Librera de programas
8. Bibliografa


Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
1. Ordenacin y bsqueda
La ordenacin es el proceso de disponer un conjunto de informacin similar, en orden
creciente o decreciente, dando una lista ordenada i de n elementos:
i1 <= i2 <= ... <= in
Podemos encontrar dos categoras generales de ordenacin:
1) la ordenacin de arrays, en memoria y en archivos de discos y
2) la ordenacin de archivos secuenciales en disco o en cinta. Slo nos referiremos a la
primera.
Hay tres formas de ordenar arrays:
Por cambio.
Por seleccin.
Por insercin.
Realizando una analoga con cartas, ordenarlas por cambio, sera extenderlas boca arriba
en una mesa y proceder a cambiar las cartas fuera de orden hasta que la baraja estuviera
ordenada.
En la ordenacin por seleccin, se extenderan las cartas en la mesa y se seleccionar
el valor ms bajo, que mantendremos en la mano, y del resto de cartas en la mesa,
seleccionaremos la siguiente ms baja y la pondremos con la que tenemos en la mano, hasta
que todas las cartas sean ordenadas.
En la ordenacin por insercin se mantienen las cartas en la mano, y tomndolas de una en
una se ponen en un montn sobre la mesa, en su orden correspondiente.
1.1. Ordenacin por el mtodo de la burbuja
La ms conocida ordenacin es esta, sin embargo es una de las peores forma de ordenacin
que se han hecho. Este mtodo, utiliza la ordenacin por cambio, usando repetidas
comparaciones y, si es necesario, cambios adyacentes. Una forma simple es la siguiente:
/* ordenacin por el mtodo de la burbuja*/
void burbuja(char *elemento, int contador)
{
register int a,b;
register char t;
for (a=1;a<contador;++a)
for (b=contador-1;b>=a;t--b) {
if (elemento[b-1] > elemento[b] {
/*intercambio de elementos*/
t=elemento[b-1];
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
elemento[b-1]=elemento[b];
elemento[b]=t;
}
}
}

Elemento es un puntero del array de caracteres que se ordenar y contador es el nmero de
elementos del array.
Para que sea ms visible la forma de ordenacin, se sugiere la siguiente
Actividad:
>> Desarrollar en TC el programa ejemplo No. 1
1.2. Ordenacin por seleccin
Una ordenacin por seleccin selecciona el elemento ms bajo y lo cambia con el primer
elemento. De los restantes n-1 elementos se cambiar por el segundo el siguiente valor ms
bajo y as consecutivamente. Una forma simple de la ordenacin por seleccin es la
siguiente:
/* ordenacin por seleccin*/
void seleccion(char *elemento, int contador)
{
register int a,b,c;
char t;
for(a=0;a<controlador-1>++a) {
c=a;
t=elemento[a];
for(b=a+1;b<contador;++b) {
if(elemento[b]<t) {
c=b;
t=elemento[b];
}
}
elemento[c]=elemento[a];
elemento[a]=t;
}
}

1.3. Ordenacin por insercin

Este es el ltimo algoritmo simple de ordenacin. Esta ordena los dos primeros miembros
del array. El algoritmo inserta el tercer miembro en su correspondiente posicin de acuerdo
a los dos primeros, el cuarto en relacin a los tres, etc.

Una versin de ordenacin por insercin sera la siguiente:
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

/*ordenacin por insercin*/
void insertar(char *elemento, int contador)
{
register int a,b;
char t;

for(a=1;a<contador;++a) {
t=elemento[a];
b=a-1;
while(b>=0&&t<elemento[b]) {
elemento[b-1]=elemento[b];
b--;
}
elemento[b-1]=t;
}
}

1.4. Ordenacin Shell

Toma su nombre de su inventor, D.L. Shell. Este mtodo en general proviene de la
ordenacin por insercin y se basa en la disminucin de incrementos. Primero se ordenan
los elementos separados en tres posiciones, despus en dos posiciones y por ltimo los que
estn juntos.

Una forma simple del algoritmo de ordenacin shell es el siguiente:

/*ordenacin de shell*/
void shell(char *elemento, int contador)
{
register int i,j,k,s,w;
char x,a[5];

a[0]=9; a[1]=5; a[2]=3; a[3]=2; a[4]=1;
for(w=0;w<5;w++) {
k=a[w]; s=-k;
for(i=k;i<contador;++i) {
x=elemento[i];
j=i-k;
if(s==0) { s=-k;
s++;
elemento[s]=x;
}
while(x<elemento[j]&&j>=0&&j<=contador) {
elemento[j+k]=elemento[j];
j=j-k;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
}


elemento[j+k]=x;
}
}
}

1.5. La ordenacin rpida

La ordenacin rpida (quick sort) inventada por Hoare, tiene un rendimiento superior al de
los dems mtodos y se considera el mejor algoritmo de ordenacin disponible en la
actualidad.

Un ejemplo de ordenacin rpida lo da el siguiente fragmento de cdigo, donde se muestra
el algoritmo usado.

/*funcin de preparacin para ordenacin rpida*/
void rapida(char *elemento, int contador)
{
br(elemento,0,contador-1);
}

/*ordenacin rpida*/
void br(char *elemento, int izquierda, int derecha)
{
register int i,j;
char x,y;

i=izquierda; j=derecha;
x=elemento[(izquierda+derecha)/2];
do {
while(elemento[i]<x&&i<derecha) i++;
while(x<elemento[j]&&j>izquierda) j--;
if(i<=j) {
y=elemento[i];
elemento[i]=elemento[j];
elemento[j]=y;
i++; j--;
}
} while (i<=j);
if(izquierda<j) br(elemento,izquierda,j);
if(i<derecha) br(elemento,i,derecha);
}

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
Para poder observar en forma clara y objetiva las diferencias de la ordenacin, se sugiere la
siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 2

1.6. Ordenaciones genricas frente a ordenaciones especficas

En la biblioteca de Turbo C existe la ordenacin rpida genrica qsort() con el siguiente
prototipo:

void qsort(void *comienzo, int contador, int tamao, int *cmpt());

comienzo es un puntero al principio de la lista de artculos que se han de ordenar. Contador
especifica el nmero de elementos de la lista. Tamao especifica la longitud en bytes de
cada elemento de la lista. Cmp es un puntero a una funcin de comparacin que contiene el
prototipo

int cmp(tipo *a, tipo *b);

donde tipo es el tipo de elementos que estn siendo ordenados.

Con el propsito de comparar una versin especializada de ordenacin rpida con la
ordenacin rpida que se encuentra en la biblioteca de Turbo C, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 3

2. Colas, pilas, listas enlazadas y rboles binarios

Los programas en C estn formados por algoritmos y estructuras de datos. Un
buen programa ser la mezcla de ambos. Un buen programador debe poseer los
mtodos correctos de almacenamiento y recuperacin para cualquier situacin.

2.1. Colas

Una cola es una lista lineal de informacin a la que se accede en el orden "primero que
entra es el primero que sale" (llamada tambin FIFO 'First Input First Output'). As, el
primer elemento que entra en la cola, es el primero que se saca, y as sucesivamente.

Para ver cmo funcionan las colas, veamos las funciones almacenar_en_cola(), que site un
elemento al final de la cola; y sacar_de_cola(), que quita el primer elemento de la cola. Se
limita en forma arbitraria a 100 el nmero de entradas y se representa por la macro MAX.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
/*almacenar una cita*/
void almacenar_en_cola(char *cola)
{
if(pos_s==MAX) {
printf("La cola est llena\n");
return;
}
p[pos_s]=cola;
pos_s++;
}

/*sacar una cita*/
char *sacar_de_cola()
{
if(pos_a==pos_s) {
printf("No quedan (ms) citas. \n");
return NULL;
}
pos_a++;
return p[pos_a-1];
}

Tienen ambas dos variables globales: pos_a que almacena el ndice de la siguiente posicin
libre de almacenamiento y pos_s que almacena el siguiente elemento a sacar.

Con el propsito de ver completo un programa simple de planificacin de sucesos, se
sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 4

2.2. Cola circular

En la parte anterior, podramos haber pensado que en vez de parar el programa cuando
alcance el lmite del array utilizado para almacenar la cola, se pudiera volver a los ndices
pos_a y pos_s, lo que permitira poner en la cola cualquier nmero de sucesos. A esta
implementacin se llama cola circular, y las funciones almacenar_en_cola() y
sacar_de_cola() tendran que sufrir algunos cambios, como se indica enseguida:

void almacenar_en_cola(char *cola)
{
if(pos_a+1==pos_s||(pos_a+1==MAX&&!pos_s)) {
printf("cola llena\n");
return;
}
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
p[pos_a]=q;
pos_a++;
if(pos_a==MAX) pos_a=0; /*vuelta al ciclo*/
}

char *sacar_de_cola(void)
{
if(pos_s==MAX) pos_s=0; /*vuelve a empezar*/
if(pos_s==pos_a) {
printf("no hay sucesos por resolver\n");
return NULL;
}
pos_s++;
return p[pos_s-1];
}

Con el propsito de ver en forma completa un programa que usa una cola circular, se
sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 5

2.3. Pilas

Una pila es lo opuesto a una cola porque usa el mtodo de acceso el ltimo que entra es el
primero que sale (llamado tambin LIFO 'Last Input First Output'). Como un ejemplo tpico
de su uso, Turbo C usa las pilas para poner los argumentos a las funciones. Solamente
existen dos operaciones bsicas que son push y pop (almacenar y sacar) que es usan en las
principales funciones.

Se requerirn las funciones poner_en_pila() y sacar_de_pila(), y como ejemplo, usaremos
las siguientes:

int *p; /*apuntar a una zona libre de memoria*/
int *cdp; /*apunta a la cima de la pila*/
int *fpd; /*apunta al fondo de la pila*/

/*poner un elemento en la pila*/
void poner(int i)
{
if(p>fpd) {
printf("la pila est llena\n");
return;
}
*p=1;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
p++;
}

/*tomar un elemento de la cima de la pila*/
quitar(void)
{
p--;
if(p<cdp) {
printf("lmite inferior de la pila sobrepasado\n");
return 0;
}
return *p;
}

Para ver cmo se hace una calculadora de cuatro funciones, utilizando pilas, se sugiere la
siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 6

2.4. Listas simplemente enlazadas

Una lista simplemente enlazada requiere que cada elemento de informacin contenga un
enlace al siguiente elemento de la lista. Cada elemento consiste normalmente e un registro
que contiene los campos de informacin y el puntero de enlace.

Hay dos caminos para construir una lista simplemente enlazada. El primero simplemente
aade cada nuevo elemento al principio o al final de la lista. El otro aade elementos en un
sitio especfico de la lista (por ejemplo, en orden ascendente). La manera en que la lista est
construida determina la forma de codificar la funcin de almacenamiento.

Para iniciar, se requiere definir una estructura de datos para guardar la informacin. Como
las listas de correos son comunes, se usa una en este ejemplo. La estructura se define aqu:

struct direccion {
char nombre[40];
char calle[40];
char ciudad[20];
char estado[3];
char cp[10];
struct direccion *siguiente;
} info;

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
La funcin almacenar_se() construir una lista simplemente enlazada poniendo cada nuevo
elemento al final. Se debe pasar un puntero a una estructura de tipo direccion, que contiene
la informacin de direccin de memoria de la ltima entrada en la lista. La funcin es:

void almacenar_se(struct direccion *i, struct direccion **ultimo)
{
if(*!ultimo) *ultimo=i; /*primer elemento de la lista*/
else (*ultimo) ->siguiente=i;
i->siguiente=NULL;
*ultimo=i;
}

La funcin almacenar_seo() insertar direcciones en la lista de correos en orden ascendente
segn el campo nombre. Tambin actualiza automticamente estos punteros cuando ocurre
un cambio.

/*almacenar en orden*/
void almacenar_seo(struct direccion *i, /*nuevo elemento para almacenar*/
struct direccion **primero, /*primero de la lista*/
struct direccion **ultimo) /*ltimo de la lista*/

{
struct direccion *viejo, *p;

p=*primero;
if(!*ultimo) { /*primer elemento de la lista*/
i->siguiente=NULL;
*ultimo=i;
*primero=i;
return;
}

viejo=NULL;
while(p) {
if(strcmp(p->, i->nombre)<0) {
viejo=p;
p=p->siguiente;
}
else {
if(viejo) { /*va en posicin intermedia*/
viejo->siguiente=1;
i->siguiente=p;
return;
}
i->siguiente=p; /*este es el nuevo primer elemento*/
*primero=i;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
return;
}
}
(*ultimo)->siguiente=i; /*se pone el ltimo*/
i->siguiente=NULL;
*ultimo=i;
}

En una lista enlazada es raro encontrar una funcin especfica, dedicada al proceso de
recuperacin, que devuelva un elemento tras otro en orden de lista.

Es un cdigo tan corto que simplemente se pone en otras rutinas, tales como buscar, borrar
o visualizar. Por ejemplo, esta rutina visualiza todos los nombres de la lista de correos:

void mostrar(struct direccion *principio)
{
while(principio) {
printf(principio->nombre);
principio=principio->siguiente;
}
}

Aqu principio es un puntero al primer elemento de la lista. Devolver elementos de la
cadena es tan simple como seguir la cadena. Se podra escribir una rutina de bsqueda
basada en el campo nombre como sigue:

struct direccion *buscar(struct direccion *principio; char *n)
{
while(principio) {
if(!strcmp(n,principio->nombre)) return principio;
principio=principio->prox;
}
return NULL; /*no se encuentra*/
}

Como buscar() devuelve un puntero al elemento de la lista que es igual al nombre buscado,
se debe declarar buscar() para devolver un puntero a un registro de tipo direccion. Si no se
encuentra, devuelve nulo.

El proceso de borrado de un elemento de una lista simplemente enlazada es directo. Como
en la insercin, hay tres casos: borrado del primer elemento, borrado de un elemento del
medio o del ltimo elemento.

Esta funcin borra un elemento dado de una lista de estructuras de tipo direccion.
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

void eliminarse (
struct direccion *p, /*elemento anterior*/
struct direccion *i, /*elemento que se va a borrar*/
struct direccion **primero, /*comienzo de la lista*/
struct direccion **ultimo); /*final de la lista*/

{
if(p) p->siguiente=i->siguiente;
else *primero=i->siguiente;
if(i==ultimo &p) *ultmo=p;
}

2.5. Listas doblemente enlazadas

Las listas doblemente enlazadas consisten en datos que estn ligados con el elemento que le
sigue y con el anterior. Una lista con dos enlaces tiene dos grandes ventajas. La primera es
que la lista se puede leer en las dos direcciones. Esto no slo simplifica la ordenacin de la
lista, sino que tambin, en el caso de las bases de datos, permite al usuario recorrer la lista
en dos direcciones. La segunda consiste en que, debido a que la lista entera se puede leer
con el enlace hacia atrs o hacia adelante, si se invalida un enlace, se puede reconstruir
utilizando otro.

Tres operaciones primarias se pueden realizar con una lista doblemente enlazada: insertar
un nuevo elemento primero, insertar en el centro o insertar al final.

Usando de nuevo el ejemplo de la lista de correos, se puede modificar la estructura
direccion como se muestra enseguida para adaptarla:

struct direccion {
char nombre[40];
char calle[40];
char ciudad[20];
char estado[3];
char cp[10];
struct direccion *siguiente;
struct direccion *anterior;
} info;

La funcin almacenar_de() construye una lista doblemente enlazada, utilizando la
estructura direccion como el elemento bsico de datos.


Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
void almacenar_deo(struct direccion *i;
struct direccion **ultimo)

{
if(!*ultimo) *ultimo=i; /*es el primer elemento de la lista*/
else (*ultimo)->siguiente=i;
i->siguiente=NULL;
i->anterior=*ultimo;
*ultimo=i;
}

En vez de ponerlo siempre al final, se puede tener una funcin que almacene cada elemento
en una posicin especfica de la lista que se est construyendo. La funcin almacenar_deo()
crea una lista que est ordenada en orden ascendente. El almacenamisnto es asignado
dinmicamente usando malloc().

/*crear una lista doblemente enlazada en orden*/
void almacenar_deo (
struct direccion *i, /*elemento nuevo*/
struct direccion **primero, /*primer elemento de la lista*/
struct direccion **ultimo) /*ultimo elemento de la lista*/

{
struct direccion *old,*p;
if(ultima==NULL) { /*primer elemento de la lista*/
i->prox=NULL;
i->prior=NULL;
ultima=i;
return i;
}
p=principio; /*comienzo de la lista*/
old=NULL;
while(p) {
if(strcmp(p->nombre,i->nombre)<0) {
old=p;
p=p->prox;
}
else {
if(p->prior) {
p->prior->prox=i;
i->prox=p;
i->prior=p->prior;
p->prior=i;
return principio;
}
i->prox=p; /*nuevo primer elemento*/
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
i->prior=NULL;
p->prior=i;
return i;
}
}
old->prox=i; /*pone al final*/
i->prox=NULL;
i->prior=old;
ultima=i;
return principio;
}

Cuando se elimina un elemento de una lista doblemente enlazada, hay tres casos a
considerar: borrar el primer elemento, eliminar uno del medio o el ltimo. La siguiente
funcin borra un elemento del tipo direccion de la lista doblemente enlazada:

void eliminar_de (
struct direccion *i, /*elemento que hay que borrar*/
struct direccion **primero, /*primer elemento*/
struct direccion **ultimo) /*ultimo elemento*/

{
if(i->prior) i->prior->prox=i->prox;
else { /*nuevo primer elemento*/
principio=i->prox;
/*si se borra slo un elemento de la lista*/
if(principio) principio->prior=NULL;
}
if(i->prox) i->prox->prior=i->prior;
return principio;
}

Para que se pueda observar con mayor detenimiento un programa sencillo de una lista de
direcciones postales que utiliza una lista doblemente enlazada, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 7

2.6. Arboles binarios

La cuarta estructura de datos es el rbol binario. Cuando stos estn ordenados, se prestan a
bsquedas, inserciones y borrados rpidos. Cada elemento del rbol binario consta de la
informacin con un enlace al miembro izquierdo y otro al derecho.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
La raz es el primer elemento del rbol. Cada elemento de datos se llama nodo. A cualquier
trozo de rbol se llama subrbol. Un nodo que no tiene subrboles conectados a l se llama
nodo terminal.

Hay tres formas de recorrer el rbol: inorden, preorden y posorden. Con inorden se visita el
subrbol izquierdo, la raz y el subrbol derecho. Con preorden se visita la raz y despus el
subrbol izquierdo y el derecho. Con posorden se visita el rbol izquierdo, el derecho y
luego la raz.

Aunque un rbol no necesita estar ordenado siempre, la mayora de las utileras lo
necesitan. Lo que constituye un rbol ordenado depende de cmo se recorrer. Los
ejemplos que usaremos, acceden al rbol en inorden.

a siguiente funcin llamada arbolA() construye un rbol binario ordenado.

struct arbol *arbolA (
struct arbol *raiz,
struct arbol *r,
char info)
{
if(!r) {
r=(struct arbol *) malloc(sizeof(struct arbol));
if(!r) {
printf("memoria agotada\n");
exit(0);
}
r->izquierda=NULL;
r->derecha=NULL;
r->info=info;
if(raiz) return r; /*primera entrada*/
else raiz->derecha=r;
return r;
}
if(info<r->info) arbolA(r,r->izquierda,info);
else
arbolA(r,r->derecha,info);
}


Para recorrer en inorden el rbol construido, usando arbolA() e imprimiendo el campo info
de cada nodo, se debera usar la funcin inorden() siguiente:

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
void inorden(struct arbol *raiz)
{
if(!raiz) return;

inorden(raiz->izquierda);
printf("%c",raiz->info);
inorden(raiz->derecha);
}

Para ver la forma en que se imprime un rbol, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 8

3. C y el 8086[8]

Esta parte no pretende ser un tutorial del lenguaje ensamblador del 8086/8088. Tampoco es
necesario que seamos expertos en lenguaje ensamblador, sino solamente entender qu es el
lenguaje ensamblador.

3.1. Bases

Los procesadores 8088 tienen 20 lneas para significar las direcciones. La forma de
simbolizarlos, se llama segmento:desplazamiento.

Formacin de direcciones. En el formato de segmeneto:desplazamiento, se maneja de la
siguiente manera:

direccin
B84F:0401
registro de segmento B84FH -> B84F0H
direccin de desplazamiento 0401H + 0401H
--------------------------------------------------------
direccin absoluta B88F1H

Una direccin absoluta puede ser expresada de varios modos en el formato
segmento:desplazamiento. Por ejemplo:

direccin 0050:0150
registro de segmento 0050H -> 00500H
direccin de desplazamiento 0150H + 0150H
--------------------------------------------------------
direccin absoluta 00650H

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
es equivalente a:

direccin 0005:0600
registro de segmento 0005H -> 00050H
direccin de desplazamiento 0600H + 0600H
--------------------------------------------------------
direccin absoluta 00650H


Sumario de registros

Hay 14 registros en el 8086. Estos pueden dividirse en cinco categoras
arbitrariamente nombradas:

1. Banderas
2. Propsito general o 'X': AX, BX, CX, DX
3. Apuntador: BP, IP, SP
4. Indice: SI, DI
5. Segmentacin: CS, DS, ES, SS

Las banderas

Algunos bits del registro bandera de 16 bits (tambin llamado la palabra de estado del
programa o PSW) reporta los resultados de operaciones lgicas o aritmticas.

Carry flag (bandera de acarreo). Carry es TRUE despus de que el resultado de una
operacin aritmtica es un acarreo del bit de mayor orden.

Parity flag (bandera de paridad). Esta bandera es TRUE si la suma de los 8 bits de menor
orden en una operacin aritmtica es impar.

Auxiliary carry flag (bandera de acarreo auxiliar). Es didntica a la bandera de acarreo,
excepto que refleja el acarreo del bit 3 en operaciones de 8 bits.

Zero flag (bandera de cero). Esta bandera es TRUE siempre que el resultado de una
operacin aritmtica sea cero.

Sign flag (bandera de signo). Esta es TRUE si en el resultado de una operacin aritmtica,
el bit de mayor orden es TRUE.

Trap flag (bandera de trampa). Cuando es TRUE, esta bandera pone al 8086 en un estado
especial de "debugging" que retorna el control del programa a una determinada localidad
despus de cada instruccin.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
Interrupt enable/disable flag (bandera de habilitar/deshabilitar interrupcin). Cuando esta
bandera es TRUE, el 8086 reconoce las interrupciones despus de completa la instruccin
actual.

Direction flag (bandera de direccin). Las instrucciones primitivas de cadena
automticamente incrementan o decrementan sus operandos de apuntador despus de cada
iteracin. Una bandera TRUE incrementa los operandos.

Overflow flag (bandera de sobreflujo). Es TRUE si hubo un acarreo dentro o fuera del bit
ms significativo. Es FALSE si hubo un acarreo dentro y fuera del bit ms significativo.

Propsito general (o grupo 'X')

Estos cuatro registros -AX, BX, CX, DX- son de 16 bits, pero pueden ser direccionados
separadamente como dos registros de 8 bits. Por ejemplo, AX pueden ser direccionados
como AL (el byte bajo) o AH (el bit alto).

AX: (A)ccumulator -acumulador-. Como el registro acumulador primario, el registro es
nico en cuatro modos: Primero, todas las operaciones de entrada/salida deben pasar a
travs del AX. Segundo, las instrucciones que involucran AX y datos inmediatos
usualmente requeren menos memoria de programa que con otros registros. Tercero, varias
de las poderosas instrucciones primitivas de cadena requieren que uno de los operandos
est en AX. Cuarto, AX contiene el operando ms bajo en las instrucciones de multiplicar y
dividir.

BX: (B)ase register -registro base-. BX es el nico registro 'X' que puede ser usado para
direccionar memoria indirecta.

CX: (C)ount -contador-. Algunas instrucciones del 8086 pueden ser iterativas; CX, que
contiene el nmero deseado de repeticiones, es automticamente decrementado despus de
cada iteracin.

DX: (D)ata -datos-. DX contiene la direccin del puerto de E/S en ciertos tipos de
instrucciones de entrada/salida.

Apuntador

SP: (S)tack (P)ointer -apuntador de pila-. Este registro siempre apunta a la localidad de
memoria conocida como pila. Las instrucciones de pila PUSH, POP, CALL, RET, mueven
datos hacia y desde la memoria de la direccin contenida en SP.

BP: (B)ase (P)ointer -apuntador de base-. Tambin llamado el apuntador de marco, se
provee para compensar los errores del 8086 en su indexado.

IP: (I)nstruction (P)ointer -apuntador de instruccin-. Este registro de 16 bits siempre
apunta a la prxima instruccin de programa a ser ejecutada.
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

Indice

Este grupo tiene tres usos. Primero, cada uno puede ser empleado como un apuntador de
propsito general. Segundo, pueden ser combinados con otros registros y/o valores.
Tercero, pueden ser usados como operandos en cualquier instruccin lgica o aritmtica.

SI: (S)ource (I)ndex -ndice fuente-.
DI: (D)estination (I)ndex -ndice destino-.

Segmentacin

Cuando se accede a una memoria, un registro de segmento provee los 16 bits de mayor
orden de la direccin de 20 bits. Esto es esencial para comprender que para cada instruccin
y para todo direccionamiento hay un segmento de registro por defecto.

CS: (C)ode (S)egment -segmento de cdigo-. CS es el registro de segmento por defecto
para todas las instrucciones que afectan la memoria de programa a travs del registro IP.
Esto significa que CS se agrega al IP para computar la direccin de la siguiente instruccin
de programa. Esta instruccin

jmp 1010

se entiende para significar

jmp CS:1010h

DS: (D)ata (S)egment -segmento de datos-. Excepto lo que se anot, toda referencia a
memoria de datos (en oposicin al programa o pila) usa DS para formar su direccin. La
instruccin

mov ax,label

Es interpretada como

mov ax,DS:label

ES: (E)xtra (S)egment -segmento extra-. ES es el registro de segmento por defecto en una
instruccin primitiva de cadena. Esto permite a una instruccin acceder a la meoria fuera
del apuntador de segmento. La instruccin

mov ax,ES:1010h

se referir a la memoria en 1010H desde el principio del segmento apuntado (64 k) por ES.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
SS: (S)tack (S)egment -segmento de pila-. Este es el registro de segmento por defecto para
todas las operaciones que involucren a SP o BP. Todas las operaciones de pila -PUSH,
POP, CALL, RET- se refieren a datos de 64 k direccionados por SS. La instruccin

mov ax,[bp+4]

se interpretar como

mov ax,SS:[bp+4]

Modos de direccionamiento de memoria

Hay tres modos principales de formar una direccin en el 8086:

1. Directo inmediato
2. Indirecto inmediato
3. Indirecto de registro

Para todas las instrucciones ejemplo de movimiento, el operando de la izquierda es el
destino y el operando de la derecha la fuente. Por ejemplo mov ax,bx mover el valor
en BX hacia AX. Similarmente, el operndo de la izquierda en instrucciones lgicas o
aritmticas contendrn el resultado de la operacin. Por ejemplo en la instruccin add ax,bx
Ax y BX sern agregadas y el resultado ser dejado en AX.

Directo inmediato. Este es el modo ms simple de direccionar memoria, meramente
especifica la localidad de memoria a ser direccionada. mov al,label mover el
contenido de la direccin de memoria label hacia el registro AL.

Indirecto inmediato. El direccionamiento indirecto implica que el operando contiene, no un
valor del dato, sino la direccin del valor del dato. Este modo es como el directo inmediato,
excepto que la localidad de memoria a ser direccionada se entiende que contiene la
direccin del operador final: jmp[wordlabel]. Este modo es muy limitado.

Indirecto de registro. En ensamblador, los corchetes alrededor de un operando de registro
son el smbolo de que la instruccin es una referencia de memoria. Por ejemplo, mov ax,bx
mver hacia AX el valor en BX, pero mov ax,[bx] mover hacia AX el valor de la localidad
de memoria contenida en BX. Hay dos categoras de direccionamiento indirecto de registro,
dependiendo de qu grupo de registros se usa.

-> Indirecto indexado. Este modo usa ya sea SI o DI en el grupo indexado para contener la
direccin del operando. Por ejemplo,

mov ax,[si]
mov ax,[di]

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
ambos cargan AX desde una direccin de memoria apuntada por el operando del registro
ndice.

-> Indirecto de base. Como su nombre implica, esta forma de direccionamiento usa ya sea
los registros "base", BP o BX. En todos los dems modos de direccionar, es idntico al
indirecto indexado:

mov ax,[bx] ;en segmento de datos
mov ax,[bp] ;en segmento de pila

-> Indirecto de base indexado. Este modo de direccionar forma una direccin agregando el
contenido de un registro base y el registro indexado:

mov ax,[bx+si] ;en segmento de datos
mov ax,[bp+di] ;en segmento de pila

-> Desplazamientos. En todos los modos de registro indirecto, puede ser agregada una
constante a los operandos. Todas las siguientes son direcciones legales:

mov ax,[di+5] ;Indexado con desplazamiento
mov ax,[bp+5] ;Base con desplazamiento
mov ax,[bx+si+5] ;De base indexado con desplazamiento

Las instrucciones condicionales JMP son particularmente ricas, correspondiendo con las
instrucciones de C. Basado en la expresin cmp ax,bx:

Operador de C Instrucciones condicionales JMP (Sinnimos)
ax = = bx je (jz)
ax ! = bx jne (jnz)
ax > bx ja (jnbe)
ax < bx jb (jnaee,jc)
ax > = bx jae (jnb,jnc)
ax < = bx jbe (jna)

La lista se muestra con mnemnicos para saltos condicionales sin signo.


3.2. El ensamblador de Microsoft

Los mdulos a que haremos referencia, usan el Ensamblador de mdulos de Microsoft,
versin 4.0.

El ensamblador contextual

El ensamblador de Intel utiliza mnemnicos contextuales: uso de una palabra clave para
cada operacin, y la misma palabra usada para diversas operaciones.
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
La idea aqu es que el ensamblador se supone como un rompecabezas para los
programadores basado en el contexto e el cual el mnemnico aparece. Para entender las
implicaciones de un dialecto contextual, consideremos las siguientes instrucciones:

mov al,bl ;direccionamiento del registro
mov [si],0 ;byte o palabra?
mov al,10 ;direccionamiento inmediato de dato
mov al,[DS:10] ;variable inmediata de memoria
mov al,mem ;mem es una etiqueta para la direccin de 10

son requeridas cinco distintas operaciones, y se usa un solo menmnico (MOV).

Especificadores de objeto primario

Un objeto en memoria tiene cuatro propiedades primarias: tamao, contenido,
desplazamiento y segmento. Por defecto, el ensamblador asume que una referencia a un
objeto es una referencia a su contenido. Otros tipos de referencia deben ser clarificadas al
ensamblador a travs de directivas de contexto

Directivas de tamao. El almacenamiento es localizado usando pseudo-operadores
de tamao como:

vara DB 0 ;"define byte" --8 bits de almacenamiento
varb DW 0 ;"define word" --16 bits de almacenamiento
varc DD 0 ;"define double word" --32 bits de almacenamiento

3.3. Interfaz con rutinas en lenguaje ensamblador

Cuando se escribe una rutina en lenguaje ensamblador, puede haber tres razones para ello:

- Para aumentar la velocidad y eficacia de la rutina
- Para realizar algunas funciones especficas de la mquina no disponibles en Turbo C
- Para usar rutinas proporcionadas por terceros

Hay dos formas de combinar rutinas en cdigo ensamblador con Turbo C. La primera es la
creacin, ensamblado y enlace de rutinas separadas en lenguaje ensamblador con funciones
en C. El segundo mtodo usa la extensin estndar de Turbo C, llamada asm, para incluir
en lnea las instrucciones de cdigo ensamblador directamente en funciones C.

Convenio de llamadas

Un convenio de llamadas es el mtodo por el que un compilador C pasa informacin a las
funciones y devuelve valores desde las funciones. Las soluciones normales usan los
registros internos de la CPU o la pila del sistema para pasar informacin entre las
funciones.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
Turbo C pasa argumentos a funciones en la pila. Estos se ponen en la pila de derecha a
izquierda. Es decir, dada la llamada

func(a,b,c);

se pone primero c, despus b y luego la a.

En el momento de entrar en un procedimiento en cdigo ensamblador, se deben guardar en
la pila los contenidos del registro BP y el valor actual del puntero de pila (SP) se debe
poner en BP. Los nicos registros que se deben preservar son SI y DI, si los usan en rutinas.

Antes de volver, la funcin en lenguaje ensamblador debe restaurar el valor de BP, SI y DI
y reponer el puntero de la pila. Si la funcin en lenguaje ensamblador devuelve un valor, se
pone en el registro AX si es un valor de 16 bits.

3.4. Creacin de una funcin en lenguaje ensamblador

El camino ms simple para aprender a crear funciones es ver cmo Turbo C genera cdigo
utilizando la opcin del compilador lnea de comando -S. Esta opcin provoca que salga un
listado en lenguaje ensamblador del cdigo que se genera.

Comencemos por el siguiente programa:

int suma(int a, int b);

int resultado;

main()
{
resultado=suma(10,20);
}

suma (int a, int b)
{
int t;
t=a+b;
return t;
}

La variable sum est declarada como global intencionalmente para ver ejemplos de datos
locales y globales. Si se llama "test" al programa, entonces la siguiente lnea crear
"test.asm"

c:\tc> tcc -S test

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
El contenido de "test.asm" es ste:

name test
_text segment byte public 'code'
dgroup group _bass,_data
assume cs:_text,ds:group,ss:dgroup
_text ends
_data segment word public 'data'
_d@ label byte
_data ends
_bss segment word public 'bss'
_b@ label byte
_bss ends
_text segment byte publis 'code'
_main proc near
;line 4
mov ax,20
push ax
mov ax,10
push ax
call near ptr _add
pop cx
pop cx
mov word ptr dgroup:_sum,ax
;line 5
@1:
ret
_main endp
_add proc near
push si
push bp
mov bp,sp
;line 9
;line 10
;line 11
;line 12
mov si,word ptr [bp+6]
add si,word ptr [bp+8]
;line 13
mov ax,si
@2:
;line 14
pop bp
pop si
ret
_add endp
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
_text ends
_bss segment word public 'bss'
public _sum
_sum label word
db 2 dup (?)
_bss ends
_data segment word public 'data'
s@ label byte
_data ends
_text segment byte public 'code'
public _add
public _main
_text ends
end

Una de las formas ms fciles para escribir nuestras funciones en lenguaje ensamblador, es
generar un esqueleto. Por ejemplo, supongamos que sea necesario hacer una rutina para
multiplicar dos enteros. Para generar un esqueleto, hay que crear un archivo que contenga
la siguiente funcin:

mul (int a, int b)
{
}

Despus, compilarlo con la opcin -S para que se produzca un archivo en lenguaje
ensamblador. El archivo sera:
name mul
_text segment byte public 'code'
dgroup group _bss,_data
assume cs:_text,ds:group,ss:dgroup
_text ends
_data segment word public 'data'
_d@ label byte
_data ends
_bss segment word public 'bss'
_b@ label type
_bss ends
_text segment byte public 'code'
_mul proc near
push bp
mov bp,sp
@1:
pop bp
ret
_mul endp
_text ends
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
_data segment word public 'data'
_s' label
_data ends
_text segment byte public 'code'
public _mul
_text ends
end


En este esqueleto, el compilador ha hecho todo el trabajo de definir los segmentos
adecuados y establecer la pila y los registros. Lo que se tiene que hacer es entrar en los
detalles. Para ver la funcin mul() acabada, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 9

Una vez ensamblado, el cdigo en ensamblador se puede enlazar a cualquier programa, por
ejemplo:

#include <stdio.h>
main()
{
printf("%d", mul(2,5));
}

4. Parmetros del sistema de disco

Hay cinco caratersticas importantes acerca de un disco:

1. Las caractersticas fsicas del disco: el medio (floppy, fijo, etc.), el nmero de lados y
el nmero de sectores por pista.
2. El nmero de sectores encontrados en un bloque de localidad de memoria. Un bloque
de localidad de memoria es una cantidad mnima de espacio de disco que puede ser
localizada. Dependiendo de las caractersticas fsicas del disco, un archivo de 1 byte
puede ocupar tanto como 512 bytes de espacio.
3. El nmero de bytes contenidos por el sector fsico.
4. El nmero total de celdas en un disco.
5. El nmero de celdas "libres" o sin usar.

El tamao total del disco puede ser calculado por:

total de bytes = (bytes/sector) * (sectores/celda) * (total de celdas)

La diferencia fundamental de las funciones DOS y las que se han mencionado
anteriormente, yace en el nmero de argumentos a ser regresados por la funcin. getmod y
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
setmod solamente retornan un valor. En contraste, la funcin dskparms que ser escrita
regresa cuatro valores. Pero C solamente acepta un valor de retorno.

Una solucin al conflicto mencionado es escribir por separado cinco funciones, cada una de
la cual devolver su propio valor. Las cinco llamadas, contendrn entonces la informacin
completa del disco.

Declaracin de la estructura dskdata

Ya hemos listado la informacin que se requiere obtener del DOS, asumiremos que la
declaracin de esta estructura, reside en la cabecera STRUCT.H; la estructura ser la
siguiente:

struct dskdata
{
UCHAR mdsb;
unsigned freeclust;
unsigned totclust;
unsigned bytes_sect;
unsigned sect_clust;
};

Una rutina en lenguaje ensamblador puede tomar precisamente el tamao adecuado si
conoce el desplazamiento de cada miembro desde el comienzo de la estructura. Nosotros
podemos escribirlo en el archivo de cabecera EQUATES.H

MDB EQU 0 ;1 byte (UCHAR)
FREECLUST EQU 1 ;2 bytes (unsigned)
TOTALCLUST EQU 3 ;2 bytes (unsigned)
BYTES_CLUST EQU 5 ;2 bytes (unsigned)
SECT_CLUST EQU 7 ;2 bytes (unsigned)

Podemos hacer el cdigo ms general si definimos los desplazamientos de pila con
comandos EQU; estas definiciones no slo agregan portabilidad al codigo, sino que hacen
el significado ms claro. Por ejemplo, en lugar de mov ax[bp+4], escribiremos mov
ax[bp+arg0]. Estas definiciones, se debern agregar al archivo de cabecera PROGSEG.H:

ARG0 EQU 4 ;desplazamiento del primer argumento de la pila
ARG1 EQU 6 ;...segundo...
ARG2 EQU 8 ;...etc.
ARG3 EQU 10
ARG4 EQU 12
ARG5 EQU 14
ARG6 EQU 16

La rutina en lenguaje ensamblador para encontrar los parmetros de disco ser:
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

DSK_PARAMS_DOS EQU 1CH ;parmetros generales del medio
SPACE_LEFT_DOS EQU 36H ;espacio en el disco restante

INCLUDE EQUATES.H

INCLUDE PROGSEG.H
EXTRN ucase: NEAR ;busca en otro mdulo el ucase
PUBLIC dskparms dskparms
PROC NEAR

0 push bp
1 mov bp,sp
2 push si
3 mov dx,[bp+ARG1] ;saca de la pila de DX la letra de la lectora
4 push dx ;lo pone en la pila donde ucase lo espera
5 call ucase ;lo hace mayscula en la pila
6 pop dx ;lo devuelve de la pila hacia DX
7 sub dx,"@" ;obtiene el caracter del ASCII a la pila
8 mov [bp+ARG1],dx ;pone el drive en la pila para uso posterior
9 mov ah,DSK_PARAMS_DOS ;nmero de funcin DOS
10 push ds ;retorna el valor DOS y cambia registro ds
11 int 21h ;llama al MS-DOS
12 cmp al,0ffh ;ff=mal nmero de drive
13 mov al,BYTE PTR [bx] ;obtiene el descriptor_byte en caso de no error
14 pop ds ;obtiene de nuevo antiguo segmento de dato
15 jne drvok ;pila=bien, segmento=bien, regresa o.k.
16 mov ax,BAD_DRIVE ;regresa cdigo de error de DOS
17 jmp dpexit
drvok:
18 mov si,[bp+ARG0] ;pone apuntador de estructura fuera de pila
19 mov [si+MDB],al ;pone MDB en al, pone el byte en la estructura
;---------- ahora obtiene el resto de los parmetros
20 mov dx,[bp+ARG1] ;pone la letra de drive fuera de pila
21 mov ah,SPACE_LEFT_DOS ;prepara para prxima llamada DOS
22 int 21h ;llama al MS-DOS
;
23 mov [si+FREECLUST],bx ;instala valores en la estructura
24 mov [si+TOTALCLUST],dx
25 mov [si+BYTES_CLUST],cx
26 mov [si+SECT_CLUST],ax
27 mov ax,0 ;regresa cdigo de xito
dpexit:
28 pop si
29 pop bp
30 ret
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
;
dskparms ENDP
PUBLIC ucase
ucase PROC NEAR
;
31 push bp
32 mov bp,sp
33 cmp BYTE PTR [bp+ARG0],'a' ;revisa lmite inferior
34 jc ucexit ;sale si es menor que 'a'
low_ok:
35 cmp BYTE PTR [bp+ARG0],'z' ;revisa lmite superior
36 ja ucexit ;sale si superior a 'z'
hi_ok:
37 sub BYTE PTR [bp+ARG0],20h ;lo hace mayscula
ucexit:
38 pop bp
39 ret
;
ucase ENDP
INCLUDE ENDPSEG.H
END

Para ver un programa en TC que despliegue las caractersticas totales del disco, se sugiere
la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 10


5. Hora y fecha

Existen cuatro formas de expresar la hora y la fecha en el MS-DOS:

El directorio de disco: Contiene una entrada para cada archivo del disco. Cada entrada
contiene la fecha y hora en que el archivo fue creado o modificado (actualizado). La hora y
fecha son almacenadas como palabras empacadas de bits.

Funciones de archivo del DOS: Leer o poner la hora y fecha en una entrada de archivo en
un directorio.

Llamadas a funciones del DOS de conservacin de hora: Leer o poner el da y la hora de un
calendario y reloj del sistema.

El BIOS de la ROM: contiene las rutinas que dan servicio al interruptor del temporizador
(nmero 8).
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

La hora y fecha en una entrada de directorio no est disponible para ser leda o escrita
directamente. Sin embargo, el DOS lo permite mediante la funcin 57H que tiene el
siguiente contenido:

Registros en la entrada
AH 57H
AL 0 si se obtiene, 1 si se pone
DX Fecha
CX Hora
BX Manejador de archivo

Registros en la salida
AX Cdigo de error si existe la bandera de acarreo
DX Fecha
CX Hora

Una rutina para manejar fecha y hora de un archivo es la funcin getstamp, que provee una
interface comn sobre las funciones que la modifican, por ejemplo, al cerrar un archivo, la
hora y fecha que se ponen son las actuales, y no las originales, por lo que las rutinas
siguientes, permitirn realizar esta funcin. La funcin getstamp obtiene la fecha y hora
originales del archivo:

FILE_STAMP_DOS EQU 57H
TIME EQU 1
FETCH EQU 0
;FD_ADJUST EQU ??
;----- poner en EQUATES.H ---------

INCLUDE EQUATES.H

INCLUDE PROGSEG.H
PUBLIC getstamp

getstamp PROC NEAR
;

push bp
mov bp,sp
;;--------------------------------------------------------------------------
;; Ajustar BX de acuerdo a cmo tu compilador convierte los manej. de archivo
;;--------------------------------------------------------------------------
mov bx,0 ;Manejadores de archivo menores que 100
mov b1,[bp+ARG0] ;Saca un byte nico fuera de la pila
add bx,FD_ADJUST ;Agrega diferencia entre FD y FH
;;--------------------------------------------------------------------------
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
;; ... Descriptores de archivo
;;--------------------------------------------------------------------------
mov ah,FILE_STAMP_DOS ;Funcin DOS 57H
mov al,FETCH ;Modo de obtencin
int 21h ;Llamada al MS-DOS
not ax ;Hace el cdigo de retorno negativo
jc gfsexit
mov ax,cx ;Mueve el tiempo hacia AX
cmp BYTE PTR[bp+ARG1],TIME ;Revisa el modo de TIME en pila
jz gfsexit ;si funciona, salir, si no ...
mov ax,dx ;... por defecto, regresa DATE
and ah,7fh ;limita fecha mxima al 2043
gfsexit:
pop bp
ret
gestamp ENDP
INCLUDE ENDPSEG.H
END

La funcin putstamp pone al archivo hora y fecha, y es la siguiente:

FILE_STAMP_DOS EQU 57H
SET EQU1

INCLUDE PROGSEG.H
PUBLIC putstamp
putstamp PROC NEAR
;
push bp
mov bp,sp
;;--------------------------------------------------------------------------
;; ajusta BX de acuerdo a los convertidores de archivo del compilador
;;--------------------------------------------------------------------------
mov bx,0 ;manejadores menor que 100
mov b1,[bp+ARG0] ;saca un byte nico de la pila
add bx,FD_ADJUST ;agrega la diferencia entre FD y FH
;;--------------------------------------------------------------------------
;; ... descriptores de archivos
;;--------------------------------------------------------------------------
mov dx,[bp+ARG1] ;obtiene fecha-a-poner de la pila
mov cx,[bp+ARG2] ;obtiene hora-a-poner de la pila
mov ah,FILE_STAMP_DOS ;funcin 57H del DOS
mov al,SET ;modo poner
int 21h ;llama al DOS
jc sfdexit ;sale con cdigo de error en AX
mov ax,0 ;si no, regresa nulo
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
sfdexit:
pop bp
ret
putstamp ENDP
INCLUDE ENDPSEG.H
END

Un programa completo que cambia la hora y fecha de un archivo, se encontrar
realizando la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 11

6. Grficos

Antes de usar cualquiera de las funciones grficas de TC es preciso poner un adaptador de
video en uno de los modos grficos, usando la funcin initgraph(), que tiene el prototipo

void far initgraph(int far *controlador, int far *modo, char far *camino);

Carga un controlador de grficos en memoria que corresponde al nmero indicado por
controlador. El parmetro modo indica un nmero entero que especifica el modo de video
usado por las funciones grficas. Por ltimo, se puede especificar un camino al controlador.

Los controladores de grficos se encuentran contenidos en archivos .BGI.

Los valores de controlador vlidos son:

Macro Equivalente
DETECT 0
CGA 1
MCGA 2
EGA 3
EGA64 4
EGAMONO 5
IBM8514 6
HERCMONO 7
ATT400 8
VGA 9
PC3270 10

Cuando se utiliza DETECT, initgraph() detecta automticamente el tipo de hardware de
video presente en el sistema y establece controlador y modo en sus valores correctos.

La estructura viewporttype se define en graphics.h como sigue:
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

struct viewporttype {
int left, top, right, bottom;
int clipflag;
}

Los campos left, top, right y bottom contienen las coordenadas de los extremos superior
izquierdo e inferior derecho de la ventana de grficos.

Las funciones fundamentales para el trazado de grficos son las que dibujan un punto, una
lnea y un crculo. En TC, estas funciones son llamadas putpixel(), line() y circle(),
respectivamente. Sus prototipos son:

void far putpixel(int x, int y, int color);
void far line(int iniciox, int inicioy, int finx, int finy);
void far circle(int x, int y, radio);

Se puede establecer el color del dibujo aplicable usando setcolor() cuyo prototipo es:

void far setcolor(int color);

Se puede rellenar cualquier figura cerrada usando la funcin floodfill(). Su prototipo es:

void far floodfill(int x, int y, int color_borde);

Los modelos de relleno son los siguientes:

Macros Valor Significado
EMPTY_FILL 0 Relleno con color de fondo
SOLID_FILL 1 Relleno con color slido
LINE_FILL 2 Relleno con lneas
LTSLASH_FILL 3 Relleno con el smbolo"|", poco denso
SLASH_FILL 4 Relleno con el smbolo "|"
BKSLASH_FILL 5 Relleno con el smbolo "/"
LTBKSLASH_FILL 6 Relleno con el smbolo "/", poco denso
XHATCH_FILL 8 Relleno con rayado
INTERLEAVE 9 Relleno con superposicin
WIDEDOT_FILL 10 Relleno con puntos ampliamente espaciados
CLOSEDOT_FILL 11 Relleno con puntos muy poco espaciados
USER_FILL 12 Relleno con modelos personalizados

Para ver un programa completo de construccin de grficos de tarta a partir de datos
introducidos por el usuario, se sugiere la siguiente


Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
Actividad:

>> Desarrollar en TC el programa ejemplo No. 12

Otra funcin de TC crea barras que pueden ser utilizadas para desarrollar grficos de
barras. Esta funcin es llamada bar() y su prototipo es:

void far bar(int izquierda, int arriba, int derecha, int abajo);

La funcin bar() dibuja una barra rectangular que tiene su extremo superior izquierdo
definido por izquierda, arriba y su extremo inferior derecho por derecha, abajo.

Puede verse un programa que solicite al usuario el nmero de entradas, introducir la
informacin y calcular el factor de normalizacin. Por ltimo, visualizar una representacin
en grfico de barras de los datos usando barras verticales.

El factor de normalizacin hace dos tareas:

1. Comprueba que la barra ms grande cabe en la pantalla.

2. Asegura que se use la altura de toda la pantalla.

Para ver el citado programa, se sugiere la siguiente

Actividad:

>> Desarrollar en Tc el programa ejemplo No. 13

Se pueden tambin crear grficos de barras tridimensionales usando bar3d() que tiene el
prototipo:

void far bar3d(int izquierda, int cima, int derecha, int abajo, int prof, int indicadorsup);

Uso de getimage() y putimage()

La funcin getimage() se usa para copiar una regin de grficos en una memoria intermedia
(buffer). La funcin putimage() pone el contenido de una memoria intermedia en la
pantalla. Tiene los prototipos

void far getimage(int izquierda, int cima, int derecha, int abajo, void far
*buf);
void far putimage(int izquierda, int cima, void far *buf, int op);

La funcin getimage() copia el contenido de una porcin rectangular de la pantalla, definida
por sus coordenadas superior izquierda e inferior derecha, en la memoria intermedia
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
apuntada por buf. Use putimage() para visualizar una memoria intermedia de datos grficos
almacenados previamente con getimage().

El valor de op determina exactamente cmo se escribe la imagen en la pantalla. Sus valores
vlidos enumerados (encontrados en graphics.h) son:

Nombre Valor Significado
COPY_PUT 0 Sobreescribir el destino
XOR_PUT 1 OR-exclusivo con destino
OR_PUT 2 OR-inclusivo con destino
AND_PUT 3 AND con destino
NOT_PUT 4 Invertir la imagen fuente

El tamao de la memoria intermedia, para una regin de terminada,en bytes se proporciona
por la funcin imagesize(). Se debe usar esta funcin en vez de intentar calcular
manualmente el espacio necesario, ya que imagesize() proporciona el valor correcto con la
independencia del modo de video que est en uso. Su prototipo es:

unsigned far imagesize(int izqueirda, int cima, int derecha, int abajo);

Para ver un programa que demuestra las funciones getimage(), imagesize() y putimage(),
que llena de blanco toda la pantalla, crea un rectngulo, lo rellena, dibuja dos lneas
diagonales; despus copia el rectngulo usando, primero COPY_PUT y despus XOR_PUT
se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 14

Salida de texto en modo grfico

Aunque las funciones estndar de texto de TC como printf() pueden usarse en la mayora de
los modos grficos, no son la alternativa ms flexible. Para aprovechar al mximo el
entorno grfico de TC ser necesario usar las funciones de salida de texto en modo grfico
descritas en esta seccin.

La funcin que saca el texto a la ventana grfica es outtext(), y su prototipo es:

void far outtext(char *cad);

Esta funcin saca la cadena apuntada por cad a la posicin aplicable. (En el modo grfico
no hay cursor visible, pero la posicin aplicable en la pantalla se mantiene como si hubiera
un cursor invisible).

Para cambiar el estilo, tamao o direccin de la salida de texto obtenida con outtext(), se
usa settextstyle() cuyo prototipo es:
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

void far settextstyle(int tipo, int direccion, int tamaocar);

El parmetro tipo determina el tipo de juego de caracteres usados. Por omisin, es un tipo
de mapas de 8x8 bits. Se puede dar a tipo uno de los siguientes valores:

Tipo(font) Valor Significado
DEFAULT_FONT 0 Tipo de 8x8 de mapas de bits
TRIPLEX_FONT 1 Tipo triplex strocked
SMALL_FONT 2 Tipo strocked pequeo
SANS_SERIF_FONT 3 Tipo strocked sin serif
GOTHIC_FONT 4 Tipo gtico strocked

La direccin en que se visualiza el texto, izquierda a derecha o de abajo hacia arriba, se
determina por el valor de direccin, que puede ser, o bien HORIZ_DIR (o cero) o
VERT_DIR (o uno).

El parmetro tamaocar es un multiplicador que aumenta el tamao del caracter. Puede
tener un valor de 0 a 10.

Para ver un programa que muestre el uso de la funcin settextstyle() y muestre cada juego
de caracteres en varios tamaos. se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 15

Cuando se cambia el tamao del tipo (font) de mapas de 8x8 bits, sus dimensiones son
multiplicadas por el valor de tamaocar. Es decir, si tamaocar es 2, los caracteres
asignados a los bits sern dibujados en un cuadro de 16x16 pixels. Sin embargo, al
teclearlos, ser espaciado proporcionalmente. Para determinar la altura y anchura de los
caracteres se usan las funciones textheight() y textwidth() respectivamente. Sus prototipos
son:

int far textheight(char far *cad);
int far textwidth(char far *cad);

Estas funciones proporcionan la altura y anchura, en pixels, de las cadenas indicadas por
cad.

Otro detalle importante acerca de outtext() es que no procesa caracteres de nueva lnea. No
hay modo de hacer un retorno de carro o un salto de lnea. Para poner un texto en una
posicin especfica de la ventana, se usa la funcin outtextxy(), cuyo prototipo es:

void far outtextxy(int x, int y, char *cad);

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
La cadena ser escrita en las coordenadas especficas de la ventana. Si x o y o ambos estn
fuera de rango, no se visualizar ninguna salida.

Para analizar un porograma que presente un mensaje mvil de letras grandes en la pantalla,
trasladndose de derecha a izquierda, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 16

Cambio del estado de lnea

Turbo C permite cambiar la forma en que se dibuja una lnea. Todas las lneas son slidas
por omisin, pero se puede especificar de puntos, de trazos contiguos, de puntos y trazos
continuos o personalizados. Para cambiar la forma que se dibujan las lneas, se utiliza
setlinestyle(), cuyo prototipo es:

void far setlinestyle(int estilo, unsigned modelo, int anchura);

El elemento estilo contiene el estilo de la lnea. Ser uno de los siguientes valores
enumerados:

Valor Significado
SOLID_LINE Lnea continua
DOTTED_LINE Lnea de puntos
CENTER_LINE Lnea de punto centrado (guin-punto-guin)
DASHED_LINE Lnea de trazos continuos
USERBIT_LINE Lnea definida por el usuario

El elemento espesor tendr uno de los valores siguientes:

Valor Significado
NORM_WIDTH Anchura de 1 pixel
THICK_WIDTH Anchura de 3 pixels

Para ver un programa que presenta una lnea de cada uno de los estilos incorporados de TC
y en un estilo personalizado, se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 17

Creacin de un modelo de relleno personalizado

Aunque TC proporciona varios modelos interesantes de relleno, incluyendo el entramado, a
veces es til poder definir unos modelos de relleno personalizados, que pueden dar a las
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
presentaciones grficas un aspecto caracterstico. Para crear un modelo de relleno, se usa
setfillpattern(), cuyo prototipo es:

void far setfillpattern(char far *modelo, int color);

Una forma interesante de crearlo, es utilizando un generador de nmeros aleatorios.

Para ver un programa que genera un nuevo modelo de relleno cada vez que se ejecute, se
sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 18

Las funciones drawpoly() y fillpoly()

Se puede dibujar cualquier polgono de forma singular utilizando la funcin drawpoly() de
Tc cuyo prototipo es:

void far drawpoly(int numpuntos, int far *puntos);

El parmetro numpuntos especifica el nmero de vrtices del polgono; puntos, tiene que
ser al menos dos veces mayor que el nmero de puntos.

Se puede rellenar un polgono con el color de relleno y modelo aplicables usando fillpoly(),
cuyo prototipo es:

void far fillpoly(int numpuntos, int far *puntos);

Para que quede entendido mejor an lo anterior, es preferible ver el programa que carga un
array con 500 vrtices generados aleatoriamente, dibuja el polgono y lo rellena, un nuevo
polgono cada vez que se ejecuta, y para esto se sugiere la siguiente

Actividad:

>> Desarrollar en TC el programa ejemplo No. 19

7. Librera de programas

/*****PROG01.C*****/
/* Controlador de ordenacin*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void burbuja(char *elemento, int contador);
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

main()
{
char s[80];

printf("introducir una cadena:");
gets(s);
burbuja(s,strlen(s));
printf("la cadena ordenada es: %s\n",s);
return 0;
}

/*****PROG02.C*****/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

/*este programa muestra cunto tarda cada uno de los seis algoritmos de
ordenacin para ordenar 2000 elementos.
*/

void burbuja(char *elemento, int contador);
void sacudida(char *elemento, int contador);
void seleccion(char *elemento, int contador);
void insertar(char *elemento, int contador);
void shell(char *elemento, int contador);
void br(char *elemento, int izquierda, int derecha);
void rapida(char *elemento, int contador);

main()
{
char s[2001], temp[2001];
register int i;
time_t principio, fin;

/*se genera una cadena de caracteres al azar */
for(i=1;1<2000;1++) temp[i]=(char) (rand()%26) + 'A';

temp[2000]='\0';

strcpy(s,temp);
principio=time('\0');
burbuja(s,strlen(s));
fin=time('\0');
printf("La ordenacin por burbuja necesit %ld segundos.\n", fin-principio);
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

strcpy(s,temp);
principio=time('\0');
sacudida(s,strlen(s));
fin=time('\0');
printf("La ordenacin por sacudida necesit %ld segundos.\n", fin-
principio);

strcpy(s,temp);
principio=time('\0');
seleccion(s,strlen(s));
fin=time('\0');
printf("La ordenacin por seleccion necesit %ld segundos.\n", fin-
principio);

strcpy(s,temp);
principio=time('\0');
insertar(s,strlen(s));
fin=time('\0');
printf("La ordenacin por insercion necesit %ld segundos.\n", fin-
principio);

strcpy(s,temp);
principio=time('\0');
shell(s,strlen(s));
fin=time('\0');
printf("La ordenacin por shell necesit %ld segundos.\n", fin-principio);

strcpy(s,temp);
principio=time('\0');
rapida(s,strlen(s));
fin=time('\0');
printf("La ordenacin rpida necesit %ld segundos.\n", fin-principio);
return 0;

}

/*ordenacin por el mtodo de la burbuja*/
void burbuja(char *elemento, int contador)
{
register int a,b;

register char t;

for(a=1;a<contador;++a)
for(b=contador-a;b>=1;--b) {
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
if(elemento[b-1] > elemento[b]) {
/*se intercambian los elementos*/
t=elemento[b-1];
elemento[b-1]=elemento[b];
elemento[b]=t;
}
}
}

/*ordenacin por sacudida*/
void sacudida(char *elemento, int contador)
{
register int a,b,c,d;
char t;
c=1;
b=contador-1; d=contador-1;

do {
for(a=d;a>=c;--a) {
if(elemento[a-1]>elemento[a]) {
t=elemento[a-1];
elemento[a-1]=elemento[a];
elemento[a]=t;
b=a;
}
}
c=b-1;
for(a=c;a<d+1;++a) {
if(elemento[a-1]>elemento[a]) {
t=elemento[a-1];
elemento[a-1]=elemento[a];
elemento[a]=t;
b=a;
}
}
d=b-1;
} while(c>=d);
}

/*ordenacin por seleccin*/
void seleccion(char *elemento, int contador)
{
register int a,b,c;
char t;


Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
for(a=0;a<contador-1;++a) {
c=a;
t=elemento[a];
for(b=a+1;b<contador;++b) {
if (elemento[b]<t) {
c=b;
t=elemento[b];
}
}
elemento[c]=elemento[a];
elemento[a]=t;
}
}

/*ordenacin por insercin*/
void insertar(char *elemento, int contador)
{
register int a,b;
char t;

for(a=1;a<contador-1;++a) {
t=elemento[a];
b=a-1;
while(b>=0&&7<elemento[b]) {
elemento[b+1]=elemento[b];
b--;
}
elemento[b+1]=t;
}
}

/*ordenacin en shell*/
void shell(char *elemento, int contador)
{
register int i,j,k,s,w;
char x, a[5];

a[0]=9; a[1]=5; a[2]=3; a[3]=2; a[4]=1;

for(w=0;w<5;w++) {
k=a[w]; s=-k;
for(i=k;i<contador;++i) {
x=elemento[i];
j=i-k;
if(s==0) {
s=-k;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
s++;
elemento[s]=x;
}
while(x<elemento[j]&&j>=0&&j<=contador) {
elemento[j+k]=elemento[j];
j=j-k;
}
elemento[j+k]=x;
}
}
}

/*funcin de preparacin para ordenacin rpida*/
void rapida(char *elemento, int contador)
{
br(elemento,0,contador-1);
}

/*ordenacin rpida*/
void br(char *elemento, int izquierda, int derecha)
{
register int i,j;
char x,y;

i=izquierda; j=derecha;
x=elemento[(izquierda+derecha)/2];

do {
while(elemento[i]<x&&i<derecha) i++;
while(x<elemento[j]&&j>izquierda) j--;
if(i<=j) {
y=elemento[i];
elemento[i]=elemento[j];
elemento[j]=y;
i++; j--;
}
} while(i<=j);
if(izquierda<j) br(elemento,izquierda,j);
if(j<derecha) br(elemento,i,derecha);
}

/*****PROG03.C*****/
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include stdlib.h>
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
#include <time.h>

void br(char *elemento, int izquierda, int derecha);
void rapida(char *elemento, int contador);

int cmp(char*, char*);

main()
{
char s[5001], temp[5001];
register int i;
time_t principio,fin;

/*se genera una cadena de caracteres al azar*/
for(i=0;i<5000;i++) temp[i]=(char) (rand()%26) + 'A';
temp[5001]='\0';
strcpy(s,temp);
principio=time('\0');
rapida(s,strlen(s));
fin=time('\0');
printf("la ordenacin rpida tard %ld segundos. Pulse una
tecla\n",fin-principio);
getch();
printf("%s\n",s);

strcpy(s,temp);
principio=time('\0');
qsort(s,strlen(s),1,cmp);
fin=time('\0');
printf("La ordenacin qsort() tard %ld segundos. Pulse una
tecla\n",fin-principio);
getch();
printf("%s\n",s);
return 0;
}

/*funcin para preparar la ordenacin rpida*/
void rapida(char *elemento, int contador)
{
br(elemento,0,contador-1);
}

/*ordenacin rpida*/
void br(char *elemento, int izquierda, int derecha)
{
register int i,j;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
char x,y;

i=izquierda; j=derecha;
x=elemento[(izquierda+derecha)/2];

do {
while(elemento[i]<x&&j<derecha) i++;

while(x<elemento[j]&&j>derecha) j--;

if (i<=j) {
y=elemento[i];
elemento[i]=elemento[j];
elemento[j]=y;
i++; j--;
}
} while (i<=j);
if(izquierda<j) br(elemento,izquierda,j);
if(i<derecha) br(elemento,i,derecha);
}
cmp(char *a, char *b)
{
return *a - *b;
}

/*****PROG04.C*****/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#define MAX 100

char *p[MAX], *sacar_de_cola(void);
int pos_a;
int pos_a;
void introducir(void), almacenar_en_cola(char *cola), revisar(void),
borrar(void);

main() /*planificador de tareas*/
{
char s[80];
register int t;

for(t=0;t<MAX;t++) p[t]=NULL; /*se pone a cero la lista*/
pos_s=0; pos_a=0;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

for(;;) {
printf("Introducir, Listar, Eliminar, Salir : ");
gets(s);
*s=toupper(*s);

switch(*s) {
case 'I':
introducir();
break;
case 'L':
revisar();
break;
case 'E':
borrar();
break;
case 'S':
exit(0);
}
}
}

/*introducir citas en la cola*/
void introducir(void)
{
char s[256], *p;

do {
printf("introducir la cita %d: ", pos_s+1);
ghets(s);
if(*s==0) break; /*no se hace entrada*/
p=malloc(strlen(s));
if(!p) {
printf("no hay memoria! \n");
return;
}
strcpy(p,s);
if(*s) almacenar_en_cola(p);
} while(*s);
}

/*ver lo que hay en la cola*/
void revisar(void)
{
register int t;
for(t=pos_a;t<pos_s;++t)
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
printf("%d. %s\n",t+1, p[t]);
}

/*borrar una cita de la cola*/
void borrar(void)
{
char *p;

if((p=sacar_de_cola()))==NULL return;
printf("%s\n",p);
}

/*almacenar una cita*/
void almacenar_en_cola(char *cola)
{
if(pos_s==MAX) {
printf("la cola est llena\n");
return;
}
p[pos_s]=cola;
pos_s++;
}

/*sacar una cita*/
char *sacar_de_cola()
{
if(pos_a==pos_s) {
printf("no quedan (mas) citas.\n");
return NULL;
}
pos_a++;
return p[pos_a-1];
}

/*****PROG05.C*****/
/*ejemplo de cola circular empleando un buffer del teclado
*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

#define MAX 80

char buf[MAX+1];
int pos_a=0;
int pos_s=0;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

void almacenar_en cola(char *cola);
void sacar_de_cola(void);

main()
{
register char car;
int t;

buf[80]=NULL;

/*no se aceptan caracteres hasta que se teclee ctrl-z*/
for(car=' ',t=0;t<32000&&car!=26;++t) {
if(kbhit()) {
car=getch();
almacenar_en_cola(car);
}
printf("%d ",);
if(car==';') /*se muestra y vaca el buffer*/
while((car=sacar_de_cola())!=NULL) putchar(car);
}
return 0;
}

/*almacenar caracteres en la cola*/
void almacenar_en_cola(char *cola)
{
/*la cola est llena o el pos_a=pos_s -1 */
if(pos_a+1==pos_s||(pos_a+1==MAX&&!pos_a)) {
printf("lista llena\n");
return;
}
buf[pos_a]=cola;
pos_a++;
if(pos_a==MAX) pos_a=0; /*vuelve a empezar*/
}

/*sacar un caracter*/
char sacar_de_cola(void)
{
if(pos_s==MAX) pos_s=0; /*vuelve a empezar*/
if(pos_s==pos_a) {
return NULL;
}
pos_s++;
return buf[pos_s-1];
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
}

/*****PROG06.C*****/
/*Calculadora sencilla con las cuatro reglas*/
#include <stdio.h>
#include <alloc.h>
#include <stdlib.h>
#define MAX 100

int *p;
int *cdp;
int *fdp;
void poner(int i);
int quitar(void);

main()
{
int a,b;
char s[80];

p=(int *) malloc(MAX*sizeof(int)); /*obtener memoria para la pila*/
if(!p) {
printf("fall al reservar memoria\n");
exit(1);
}
cdp=p;
fdp=p+MAX-1;
printf("Calculadora con las cuatro reglas\n");
do {
printf(": ");
gets(s);
switch(*s) {
case '+':
a=quitar();
b=quitar();
printf("%d\n",a+b);
poner(a+b);
break;
case '-':
a=quitar();
b=quitar();
printf("%d\n",b-a);
poner(b-a);
break;
case '*':
a=quitar();
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
b=quitar();
printf("%d\n",b*a);
poner(b*a);
break;
case '/':
a=quitar();
b=quitar();
if(a==0) {
printf("divisin por cero\n");
break;
}
printf("%d\n",b/a);
poner(b/a);
break;
case '.': /*mostrar el contenido de la cima de la pila*/
a=quitar();
poner(a);
printf("valor actual en la cima de la pila: %d\n",a);
break;
default:
poner(atoi(s));
}
} while(*s!='s');
return 0;
}

/*poner un elemento en la pila*/
void poner(int i)
{
if(p>fdp) {
printf("la pila est llena\n");
return;
}
*p=i;
p++;
}

/*tomar un elemento de la cima de la pila*/
quitar(void)
{
p--;
if(p<cpd) {
printf("lmite inferior de la pila sobrepasado\n");
return 0;
}
return *p;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
}

/*****PROG07.C*****/
/*un sencillo programa de lista de correos que ilustra la utilizacin y
mantenimiento de listas doblemente enlazadas
*/
#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include <string.h>

struct direccion {
char nombre[30];
char calle[40];
char ciudad[20];
char estado[3];
char cp[10]; /*contiene codigos postales de Canad, U.S.A. y Mxico*/
struct direccion *siguiente; /*puntero a la entrada siguiente*/
struct direccion *anterior; /*puntero a la entrada anterior*/
} entrada_lista;
struct direccion *principio; /*puntero a la primera entrada de la lista*/
struct direccion *final; /*puntero a la ltima entrada*/
struct direccion *hallar(char *s);

void introducir(void), busqueda(void), guardar(void);
void cargar(void), listado(void);
void borrar(struct direccion **, struct direccion **);
void almacenar_deo(struct direccion *i, struct direccion **principio,
struct direccion **final);
void entrada(char *, char *, int), mostrar(struct direccion *);
int seleccion_menu(void);

main()
{
principio=final=NULL; /*valores iniciales para los punteros inicial y

final*/
for(;;) {
switch(seleccion_menu()) {
case 1: introducir();
break;
case 2: borrar(&principio, &final);
break;
case 3: listado();
break;
case 4: busqueda(); /*buscar una calle*/
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
break;
case 5: guardar(); /*guardar una lista en disco*/
break;
case 6: cargar(); /*leer del disco*/
break;
case 7: return 0;
}
}
}

/*seleccionar una operacin*/
seleccion_menu(void)
{
char s[80];
int c;

printf("1. Introducir un nombre\n");
printf("2. Borrar un nombre\n");
printf("3. Listar el archivo\n");
printf("4. Buscar\n");
printf("5. Guardar el archivo\n");
printf("6. Cargar el archivo\n");
printf("7. Salir\n");
do {
printf("Introducir su opcin: ");
gets(s);
c=atoi(s);
} while(c<0||c>7);
return c;
}

/*introducir nombres y direcciones*/
void introducir(void)
{
struct direccion *info;

for(;;) {
info=(struct direccion *) malloc(sizeof(entrada_lista));
if(info) {
printf("\nmemoria agotada");
return;
}
entrada("escriba el nombre: ", info->nombre,30);
if(!info->nombre[0]) break; /*detener la introduccin*/
entrada("escriba la calle :", info->calle,40);
entrada("escriba la ciudad :", info->ciudad,20);
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
entrada("escriba el estado :", info->estado,3);
entrada("escriba el cdigo postal :", info->cp,10);
almacenar_deo(info, &principio, &final);
} /*fin de ciclo de entrada*/
}

/*esta funcin admite una cadena de longitud igual a contador como mximo y
evitar que la cadena se desborde. Tambin muestra un mensaje indicativo
*/
void entrada(char *indicacion, char *s, int contador)
{
char p[255];
do {
printf(indicacion);
gets(p);
if(strlen(p)>contador) printf("\nes demasiado largo\n");
} while(strlen(p)>contador);
strcpy(s,p);
}

/*crear una lista doblemente enlazada en orden*/
void almacenar_deo (
struct direccion *i, /*elemento nuevo*/
struct direccion **principio, /*primer elemento de la lista*/
struct direccion **final /*ltimo elemento de la lista
)

{
struct direccion *vieja, *p;

if(*final==NULL) { /*primer elemento de la lista*/
i->siguiente=NULL;
i->anterior=NULL;
*final=i;
*principio=i;
return;
}
p=principio; /*empezamos por el principio de la lista*/
vieja=NULL;
while(p) {
if(strcmp(p->nombre, i->nombre)<0) {
vieja=p;
p=p->siguiente;
}
else {
if(p->anterior) {
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
p->anterior->siguiente=i;
i->siguiente=p;
i->anterior=p->anterior;
p->anterior=i;
return;
}
i->siguiente=p; /*nuevo primer elemento*/
i->anterior=NULL;
p->anterior=i;
*principio=i;
return;
}
}
vieja->siguiente=i; /*se pone al final*/
i->siguiente=NULL;
i->anterior=vieja;
*final=i;
}

/*eliminar un elemento de la lista*/
void borrar(struct direccion **final)
{
struct direccion *info, *hallar();
char s[80];

printf("escriba el nombre: ");
gets(s);

info=hallar(s);
if(info) {
if(*principio==info) {
*principio=info->siguiente;
if(*principio) (*principio)->siguiente=NULL;
else *final=NULL;
}
else {
info->anterior->siguiente=info->siguiente;
if(info!=*final)
info->siguiente->anterior=info->anterior;
else
*final=info->anterior;
}
free(info); /*se devuelve la memoria al sistema*/
}
}

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
/*buscar una direccin*/
struct direccion *hallar(char *nombre)
{
struct direccion *info;
info=principio;
while(info) {
if(!strcmp(nombre,info->nombre)) return info;
info=info->siguiente; /*obtiene la direccin siguiente*/
}
printf("no se encuentra ese nombre\n");
return (NULL); /*no se encontr*/
}

/*mostrar toda la lista*/
void listado(void)
{
struct direccion *info;

info=principio;
while(info) {
mostrar(info);
info=info->siguiente; /*obtiene la direccin siguiente*/
}
printf("\n\n");
}

/*esta funcin es la que imprime los campos de cada direccin*/
void mostrar(struct direccion *info)
{
printf("%s\n",info->nombre);
printf("%s\n",info->calle);
printf("%s\n",info->ciudad);
printf("%s\n",info->estado);
printf("%s\n",info->cp);
printf("\n\n");
}

/*bsqueda de un nombre en la lista*/
void busqueda(void)
{
char nombre[40];
struct direccion *info, *hallar();

printf("escribe el nombre que hay que buscar: ");
gets(nombre);
info=hallar(nombre);
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
if(!info) printf("no se encontr\n");
else mostrar(info);
}

/*guardar el archivo en disco*/
void guardar(void)
{
struct direccion *info;
FILE *fp;

fp=fopen("listacor","wb");
if(!fp) {
printf("no se puede abrir el archivo\n");
exit(1);
}
printf("\nguardando el archivo\n");
info=principio;
while(info) {
fwrite(info,sizeof(struct direccion),1,fp);
info=info->siguiente; /*obtiene la direccin siguiente*/
}
fclose(fp);
}

/*cargar el archivo de direcciones*/
void cargar()
{
struct direccion *info;
FILE *fp;

fp=fopen("listacor","rb");
if(!fp) {
printf("no se puede abrir el archivo\n");
exit(1);
}
/*se libera toda memoria asignada anteriormente*/
while(principio) {
info=principio->siguiente;
free(info);
principio=info;
}
/*se ponen a cero los punteros inicial y final*/
principio=final=NULL;
printf("\ncargando el archivo\n");
while(!feof(fp)) {
info=(struct direccion *) malloc(sizeof(struct direccion));
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
if(!info) {
printf("memoria agotada ");
return;
}
if(1!=fread(info,sizeof(struct direccion),1,fp)) break;
almacenar_deo(info,&principio,&final);
}
fclose(fp);
}

/*****PROG08.C*****/
/*este programa muestra un rbol binario*/
#include <stdlib.h>
#include <stdio.h>

struct arbol {
char info;
struct arbol *izquierda;
struct arbol *derecha;
};

struct arbol *raiz; /*primer nodo del rbol*/
struct arbol *arbolA(struct arbol *raiz, struct arbol *r, char info);
void imprimir_arbol(struct arbol *raiz, int l);

main() /*programa imprimir arbol*/
{
char s[80];
raiz=NULL; /*se da valor inicial a la raiz*/
do {
printf("escriba una letra: ");
gets(s);
if(!raiz) raiz=arbolA(raiz, raiz, *s);
else arbolA(raiz, raiz, *s);

} while(*s);
imprimir_arbol(raiz, NULL);
return 0;
}

struct arbol *arbolA (
struct arbol *raiz;
struct arbol *r;
char info)

{
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
if(!r) {
r=(struct arbol *) malloc(sizeof(struct arbol));
if(!r) {
printf("memoria agotada\n");
exit(0);
}
r->izquierda=NULL;
r->derecha=NULL;
r->info=info;
if(!raiz) return r; /*primera entrada*/
if(info<raiz->info) raiz->izquierda=r;
else raiz->derecha=r;
return r;
}
if(info<r->info) arbolA(r,r->izquierda,info);
else
arbolA(r, r->derecha,info);
}

void imprimir_arbol(struct arbol *r, int l)
{
int i;

if(!r) return;
imprimir_arbol(r->izquierda,l+1);
for(i=0;i<l;++i) printf(" ");
printf("%c\n",r->info);
imprimir_arbol(r->derecha,l+1);
}

/*****PROG09.ASM****/

name mul
_text segment byte public 'code'
dgroup group _bss,_data
assume
cs:_text,ds:dgroup,ss:dgroup
_text ends
_data segment word public 'data'
_d' label byte
_data ends
_bss segment word public 'bss'
_b' label byte
_bss ends
_text segment byte public 'code'
_mul proc near
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
push bp
mov bp,sp
;
*************************************************
; este es el cdigo para multiplicar nmeros
mov ax,[bp+4]
;a
imul ax,[bp+6]
;b
;
*************************************************
@1:
pop bp
ret
_mul endp
_text ends
_data segment word public 'data'
_s@ label byte
_data ends
_text segment byte public 'code'
public _mul
_text ends
end

/*****PROG10.C*****/
#include "stdio.h"
#include "defines.h"
#include "struct.h"

#define DEFALUT_DRV '@' /** '@' - 0X40=0, o el disco por default **/

main (argc, argv)
int agrc;
char *argv[];
{
int errcode;
struct dskdata *dpp; /*dpp= puntero a parmetro de disco*/
UCHAR drive;
char *malloc();
static char wrnmsg[]="\007 CUIDADO. Tipo no definido. El disco puede
estar

fallando.";
static char *drivetype[] =
{
"Doble lado, 8 sectores por pista, disco de 5.25 pulgadas",
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
"Lado nico, 8 sectores por pista, disco de 5.25 pulgadas",
"Doble lado, 9 sectores por pista, disco de 5.25 pulgadas",
"Lado nico, 9 sectores por pista, disco de 5.25 pulgadas",
"\007Tipo desconocido...",
"\007Tipo desconocido...",
"Doble lado, 15 sectores por pista, disco de 5.25 pulgadas",
"Disco duro",
};
drive=(argc<2)?DEFAULT_DRV: *argv[1];
if ((dpp=(struct dskdata *) malloc(sizeof(struct dskdata)))==NIL)
copyexit(OUT_OF_MEM, "ESPACIO", THIS_YEAR);
if ((errcode=dskstats(dpp,drive))==NULL)
{
dpp->mdb=(UCHAR)(~dpp->mdb);
if(dpp->mdb >= (sizeof(drivetype) /
sizeof(drivetype[0])))
puts(warnmsg);
else
{
printf("Tipo de lectora = %s.\n",drivetype[dpp->mdb]);
printf("Celdas libres = %u\n",dpp->freeclust);
printf("Total de celdas = %u\n",dpp->totclust);
printf("Bytes/sector = %u\n",dpp->bytes_sect);
printf("Sectores/celda = %u\n\n",dpp->sect_clust);
printf("Espacio total = %91u bytes.\n",dpp->dsksize);
printf("Espacio libre = %91u bytes.\n",dpp->spaceleft);
printf("Espacio usado = %91u bytes.\n",(dpp->dsksize -
dpp->spaceleft));
}
}
copyexit(errcode,"ESPACIO",THIS_YEAR);
}

/*****PROG11.C*****/
#include "stdio.h"
#include "fcntl.h"
#include "defines.h"
#define TIME 1

main(argc, argv)
int argc;
char *argv[];
{
unsigned sametime;
int errcode, newdate;
int file_2_date;
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
if(argc<3)
copyexit(FEW_ARGS,"SYNTAX:FILEDATE FILENAME
DD/MM/YY", THIS_YEAR);
if ((errcode=newdate=str2date(argv[2])) <0)
copyexit(NO_READ_OPEN,"FILEDATE",THIS_YEAR);
sametime=gestamp(file_2_date,TIME);
errcode=putstamp(file_2_date,newdate,sametime);
close(file_2_date);
copyexit(errcode,"FILEDATE",THIS_YEAR);
}

/*****PROG12.C*****/
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX 360
main()
{
int controlador, modo;
int sector[MAX];
int contador, i, tam, color;
int principio, fin;
float factor_norm;
int colormax;
struct viewporttype info;
do {
printf("Cuntos sectores (1 - 359) ? : ");
scanf("%d",&contador);
} while(contados<1||contador>359);
for(i=0;i<contador;i++) {
printf("escriba un valor para el sector %d : ", i+1);
scanf("%d", &sector[i]);
}
/*factor de normalizacin de la computadora*/
tam=0;
for(i=0;i<contador;i++) tam+=sector[i];
factor_nom=360.0/(float) tam;
controlador=DETECT;
initgraph(&controlador,&modo,"");
getviewsettings((struct viewporttype far *) &info);
colormax=getmaxcolor();
principio=fin=0;
for(i=0, color=1;i<contador;i++, color++) {
setfillstyle(SOLID_FILL,color);
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
/*calcula el punto final*/
fin=fin+(int)sector[i]*factor_norm;
/*si es el ltimo segmento, se asegura de que el ltimo radin
est en el grado 360*/
if(1==contador-1&&fin!=360) fin=360;
pieslice(info.right/2,info.bottom/2, principio, fin, info.bottom/4);
principio=fin;
if(i%2) fin++; /*se promedian los efectos de truncacin*/
/*se reciclan los colores si es necesario*/
if(color==colormax) color=1;
}
getch();
closegraph();
return 0;
}

/*****PROG13.C*****/
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX 100

main()
{
int controlador, modo;
int barras[MAX];
int contador, i, tam, color;
float factor_norm;
struct viewporttype info;
int espaciado;
int colormax;
do {
printf("Cuntas barras (1-99) ? : ");
scanf("%d",&contador);
} while (contador<1||cntador>99);
for(i=0;i<contador;i++) {
printf("escriba un valor para la barra %d : ", i+1);
scanf("%d", &barras[i]);
}
controlador=DETECT;
initgraph(&controlador, &modo,"");
getviewsettings((struct viewporttype far*) &info);
colormax=getmaxcolor();
/*factor de normalizacin de la computadora*/
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
tam=0;
/*se halla la barra ms grande*/
for(i=0;i<contador;i++)
if(barras[i]>tam) tam=barras[i];
factor_norm=(float) info.bottom/(float) tam;
/*se determina cunta distancia hay entre las barras*/
espaciado=info.right/contador;
for(i=0,color=1;i<contador;i++,color++) {
setfillstyle(SOLID_FILL, color);
bar(i*espaciado,info.bottom-(int) factor_norm*barras[i];
i+espaciado+(espaciado/2), info.bottom);
/*se reciclan los colores si es necesario*/
if(color==colormax) color=1;
}
getch();
closegraph();
return 0;
}

/*****PROG14.C*****/
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>

main()
{
int controlador, modo;
int tam;
void *buf;
struct viewporttype info;

controlador=DETECT;
initgraph(&controlador,&modo,"");
getviewsettings((struct viewporttype far *) &info);
setfillstyle(SOLID_FILL,WHITE);
rectangle(0, 0, info.right, info.bottom);
floodfill(1, 1,, WHITE);
setcolor(RED);
rectangle(0, 0, info.right/4, info.bottom/4);
/*crear un recuadro*/
setfillstyle(SOLID_FILL, GREEN);
floodfill(1, 1, WHITE);
setcolor(GREEN);
line(0, 0, info.right/4, info.bottom/4);
line(0, info.bottom/4, info.right/4, 0);
getch();
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
/*desplazar la imagen*/
/*primero se toma el tamao de la imagen*/
tam=imagesize(0, 0, info.right/4, info.bottom/4);
if(tam != -1) { /*se asigna memoria para la imagen*/
buf=malloc(tam);
if (buf) {
getimage(0, 0, info.right/4, info.bottom/4);
putimage(info.right/3, info.bottom/3, buf, COPY_PUT);
putimage((info.right/4,)*3, (info.bottom/4)*3, buf,
XOR_PUT);
}

}
getch();
closegraph();
return 0;
}

/*****PROG15.C*****/
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>

main()
{
int controlador, modo;
controlador=DETECT; /*autodeteccin*/
initgraph(&controlador, &modo, "");
outtext("Normal");

/*letra gtica, tamao tres veces mayor que el normal*/
settextstyle(GOTHIC_FONT,HORIZ_DIR,3);
outtext("Gtica");

/*letra triplex, tamao cinco veces mayor que el normal*/
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 5);
outtext("Triplex");

/*letra sans serif, tamao siete veces mayor que el normal*/
settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 7);
outtext("Sans serif");

getch();
closegraph();
return 0;
}
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado

/*****PROG16.C*****/
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <alloc.h>
#include <stdlib.h>

#define MAX 1024

main()
{
int controlador, modo;
int alto, ancho;
char *p, s[2], mensaje[MAX];
struct viewporttype info;
int tam;
void *buf, *bufborrar;

printf("Escriba su mensaje (menos de %d caracteres) : \n", MAX);
gets(mensaje);
controlador=DETECT; /*autodeteccin*/
initgraph(&controlador, &modo, "");
getviewsettings((struct viewporttype far *) &info);
settextstyle(DEFAULT_FONT, HORIZ_DIR,9);
alto=9*8; /*la letra por defecto tiene 8 pixels de alto*/
ancho=9*8; /*la letra po defecto tiene 8 pixels de ancho*/
/*se reserva un buffer para almacenar la parte de la pantalla que contiene
el mensaje, menos espacio para el caracter de la izquierda.
*/
tam=imagesize(ancho, (info.bottom/2)-(alto/2), info.right, (info.bottom/2)+
(alto/2));
buf=(void *) malloc(tam);
if (!buf) {
printf("Error de asignacin!");
exit(1);
}
/*se reserva el buffer que se va a utilizar para borrar la letra de la
derecha en cuya posicin se va a escribir el caracter siguiente.
*/
tam=imagesize(0, 0, ancho, alto);
bufborrar=malloc(tam);
if(!buffborrar) {
printf("Error de asignacin!");
exit(1);
}
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
/*toma un trozo de pantalla en blanco del tamao de un caracter*/
getimage(0, 0, ancho, alto, bufborrar);
p=mensaje;
s[1]='\0';
while(?kbhit()) {
/*desplaza el texto existente hasta la izquierda*/
getimage(ancho, (info.bottom/2)-(alto/2), info.right, (info.bottom/2)+
(alto/2),
buf);
putimage(0, (info.bottom/2)-(alto/2), buf, COPY_PUT);
/*toma el caracter siguiente*/
*s=*p;
/*borrar la posicin del caracter nuevo*/
putimage(info.right-ancho, (info.bottom/2)-(alto/2), bufborrar,
COPY_PUT);
/*se saca el caracter*/
outtextxy(info.right-ancho, (info.bottom/2)-(alto/2), (char far *s) s);
p++;
if(!*p) p=mensaje; /*vuelve al principio del mensaje*/
}
getch();
closergraph();
return 0;
}

/*****PROG17.C*****/
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>

main()
{
int controlador, modo;
struct viewporttype info;
controlador=DETECT;
initgraph(&controlador, &modo "");
getviewsettings((struct viewporttype far *) &info);
/*por defecto lnea continua*/
line(0, 0, info.right, 0);
getch();
setlinestyle(DOTTED_LINE, 0, NORM_WIDTH);
line(0, 10, info.right, 10);
getch();
setlinestyle(CENTER_LINE, 0, NORM_WIDTH);
line(0, 20, info.right, 20);
getch();
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
setlinestyle(DASHED_LINE,0, NORMWIDTH);
line(0, 30, INFO.RIGHT, 30);
getch();
setlinestyle(USERBIT_LINE, 146, THICK_WIDTH);
line(0, 40, info.right, 40);
getch();
closegraph();
return 0;
}

/*****PROG18.C*****/
#include <graphics.h>
#include <stdlib.h>
#include <time.h> /*lo utiliza randomize*/
#include <conio.h>

main()
{
int controlador, modo;
struct viewporttype info;
char buf_llenar[8];
int i;
controlador=DETECT;
initgraph(&controlador, &modo, "");
getviewsettings((struct viewporttype far *) &info);
/*crea un entramado aleatorio para rellenar*/
ramdomize();
for(i=0;i<8;i++) buf_llenar[i]=rand()%256;
setfillpattern(buf_llenar, RED);
setfillstyle(USERFILL_RED);
rectangle(0, 0, info.right/2, info.bottom/2);
floodfill(1, 1, WHITE);
getch();
closegraph();
return 0;
}

/*****PROG19.C*****/
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>

#define MAX 500

main()
Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
{
int controlador, modo;
int poligono[MAX];
int i;
struct viewporttype info;

controlador=DETECT;
initgraph(&controlador, &modo, "");
getviewsettings((struct viewporttype far *) &info);

randomize();
for(i=0;i<MAX;i++) {
if(!(i%2))
poligono[i]=rand() % info.right;
else
poligono[i]=rand() % info.bottom;
}
drawpoly(MAX/2, poligono);
setfillstyle(SOLID_FILL, BLUE);
fillpoly(MAX/2, poligono);
getch();
closegraph();
return 0;
}


8. Bibliografa.

BORLAND International. Turbo C user's guide. U.S.A. 1988.

BORLAND International. Turbo C reference guide. U.S.A. 1988.

CAMPBELL, Joe. Crafting C tools for the IBM PCs. Prentice Hall.

GARCIA-BADELL, J.Javier. Turbo C: Programacin y manejo de archivos.
Macrobit Corporation. Mxico, 1991.

SCHILDT, Herbert. Programacin en lenguaje C. [C made easy].
McGraw-Hill Inc. Espaa, 1990.

SCHILDT, Herbert. Turbo C/C++. Manual de referencia. [The
complete reference]. Osborne/McGraw-Hill Inc.
Mxico, 1993.

Rodolfo Gallardo-Rosales


Tutorial
Turbo C Avanzado
SCHILDT, Herbert. Turbo C. Programacin avanzada. [Advanced
Turbo C]. 2a. ed. Borland-Osborne/McGraw-hill.
Espaa, 1990.

Para mayor informacin

Se sugiere la lectura de alguno de los libros mencionados arriba, y el estudio ms completo
ser la nica manera de dominar integralmente el Lenguaje de programacin Turbo C.

Você também pode gostar