printf("текущий режим=%d, число текстовых колонок=%d",

  rr. h.al, rr. h.ah);

}

Пример b) Установим нулевой видеорежим, а затем вернем 3 видеорежим

#include<stdio. h>

#include<dos. h>

#include<conio. h>

void main(){

union REGS rr;/*структура описывает регистры общего назначения*/

/*используется 10-е прерывание и устанавливает нулевой видео режим 40х25*/

rr. h.ah=0x00;

rr. h.al=0x00;

int86(0x10,&rr,&rr);

/*используется 10-е прерывание и читаем текущий видео режим*/

rr. h.ah=0x0f;

int86(0x10,&rr,&rr);

printf("текущий режим=%d, число текстовых колонок %d",

  rr. h.al, rr. h.ah);

getch();

/*используется 10-е прерывание  и устанавливает нулевой видео режим 80х25*/

rr. h.ah=0x00;

rr. h.al=0x03;

int86(0x10,&rr,&rr);

/*используется 10-е прерывание и читаем текущий видео режим*/

rr. h.ah=0x0f;

int86(0x10,&rr,&rr);

printf("текущий режим=%d, число текстовых колонок %d",

  rr. h.al, rr. h.ah);

getch();

}

Задание:

Написать программу, используя доступ через функции и структуры. В программе необходимо реализовать функцию AH=01h (0x01) прерывания 10h BIOS, чтобы установить размер/форму курсора (текст), причем если курсор виден, то он мерцает. Для этого в качестве входа используются регистры CH и CL, где

  CH = начальная строка (значения от 0 до 1Fh; 20h=подавить курсор)

  CL = конечная строка (0-1Fh)

Написать программу, использующую функцию AH=00h прерывания 10h BIOS, которая устанавливает 2 видео-режим (AL=2), показывает результат установки на экране монитора, затем переустанавливает в 1 видео-режим (AL=1) и выводит результат на экран и по окончанию программы возвращает 3 видео-режим (AL=3).

Лабораторная работа №4

НЕ нашли? Не то? Что вы ищете?

Тема: «Работа с функциями BIOS. Запись символа в видеопамять напрямую, используя указатели far или near»

(2 часа)

“Близкий” (near) указатель задает только смещение адреса объекта, на который ссылается указатель. В качестве сегментной части адреса объекта используется текущее значение сегментного регистра DS. Поэтому near-указатель занимает в памяти компьютера только два байта и позволяет адресовать не более 64 Кбайт, т. е. работает только внутри сегмента DS.

“Далекий” (far) указатель задает полный адрес объекта: значение сегмента и значение смещения. Поэтому far-указатель занимает в памяти компьютера 4 байта и позволяет адресовать любой байт в адресном пространстве. Причем первое слово, рассматривается как число без знака и задает смещение, а второе слово – значение сегмента адреса. При доступе к объекту данных по значению указателя (т. е. при выполнении операции *) сегмент адреса помещается в сегментный регистр (как правило, это регистр ES). far-указатель применяют очень часто, например, для доступа к памяти видеоадаптера или специальным областям BIOS.

Пример: Вывод символа на экран и задание атрибутов (атрибуты символа – это фон и цвет символа)

void main(){

/*программа показывает пример применения записи символа в видеопамять напрямую, используя указатель far*/

/*указатель на первый байт видео памяти третьего видео режима*/

char far *video=(char far*)0xB8000000L;

*video='N';//символ

video++;//указатель на атрибут символа

//IRGB IRGB

//0x42

//0100 0010

*video=0x42;/*атрибуты символа: зеленый символ на красном*/

}

Пример: вывод символа на экран программой, использующей ассемблерную вставку:

void main() //пример применения ассемблерных вставок

{

asm {

  mov ah,0eh //пересылаем значение 0еh в регистр ah

  mov al,'N' //пересылаем символ N в регистр al

  int 10h  //вызываем 10-е прерывание

  }

}

Задание:

Написать программу вывода семи символов (символы должны иметь  различные атрибуты), используя указатели.

Лабораторная работа №5

Тема: «Работа с памятью. Выделение памяти посредством прерывания Int 21h DOS»

(2 часа)

При выделении памяти посредством прерывания Int 21h DOS используется понятие блока (определенное количество байт). DOS выделяет память блоками, эти блоки последовательно соединены друг с другом в виде цепочки, и если освобождается блок в середине цепочки, то DOS может использовать его при выделении памяти, но не соединяет его со свободной памятью оставшейся вне цепочки.

#include<dos. h>

#include<stdio. h>

#include<conio. h>

void main(){

clrscr();

unsigned int perem, perem_AX, perem2;

//выделим блок памяти функцией 48h INT21h

_AH=0x48;

_BX=0xffff;/*запрос явно большого участка памяти с целью получения доступной памяти в параграфах*/

geninterrupt(0x21);

perem=_BX;

/*умножаем на 16, чтобы получить количество в байтах*/

printf("Свободно байт = %u\n",perem*16);

/*выделим участок памяти на 2 параграфа меньше, чем кол-во свободной памяти*/

_AH=0x48;

_BX=perem-2;

geninterrupt(0x21);

perem_AX=_AX;

/*проверка размера свободного блока памяти функцией 48h INT21h*/

_AH=0x48;

_BX=0xffff;

geninterrupt(0x21);

perem2=_BX;

printf("Свободно байт после выделения памяти=%u\n",

  perem2*16);

//перераспределение участка памяти (сжать, добавить)

_ES=perem_AX;

_BX=perem-200; //освобождаем 200 параграфов

_AH=0x4a;

geninterrupt(0x21);

/*проверка размера свободного блока памяти функцией 48h INT21h*/

_AH=0x48;

_BX=0xffff;

geninterrupt(0x21);

perem2=_BX;

//умножаем на 16, чтобы получить количество в байтах

printf("Свободно байт после перераспр. памяти=%u\n",

  perem2*16);

//освобождение участка памяти

_AH=0x49;

_ES=perem_AX;

geninterrupt(0x21);

/*проверка размера свободного блока памяти функцией 48h INT21h после освобождения памяти*/

_AH=0x48;

_BX=0xffff;

geninterrupt(0x21);

perem2=_BX;

printf("Свободно байт после освоб. памяти=%u\n",

  perem2*16);

getch();

}

Задание:

Выделить участок памяти в параграфах, занести в него массив элементов 1. char; 2. int, прочитать его и освободить участок памяти.

Примечание: память выделяется в параграфах, поэтому байты надо перевести в параграфы: (количество элементов)%16 +1.

Лабораторная работа №6

Тема: «Работа с внешними устройствами, на примере видеоадаптера»

(2 часа)

В видеопамяти вся информация записывается в виде длинной ленты данных. А при выводе символов на экран происходит ее преобразование в матрицу (разбивают на строки). Для видео режима 80х25 одна строка занимает 160 байт = 80байт * 2 байта на каждый символ.

Для того чтобы вывести символ на экран, используя видеоадаптер, необходимо вычислить смещение относительно используемого адреса, на который настроен указатель. Для этого используется формула:  (y*X1 + x)*2, где y – строка, x – колонка, X1 – количество столбцов используемых в данном режиме.

Работа с ВУ через адресное пространство:

#include<stdio. h>

#include<conio. h>

void main(){

/*записываем в область памяти, принадлежащую внешнему устройству (контроллеру видеоадаптера)*/

clrscr();

char far *ykazat=(char far *)0xB8000000;

*ykazat='*';

}

Пример перехвата прерывания в ОС MS-DOS

#include<dos. h>

#include<stdio. h>

//задаем адрес видеопамяти

char far *ykazat=(char far*)0xB8000000;

/*объявляем переменную, в которой сохраняется  перехваченный вектор прерывания*/

void interrupt( *old_vect) (...);

//новая функция обработки прерывания

void interrupt fun_vector(...){

//сохраняем в стеке используемые перехваченным прерыванием регистры

asm{

  push ax

  push bx

  push es

}

//переводим номер функции в ASCII код

if (_AH>9) *ykazat=_AH+0x41-10;

else *ykazat=_AH+0x30;

//восстанавливаем регистры

asm{

pop es

pop bx

pop ax

}

old_vect(); //вызов старого прерывания

};

void main(){

old_vect=getvect(0x10); /*сохраняем значение перехватываемого вектора*/

setvect(0x10,fun_vector); /*записываем новое значение вектора*/

_AH=0x0e;

_AL='@';

geninterrupt(0x10);

setvect(0x10,old_vect);/*восстанавливаем перехвач. 

  вектор*/

}

Прерывание по таймеру 1Ch (пользовательское) – этот вектор (0:0070) BIOS берет по каждому тику аппаратных часов. Первоначально он использует IRET, но может быть изменен пользовательской программой с целью адресовать фоновую программу пользователя, базирующуюся на таймере. И поскольку программа INT 1Ch выполняется во время низкоуровневого аппаратного прерывания, и система еще не сбрасывает контроллер прерываний, поэтому другие аппаратные прерывания (в том числе прерывание от клавиатуры)  не будут происходить при работе INT 1Ch, т. е. не будет работать ввод пользователя. Поэтому большинство программ перехватывают вектор INT 08h, вызывают нужный вектор, а только затем выполняют операции, зависящие от времени, после того как BIOS закончит свою работу.

Задание:

Записать в виде прямой диагонали фамилию и имя, используя прямой доступ к видеопамяти (выполнить то же самое для обратной диагонали). Дополнительное задание:

Написать программу, перехватывающую вектор 1Ch (таймер), с целью увеличения счетчика задержки по времени. В векторе прерывания увеличивать счетчик на 1. В основной программе использовать счетчик для задержки на определенное количество секунд.

1секунда=18 тиков (18,2)

Пояснение: создаваемой функции дается задание увеличения тиков. Пример: 18*3=3 секунды.

Лабораторная работа №7

Тема: «Управление задачами и памятью в Windows»

(2 часа)

Для управления задачами используется механизм «предок-потомок».

Программа, которая запускается на исполнение, называется программой-потомком (child program – дочерняя программа). Программа, которая запускает дочернюю программу, называется программой-предком (parent program – родительская программа). Функции языка С, работающие с процессами, находятся в библиотеке <PROCESS. H>.

Для того чтобы запустить дочернюю программу с возвратом в родительскую, используются следующие функции:

int spawnl(int mode, char *path, char *arg0, …, NULL);

int spawnle(int mode, char *path, char *arg0, …, NULL, char **env);

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5