Red de conocimiento informático - Conocimiento de la instalación - Solicite el programa de tiempo de permanencia del sistema de diseño del curso de principios de microcomputadoras

Solicite el programa de tiempo de permanencia del sistema de diseño del curso de principios de microcomputadoras

Programación en lenguaje C a nivel de sistema (introducción a los principios de interrupción)

Resumen: este artículo presenta principalmente la escritura, instalación y uso de programas de servicio de interrupción en lenguaje C. Dado que la escritura del programa de servicio de interrupción total implica las operaciones de lectura y escritura del puerto de hardware, el usuario interactúa directamente con el hardware. Hay una gran cantidad de datos (como la dirección del puerto de hardware, etc.) que se utilizan en el proceso de programación. lo que hace que el programador interactúe con la computadora. Falta una función de "búfer" entre los dispositivos de hardware y es mucho más conveniente usar lenguaje ensamblador para programar directamente el hardware. Este artículo solo escribe el programa de interrupción suave como introducción.

Palabras clave: interrupción suave, vector de interrupción, tabla de vectores de interrupción, residente de memoria TSR, reentrada de DOS, solicitud de interrupción, dirección de segmento, compensación, registro, BIOS, DOS, setvect (), getvect (), keep ( ), desactivar ( ), habilitar ( ), geninterrupt ( ), int86 ( ), interrumpir

Para la mayoría de los entusiastas del lenguaje C, existe una pregunta sobre cómo utilizar las rutinas de interrupción en el lenguaje C. estar muy familiarizado con él. Por ejemplo, podemos llamar directamente a la interrupción 13H a través de la función INT86 () para operar los sectores físicos del disco, o podemos llamar a la interrupción 33H a través de la función INT86 () para operar el cursor del mouse que se muestra en el. pantalla. De hecho, 13H o 33H son solo algunas funciones y los parámetros de estas funciones se implementan a través de registros de CPU. El número de interrupción solo apunta indirectamente a la unidad de almacenamiento inicial del cuerpo de la función. Se dice que es indirecto, es decir, la dirección inicial y el desplazamiento del segmento de función se calculan a través del número de interrupción (se explicará específicamente cómo operar a continuación). ). De esta manera, los programadores no necesitan dedicar demasiado tiempo a escribir programas para operar el hardware. Solo necesitan configurar los parámetros en sus propios programas y luego llamar a la rutina de servicio de interrupción proporcionada por BIOS o DOS, lo que reduce en gran medida la dificultad de. desarrollo del programa. El ciclo de desarrollo del programa se acorta. Entonces, dado que es una función de interrupción, el usuario puede llamarla arbitrariamente y escribirla arbitrariamente.

Los primeros 1024 bytes de la memoria de la computadora (desplazamiento 00000H a 003FFH) almacenan 256 vectores de interrupción. Cada vector de interrupción ocupa 4 bytes. Los primeros dos bytes almacenan la rutina de servicio de interrupción y los dos últimos bytes. almacene la dirección del segmento de entrada del programa de interrupción. Cuando lo use, simplemente transfiéralo al registro IP y CS respectivamente. Cuando use el programa de interrupción, simplemente transfiéralo al registro respectivamente. En IP y CS, puede transferirlo a la interrupción. Rutina de servicio para implementar llamadas de interrupción. Siempre que ocurre una interrupción, la CPU multiplica el número de interrupción por 4 para obtener la dirección del vector de interrupción en la tabla de vectores de interrupción, y luego obtiene los valores IP y CS, de modo que pueda ir a la dirección de entrada de la rutina del servicio de interrupción y llamar. la interrupción. Este es el proceso básico de llamar a la rutina del servicio de interrupción mediante el número de interrupción. Cuando se inicia la computadora, el BIOS completa las interrupciones básicas en la tabla de vectores de interrupción. Cuando DOS obtiene el control del sistema, debe completar algunos vectores de interrupción en la tabla y algunos vectores de interrupción en el BIOS deben modificarse. El sistema reserva algunos vectores de interrupción para los usuarios, como las interrupciones 60H a 67H. Los usuarios pueden escribir rutinas de servicio de interrupción en estos vectores de interrupción. Además, puede cambiar y mejorar los vectores de interrupción existentes en su sistema.

En lenguaje C, se proporciona un nuevo tipo de función de interrupción, que se utiliza especialmente para definir rutinas de servicio de interrupción. Por ejemplo, podemos escribir la siguiente rutina de servicio de interrupción:

/*. Ejemplo 1: Rutina de servicio de interrupción*/

void interrupción int60()

{

puts ("Este es un ejemplo");

}

La función de esta interrupción es mostrar una cadena, entonces ¿por qué no usar la función printf()? Esto implica el problema del reingreso a DOS, que se explicará más adelante.

Se ha escrito un programa de servicio de interrupción simple ¿Cómo completar su dirección de entrada de función en la tabla de vectores de interrupción para que cuando ocurra una interrupción, se pueda transferir al programa de servicio de interrupción para su ejecución? setvect() tiene dos parámetros: número de interrupción y dirección de entrada de función. Su función es instalar la función especificada en el vector de interrupción especificado. La función getvect() tiene un parámetro: número de interrupción, y el valor de retorno es la dirección de entrada. interrumpir. Antes de instalar una interrupción, es mejor usar la función deshabilitar () para desactivar la interrupción y evitar que se generen nuevas interrupciones durante el proceso de instalación y causar confusión en el programa. Una vez completada la interrupción de la instalación, use enable (). Función para activar la interrupción para que el programa pueda ejecutarse normalmente. Ahora podemos enriquecer el ejemplo anterior:

/*Ejemplo 2: Escribir, instalar y usar una rutina de servicio de interrupción*/

#include

#include

#ifdef __cplusplus

#define __ARGU ...

#else

#define __ARGU

#endif

void interrumpir int60 (__ARGU) /* Función de servicio de interrupción**

{

puts ( "Este es un ejemplo");

}

void install (void interrupt (*fadd)(__ARGU),int num) /*Installation interrupt*/

{

disable(); /*Desactivar interrupciones*/

setvect(num, fadd /*Establecer interrupciones*/

enable); () /*Activar interrupciones*/

}

void main()

{

instalar (int60,0x60) ; /* Instalar la función int60 para la interrupción 0x60*/

geninterrupt (0x60); /*Generar artificialmente la interrupción 0x60*/

}

Es fácil para Lectores con cierta experiencia obtendrán el resultado de este programa: "¡Este es un ejemplo!" se mostrará en la pantalla.

Lo anterior trata sobre escribir e instalar una rutina de servicio de interrupción. A continuación se ofrece una breve introducción a la escritura y el uso de programas residentes en memoria (TSR). En lenguaje C, un programa puede usar la función mantener () para permanecer en la memoria. Esta función tiene dos parámetros: estado y tamaño. El tamaño es la longitud de la memoria residente, que se puede obtener mediante tamaño =_SS+_SP/16-_psp. Por supuesto, esto es solo un método de estimación, no un valor exacto. Después de ejecutar la función, la información del estado de salida se guardará en estado. Por ejemplo, para el ejemplo anterior, reescriba "geninterrupt (0x60);" como "keep(0,_SS+_SP/16-_psp);" y luego ejecute esta parte del programa. Cualquier otro software o programación, siempre que se utilice la interrupción de 60 H, se mostrarán las palabras "Este es un ejemplo" en la pantalla. La única forma de restaurar la definición del sistema de la interrupción 60H es reiniciar la computadora.

Ejemplos como el anterior son en realidad imperfectos porque no tienen en cuenta el estado del entorno DOS, si el programa ya reside en la memoria o si ha salido de la memoria. El segundo problema es fácil de resolver: al comienzo de la ejecución del programa, lea la dirección de entrada de interrupción de una función (como la interrupción 63H) y determine si está vacía (NULL, si está vacía, establezca la dirección en no). -null primero, y luego la memoria es residente. Si no está vacía, significa que la memoria ha sido residente y el programa se cierra. El juicio en este paso es muy importante; de ​​lo contrario, ocupará demasiado espacio de memoria repetidamente y eventualmente provocará que el sistema falle. En cuanto a las otras dos preguntas, no entraré en detalles aquí. Si está interesado, puede consultar algunos libros.

No sólo eso, también podemos usar teclas de acceso rápido para llamar a programas residentes en memoria en DOS. Por ejemplo, después de que el "Diccionario Hope" que viene con el "Sistema de caracteres chinos Hope" resida en la memoria, puede activar el programa presionando Ctrl+F11 en cualquier momento y aparecerá la interfaz del diccionario. El teclado de la microcomputadora tiene un chip de microprocesador que escanea y detecta la pulsación y liberación de cada tecla. La mayoría de las teclas tienen un código de escaneo que notifica a la CPU el estado actual, pero algunas teclas especiales, como PrintScreen, Ctrl+Break, etc., no generan un código de escaneo, sino que generan directamente una interrupción. Debido a esto, podemos señalar el número de interrupción generado por Ctrl+Break a la dirección de entrada de nuestro propio programa. Luego, cuando presione Ctrl+Break, el sistema llamará a su propio programa para ejecutarlo. vector. En cuanto al procedimiento de activación de otras teclas, se puede realizar utilizando la interrupción del teclado 9H capturada por el código de escaneo, que no se explicará una por una aquí. Por ejemplo, después de ejecutar el siguiente programa, regrese al sistema DOS y presione Ctrl + Interrumpir en cualquier momento, el color de fondo de la pantalla cambiará a rojo.

/* Ejemplo 3: Escritura, instalación y uso de rutina de servicio de interrupción, residente en memoria*

#include

#include < conio .h>

#ifdef __cplusplus

#define __ARGU ...

#else

#define __ARGU

#endif

void interrupt newint(__ARGU); /*Declaración de función*

void install (void interrupt (*fadd)(__ ARGU), int num);< / p>

int main()

{

instalar (newint,0x1b); /*Ctrl+número de interrupción: 1BH*

mantener(0); ,_SS+(_SP/16)-_psp); /*programa residente*/

return 0;

}

interrupción nula newint(__ARGU)< / p>

{

textbackground(4); /*Establece el color de fondo de la pantalla en rojo*/

clrscr() /*Borrar la pantalla*/

}

instalación nula (interrupción nula (*fadd)(__ARGU), int num)

{

disable();

setvect(num,fadd); /*Establecer interrupción*/

enable( );

}

Porque la interrupción 13H es el programa de servicio de interrupción de disco proporcionado por BIOS, por lo que para aplicaciones en DOS, sus funciones de guardado y lectura se implementan llamando a esta interrupción. Hay muchos virus de DOS a los que les gusta modificar la interrupción 13H para dañar el sistema. Por ejemplo, modifique el programa de servicio de interrupción 13H a:

/*Ejemplo 4: Pseudocódigo del programa del cuerpo del virus*/

.

void interrumpir new13(__ARGU)

{

Si (las condiciones para el ataque de virus están dadas)

{ Cambie el parámetro de entrada para que apunte al dirección de entrada del programa de virus;

Ejecutar código de virus;

}

Llamar a la interrupción 13H original;

}

Siempre que exista algún software (por ejemplo: ................................g., EDIT.COM, etc.) .) ejecutándose en el disco, ataque de virus Cuando llega el momento, el virus se activa.

Por supuesto, esto da como resultado menos memoria disponible y es más fácil de detectar por los usuarios. Algunos virus "inteligentes" modifican otros vectores de interrupción para que el sistema informe el mismo tamaño de memoria que realmente. También hay algunos virus que desaparecerán silenciosamente cuando los usuarios los descubran y los rastreen a través de algunos programas (como DEBUG.COM, etc. El principio básico todavía está relacionado con la interrupción de la modificación). Lado 0 Cilindro 0 Sector 1 (Lado 0 Cilindro 0 Sector 1) del disco duro almacena información de inicio importante. Una vez dañado, la computadora no podrá reconocer el disco duro. Podemos escribir un programa para evitar que cualquier software (incluidos los virus) realice una operación de "escritura" en este sector, logrando un efecto de "protección contra escritura" hasta cierto punto. El principio básico es modificar el vector de interrupción 13H y residir en la memoria. , seguimiento de operaciones en discos mediante software (incluidos virus). El principio básico es modificar el vector de interrupción 13H y residir en la memoria, monitoreando cada detalle del software (incluidos los virus) que opera en el disco. Los lectores deben tener en cuenta que este programa no considera salidas residentes en la memoria, por lo que si desea reanudar la interrupción 13H, reinicie la computadora.

/* Ejemplo 5: Protección maestra del sector de arranque, utilice Turbo C 2.0 para compilar, MBSP.C*/

#include

#include

#include

#define STSIZE 8192

#define PSP_ENV_PSP 0x2c

#define PARA(x) ((FP_OFF(x)+15)>>4)

typedef struct {

unsigned bp,di,si,ds,es,dx, cx,bx,ax,ip,cs,flags;

}INTERRUPT_PARAMETER;

instalación vacía (interrupción vacía (*faddress)(), int num);

interrupción nula new13(INTERRUPT_PARAMETER p);

int main()

{

union REGS regs;

struct SREGS sregs;

mem unsigned;

puntero lejano sin firmar;

char far *pila;

printf("/ n<> versión 1.0\n \n");

if ((stack=malloc(STSIZE))==NULL)

{

printf ("¡No hay suficiente memoria!\n");

exit(1);

}

if (getvect( 0x62)! =NULL)

{

printf("¡Ya instalado!\n");

exit(1);

}

instalar(getvect(0x13),0x62);

instalar (new13, 0x13);

pointer=MK_FP(_psp,PSP_ENV_PSP);

freemem(*puntero);

segread(&sregs);

mem=sregs.ds+PARA(stack)-_ psp;

setblock (_psp,mem);

mantener (0,mem);

devolver 0;

}

{

disable();

setvect(num,faddress);

enable();

}

interrupción nula nueva13 (INTERRUPT_PARAMETER p)

{

p.ax=_AX;

p.cx=_CX;

p.dx=_DX ;

if(_AH==0x03&&_CH==0&&_CL==0x01&&_DH==0&&_DL==0x80) devuelve;

enable();

geninterrupt (0x62

);

desactivar();

_AX=p.ax;

_CX=p.cx;

_DX=p. dx;

Regresar;

}

Nota: antes de usar este programa, utilice un software antivirus para limpiar el sector de arranque, la memoria y todos los archivos de la computadora. ② Los lectores con conocimientos de lenguaje ensamblador pueden escribir un nuevo programa de inicio por sí mismos, primero residen el programa en la memoria y luego llaman al programa de inicio original. que el virus aún no está allí. Obtenga el control del sistema.

Antes de llamar al programa de inicio original, cree un nuevo programa de inicio, resídalo en la memoria y luego llame al programa de inicio original, de modo que el virus aún no haya obtenido el control del sistema.

Por último, una breve explicación del problema de volver a entrar en DOS (sistema operativo monousuario y monotarea). Si el programa se interrumpe durante la ejecución, es posible que no se ejecute correctamente porque destruirá el entorno original del programa, lo cual es catastrófico. Cuando ocurre una interrupción, la CPU finalizará inmediatamente el programa actual y ejecutará la rutina de servicio de interrupción. Si la rutina de servicio de interrupción en la rutina de servicio de interrupción llama a una interrupción de DOS (como la interrupción de DOS número 21H), esto inevitablemente reescribirá el entorno global. variables (como PSP El prefijo del segmento del programa se cambiará al PSP que está ejecutando el programa de interrupción), lo que provocará que se destruya el entorno original y que el programa original no pueda ejecutarse correctamente. El programa original no se puede ejecutar correctamente. Cuando la llamada de interrupción se completa y regresa, el usuario obtendrá resultados inesperados. Por lo tanto, al escribir un programa de servicio de interrupción, se deben evitar las llamadas a funciones del sistema DOS y funciones como malloc (), printf (), sprintf () no deben aparecer en el programa de servicio de interrupción en lenguaje C.

Referencias:

"Programación de utilidades avanzada en lenguaje C", escrito por Wang Shiyuan, Tsinghua University Press, 1996.3