Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СП - ASM / Лабораторная работа №2 Видеопамять, методы адресации.doc
Скачиваний:
18
Добавлен:
03.03.2016
Размер:
293.89 Кб
Скачать

Inc ax ;Инкремент числа-заполнителя

add SI, 2 ;Смещение в массиве к следующему слову

loop fill ;На метку fill (CX раз)

Повышение эффективности достигается за счет того, что команда занесения числа в элемент массива оказывается короче (так как в нее не входит адрес массива) и выполняется быстрее, так как этот адрес не надо каждый раз считывать из памяти. Базово-индексная адресация со смещением. Адресуется память (байт или слово). Относительный адрес операнда определяется как сумма содержимого двух регистров и смещения. Это способ адресации является развитием предыдущего. В нем используются те же пары регистров, но полученный с их помощью результирующий адрес можно еще сместить на значение указанной в команде константы. Как и в случае базово-индексной адресации, константа может представлять собой индекс (и тогда в одном из регистров должен содержаться базовый адрес памяти), но может быть и базовым адресом. В последнем случае регистры могут использоваться для хранения составляющих индекса. Приведем формальный пример рассматриваемого режима адресации. Пусть в сегменте данных определен массив из 24 байтов, в котором записаны коды латинских и русских символов верхнего ряда клавиатуры:

sims db "QWERTYUIOP{}'

db "ЙЦУКЕНПШЦЗХЪ'

Последовательность команд

mov BX,12 ;Число байтов в строке

mov SI, 6

mov DL,syms[BX][SI]

загрузит в регистр DL элемент с индексом 6 из второго ряда, т.е. код ASCII буквы Г. Тот же результат можно получить, загрузив в один из регистров не индекс, а адрес массива:

mov BX, off set sym

mov SI,6

mov DL, 12 [BX] [SI]

Пример программы, выводящей строку «Hello World!!», использующей различные способы адресации и функции ЯВУ С:

#include <dos.h>

#include <conio.h>

// объявляем переменную с кодом цвета

char color = 3;

void main() {

// очиства экрана

clrscr();

// начало ассемблерной вставки

asm {

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

push ax ;

push es ;

// в сегментный регистр es - адрес начала видеопамяти текстового режима

mov ax, 0B800h ;

mov es, ax ;

// в ячейку памяти es:0 соответствующую первому знакоместу

// (левому верхнему углу текстового экрана) записываем код символа ‘H’

// применяя непосредственную адресацию,

// а в ячейку es:1 соответствующую атрибутам первого знакоместа

// записываем код атрибутов

mov byte ptr es:0, 'H' ; // код символа

mov byte ptr es:1, 1 ; // атрибуты изображения символа

// в ячейку памяти es:2 соответствующую второму знакоместу

// записываем код символа ‘e’ применяя непосредственную адресацию

mov al, 'e' ; //

mov es:2, al ;

// в ячейку памяти es:2 соответствующую атрибутам второго знакоместа

// записываем атрибуты символа ‘e’ применяя регистровую адресацию

mov al, 2 ;

mov es:3, al ;

mov bx, 4 ;

mov byte ptr es:[bx], 'l' ;

// в ячейку памяти es:[bx] соответствующую атрибутам третьего знакоместа

// записываем код цвета 3 применяя прямую адресацию

// указывая в команде mov al, color имя переменной

inc bx ;

mov al, color ;

mov es:[bx], al ;

mov byte ptr es:[bx]+1, 'l' ;

mov byte ptr es:[bx]+2, 4 ;

mov di, 3 ;

mov byte ptr es:[bx][di], 'o' ;

mov byte ptr es:[bx][di+1], 5 ;

mov si, 5 ;

mov word ptr es:[bx][si], ' ' ;

add si, 2 ;

mov ax, 0x0657 ;

// \/\/

// | |

// | +--- 57h – код символа 'W'

// +----- 06h – код атрибутов символа

mov es:[bx][si], ax ;

add si, 2 ;

mov word ptr es:[bx][si], 076Fh ;

// \/\/

// | |

// | +--- 6Fh – код символа 'o'

// +----- 07h – код атрибутов символа

// восстанавливаем содержимое использованных регистров

pop es ;

pop ax ;

}

pokeb(0xB800, 0x0010, 'r');

pokeb(0xB800, 0x0011, 8);

poke(0xB800, 0x0012, 0x096C);

// \/\/

// | |

// | +--- 6Ch – код символа 'l'

// +----- 09h – код атрибутов символа

unsigned char far *ch; // описываем указатель на байт

// устанавливаем его на адрес 0xB800:0x0014 – позицию символа ‘d’

ch = (unsigned char far *) MK_FP(0xB800, 0x0014);

// \ / \ / \ /

// --------\/-------- -\/- -\/-

// | | |

// | | +---- смещение соответствующее

// | | десятому знакоместу

// | | 0x0014 = 20, 20 / 2 = 10

// | |

// | +------------ сегментный адрес

// | видеопамяти

//

// +------------------------------ приведение типа void*

// (бестипового указателя)

// к типу unsigned char far *

*ch = 'd'; // помещаем в ячейку 0xB800:0x0014 код символа ‘d’

*(ch+1) = 10; // помещаем в ячейку 0xB800:0x0015 атрибуты символа ‘d’

unsigned int far *cha; // описываем указатель на слово

// устанавливаем его на адрес 0xB800:0x0016 – позицию символа ‘!’

cha = (unsigned int far *) MK_FP(0xB800, 0x0016);

*cha = 0x0921;

// \/\/

// | |

// | +--- 21h – код символа ‘!’

// +----- 09h – атрибуты символа ‘!’

// переходим к ячейке памяти для следующего знакоместа

cha++; // ОБРАТИТЕ ВНИМАНИЕ адрес cha увеличивается на 2

// т.е. на размер типа, на который указывает cha

// т.е. на sizeof(int)

*cha = 0x8921;

// \/\/

// | |

// | +--- 21h – код символа ‘!’

// +----- 89h – атрибуты символа ‘!’:

// 8 – код цвета фона

// 9 – код цвета символа

// для сравнения выводим символ ‘!’ с использованием функций

// библиотеки conio.h

gotoxy(14, 1); // переход к позиции 14 символа в 1 строке

textcolor(7); // установка цвета 7 (серый)

cprintf("!"); // вывод символа ‘!’

}

Просмотреть ассемблерный код, который генерирует компилятор С можно выполнив команду:

c:\BC\BIN>bcc -S -Ic:\BC\INCLUDE -Lc:\BC\LIB ll2.cpp

если компилятор ВС размещен в каталоге c:\BC\BIN .

II Изучение способов определения состава оборудования в MS-DOS

Составить на ЯВУ С программу получения сведений о составе оборудования ПЭВМ:

  1. тип ПЭВМ;

  2. дату издания BIOS;

  3. размер ОЗУ (основной памяти);

  4. наличие, количество и тип НГМД;

  5. наличие математического сопроцессора;

  6. текущий режим адаптера дисплея;

  7. количество установленных адаптеров последовательного порта и их базовые адреса;

  8. наличие манипулятора «джойстик»;

  9. количество адаптеров параллельного порта и их базовые адреса.

Получение указанной информации реализовать всеми возможными способами: с использованием ассемблерных вставок, средств BIOS и DOS, функций и макросов ЯВУ С. Сравнить полученные результаты. Использовать структуры с битовыми полями.

Определение размера ОЗУ обращением к ячейкам CMOS реализовать на языке Ассемблера в виде внешней процедуры с использованием раздельной компиляции. Процедура должна выводить сообщение о начале и окончании своей работы, с использованием обращений к функциям ЯВУ С.