Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Shpory_Sp_(1)

.pdf
Скачиваний:
8
Добавлен:
08.03.2016
Размер:
1 Mб
Скачать

По умолчанию в реальном режиме работы микропроцесор запрещает прерывание автоматически и поэтому для аргументации давать команду STI, чтобы разрешить появление более приоритетных прерываний.

24. Побудова простих асемблерів.

Входом для ассемблера является исходный модуль, содержащий текст программы, который обычно представлен в виде некоторого файла, выполненного с помощью текстового редактора. Выходом ассемблера является – объектный модуль, содержащий машинный код и информацию для объединения данного модуля с другими модулями. Объектный модуль также запоминается в виде файла.

На практике обычно используются двухпроходовые ассемблеры. Внутренняя структура упрощенного двухпроходового ассемблера представлена на рис.1. Он называется двухпроходовым, так как сканирует исходный код 2 раза.

Цель первого прохода – получить информацию о местоположении идентификаторов. Цель второго прохода – генерация машинного кода.

Для локализации идентификаторов в ассемблере предусмотрен счетчик ячеек (адресов). Он фиксирует относительные позиции (т.е. смещения) операторов внутри каждого сегмента.

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

Таблица имен состоит из имени идентификатора, значения его смещения, имени сегмента, в котором определен данный идентификатор, и типа идентификатора.

На втором проходе эта информация используется при генерации команд, операнды которых содержат идентификаторы.

Кроме таблицы имен, ассемблер использует 2 таблицы о командах и директивах, которые называются таблицами фиксированных имен. В этих таблицах размещены мнемоники инструкций ассемблера, коды операций и форматы команд, а также информация, необходимая для увеличения (инкремента) счетчика ячеек, и т.д.

Если в левом поле оператора встречается метка или переменная, то в таблицу имен помещается ее имя, текущее значение счетчика ячеек и другие атрибуты. Если одна и та же метка или переменная определяются дважды, то фиксируется ошибка. Ошибка также фиксируется в случае, если мнемоническое имя команды или директивы не находится ни в одной из таблиц фиксированных имен. Если встречается директива END, то первый проход ассемблера завершается и начинается второй проход.

Во время второго прохода осуществляется ассемблирование машинных команд, а также ввод констант из директив определения данных и подготовка информации для редактора связей. Если операнды команд или директив содержат выражения, то они вычисляются, и определяется смещение. Если на втором проходе встречается директива END, то процесс ассемблирования завершается и на экран монитора и/или на диск выводятся объектный модуль и листинг программы.

При разработке ассемблера рекомендуется придерживаться следующего формата ассемблерных инструкций:

Метка: Мнемоника Операнд, Операнд ; комментарий.

19.Комунікаційний порт COM. Прийом даних в MS DOS. uses crt;

var b:byte; begin

Port[$3F8+3]:=$80; Port[$3F8]:=$18;{115200/24=4800} Port[$3F8+1]:=0;

Port[$3F8+3]:=3;{word length=8 bit, 1 bit is stopped} Port[$3F8+1]:=0;{interrupts off} Port[$3F8+4]:=$B;{modem control,

set signals on lines DTR and RTS and interrupts on} writeln('receive messages');

repeat

if (Port[$3F8+5] and 1=1) then begin b:=Port[$3F8];

writeln(b);

end;

until keypressed; end.

20.Комунікаційний порт COM. Передача даних в MS DOS. uses crt;

var b:byte; begin

Port[$3F8+3]:=$80; Port[$3F8]:=$18;{115200/24=4800} Port[$3F8+1]:=0;

Port[$3F8+3]:=3;{word length=8 bit, 1 bit is stopped} Port[$3F8+1]:=0;{interrupts off} Port[$3F8+4]:=$B;{modem control,

set signals on lines DTR and RTS and interrupts on} writeln('sending messages');

repeat

if (Port[$3F8+5] and 20=1) then begin Port[$3F8]:=b;

writeln(b);

end;

until keypressed; end.

WriteAX proc near

;Using : in ax must be string to print pusha

mov si,10 mov cx,0

@@w1:mov dx,0 div si

add dx,'0' push dx inc cx cmp ax,0

jnz @@w1 mov ah,2

@@w2: pop dx int 21h

loop @@w2 popa

ret WriteAX

30.Особливості програмування в захищеному режимі (режим віртуальної адреси).

При программировании в защищенном режиме следует учесть возможность многозадачности,

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

Следует также учесть возможности механизма ввода вывода с учетом привилегий (процессы

сболее низким уровнем не получают прямого доступа к устройствам).

см. также 19.

Адресс вычисляется с помошью селектора и смещения. Селектор содержит адресс дескриптора в таблице дескриптора, уровень запраш привилегий и указатель на табл.ицу (gdt, ldt).

Смещение 32разрядное и может определять сегмент размером <1Гб (4Гб при устан ьите гранулярности).

см. также 22.

Переход в защищенный режим осуществляется установкой младшего бита в регистре CR0 (выход – сброс бита)

31. Селектори та дескриптори сегментів (захищений режим). Тіньові регістри.

Принцип формирования физического адреса: Селектор:Смещение (по 32 бита)

Поступает на «Сегментное преобазование табл. дескрипторов» Получается линейный адресс (32 бита)

И через страничное преобразование получается физический адресс(32 бита)

Сегментный регистр в защищенном режиме содержит не сегменты, а селекторы, которые состоят из 3-х полей:

Селектор: [индекс(13 бит)][Ti(1бит)][RPL (1 бит)]

Ti – индекс таблицы (0-gdt, 1-ldt)

RPL – запрашиваемый уровень привилегий Индекс – номер таблицы дескрипторов Пример dt

0.Пустой дескриптор

1.дескриптор

2.дескриптор

3. ....

Таблица дескрипторов создается операционной системой, и программы не имеют к ней доступа. Каждая программа может иметь свою ldt, и использовать gdt

Если отключено страничное преобразование, то линейный адрес соответствует физическому. Лин адрес = базовый+смещение

Существуют 2 типа таблиц дескрипторов : локальные и глобальная обычно для их хранения отводится спец. место в о.п.

Глобальная таблица одна и принадлежит опер. сист.

Локальных таблиц может быть несколько, у каждой задачи 1 лок. табл. дескр.

Все виртуальное пространство адресов делится на 2 части, к одной части доступ через gdt, а к другой – через ldt

При переключении задач gdt не изменяется, а ldt замещается на ldt новой задачи. Структура:

Задача 1

Задача 1

LDT

LDT

Задача 1

Задача 1

LDT

GDT

Структура дескриптора дескрипторной таблицы:

[Баз адрес ][атр1][ атр2 ][ баз адрес сегмента ][ граница сегмента ] Защита сегментов памяти от несанкционированного доступа выполняется процессором на аппаратном уровне.

37. Завантаження таблиць дескрипторів (наприклад, таблиці GDT).

В защищенном режиме любой запрос к памяти со стороны операционной системы должен быть санкционированным. Микропроцессор аппаратно контролирует доступ к любому адресу. Каждый участок памяти выделяемый той или иной программе должен быть описан в соответствующем дескрипторе который определяет права доступа расположенной информации по отношению к другим участкам. Дескрипторы группируются по трем видам дескрипторных таблиц: GDTтаблица глобальных дескрипторов, LDTтаблица локальных дескрипторов, IDTтаблица дескрипторов прерываний.

При переходе в защищенный режим в первую очередь нужно позаботиться о формировании GDT. Она состоит из полей по количеству описываемых сегментов.

На языке MASM соответствующее поле может быть описано descr struc

limit

dw

0

base1

dw 0

base1

db

0

atr

db

0

lim_atr db 0 base_3 db 0 ends

Саму таблицу GDT можно описать так

Gdt_seg segment

Gdt_0

descr <0,0,0,0,0,0>

Gdt_gdt_8

descr <0,0,0,0,0,0>

Gdt_ldt_10

descr <0,0,0,0,0,0>

Gdt_ds_18

descr <0,0,0,0,0,0>

Gdt_es_20

descr <0,0,0,0,0,0>

Gdt_ss_28

descr <0,0,0,0,0,0>

Gdt_cs_30 descr <0,0,0,0,0,0> Gdt_size=$-gdt_0-1

Gdt_seg ends

Адрес таблицы GDT должен находиться в специальном системном регистре gdtr для загрузки которого выделена специальная команда lgdt.

point struc lim dw 0 adr dd 0 ends

data

point_gdt point<gdt_size,0>

……. code

xor eax,eax mov ax,gdt_seg shl eax,4

mov dword ptr point_gdt.adr,eax lgdt pword point_gdt

21. Комунікативний порт COM. Прийом даних в Winows.

#include "stdafx.h" #include <conio.h> #include <Windows.h> #include <iostream>

int _tmain(int argc, _TCHAR* argv[])

{

HANDLE hSerial;

LPCTSTR sPortName = L"COM2";

hSerial = CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if(hSerial == INVALID_HANDLE_VALUE)

{

if(GetLastError()==ERROR_FILE_NOT_FOUND)

{

std::cout << "serial port does not exist.\n";

}

std::cout << "some other error occurred.\n";

}

DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength=sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams))

{

std::cout << "getting state error\n";

}

dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=7; dcbSerialParams.StopBits=ONESTOPBIT;

dcbSerialParams.Parity=NOPARITY; char answer[] ="Y";

DWORD dwSize = sizeof(answer); // размер этой строки

DWORD dwBytesWritten; // тут будет количество собственно переданных байт

DWORD iSize; char sReceivedChar; int i = 0;

std::cout<<"Wait message..."<<std::endl; bool DialogState = false;

while (true)

{

ReadFile(hSerial, &sReceivedChar, 1, &iSize, 0); // получаем 1 байт

if (iSize > 0)

{

if (sReceivedChar == '1')

{

std::cout<<"Do you want recive message (Y/N)?\t"; std::cin>>answer;

BOOL iRet = WriteFile (hSerial,answer,dwSize,&dwBytesWritten,NULL);

}

if (answer != "Y")

{

std::cout<<"Transmit denied! Press any key to exit..."; _getch();

return 0;

}

if (sReceivedChar == '0' )

{

break;

}

i++;

if (i == 1)

{

continue;

}

std::cout<<sReceivedChar;

// если что-то принято, выводим

}

}

std::cout<<"\nPress any key to exit..."; _getch();

return 0;

}

22. Комунікативний порт COM. Передача даних в Winows.

#include "stdafx.h" #include <conio.h> #include <Windows.h> #include <iostream>

HANDLE hSerial;

LPCTSTR sPortName = L"COM1";

int _tmain(int argc, _TCHAR* argv[])

{

int i = 0;

std::cout<<"Press <Enter> to start, please...\n"; _getch();

hSerial = CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if(hSerial == INVALID_HANDLE_VALUE)

{

if(GetLastError()==ERROR_FILE_NOT_FOUND)

{

std::cout << "serial port does not exist.\n";

}

std::cout << "some other error occurred.\n";

}

DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength=sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams))

{

std::cout << "getting state error\n";

}

dcbSerialParams.BaudRate=CBR_9600; dcbSerialParams.ByteSize=8; dcbSerialParams.StopBits=ONESTOPBIT; dcbSerialParams.Parity=NOPARITY; if(!SetCommState(hSerial, &dcbSerialParams))//

{

std::cout << "error setting serial port state\n";

}

char data[] = "Hello"; // строка для передачи

char *symbol_null = "0";//flag of the end of message char *HtH = "1";

DWORD dwSize = sizeof(data); // размер этой строки

DWORD dwBytesWritten; // тут будет количество собственно переданных байт

BOOL iRet = WriteFile(hSerial, HtH, sizeof(HtH),0,NULL);//send synchro

DWORD iSize; char sReceivedChar; char answer;

bool DialogState = true; while (true)

{

ReadFile(hSerial, &answer, 1, &iSize, 0); // получаем 1 байт if(iSize > 0)

{

if (answer == 'N')

{

DialogState = false;

}

iRet = WriteFile (hSerial,data,dwSize,&dwBytesWritten,NULL);//send message iRet = WriteFile(hSerial, symbol_null, sizeof(symbol_null),&dwBytesWritten,

NULL);//send the end of message

std::cout << dwSize << " Bytes in string. " << dwBytesWritten << " Bytes sended. " <<

std::endl

<<"Transmitted message:"<<std::endl<<"'"<<data<<"'"<<std::endl;

break;

}

}

if (DialogState == true)

{

std::cout<<"\Message was send!";

}

else

{

std::cout<<"\nTransmit was denied!";

}

std::cout<<"Press any key to exit..."; _getch();

return 0;

}

4. Керування зовнішніми пристроями на фізичному рівні (приклади)

#include <bios.h>

//Консольный ввод-вывод

#include <conio.h>

//Для функции atoi

#include <stdlib.h>

#define COM1 0

#define DATA_READY 0x100 #define TRUE 1

#define FALSE 0

#define SETTINGS (_COM_9600 | _COM_CHR8 | _COM_STOP1 | _COM_NOPARITY)

int main(int ArgC, char * ArgV[])

{

unsigned in, out, status, commnum; if( ArgC == 1 ){

cprintf("Pass COM port number as first argument (COM1=0, COM2=1...)\r\n"); return 0;

};

commnum = atoi(ArgV[1]);

cprintf("Working with COM%i\r\n",(commnum+COM1+1));

_bios_serialcom(_COM_INIT, COM1 + commnum, SETTINGS); cprintf("... _BIOS_SERIALCOM for PowerAnts, press [ESC] to exit ...\r\n");

for (;;)

{

status = _bios_serialcom(_COM_STATUS, COM1 + commnum, 0); if (status & DATA_READY)

if ((out = _bios_serialcom(_COM_RECEIVE, COM1 + commnum, 0) & 0x7F) != 0) putch(out);

if (kbhit())

{

if ((in = getch()) == '\x1B') break;

_bios_serialcom(_COM_SEND, COM1 + commnum, in);

}

}

return 0;

}

23. API ОС Windows для роботи з зовнішніми пристроями та файлами

WinApi для роботи з файлами в с++:

CreateFile

OpenFile

ReadFile

WriteFile

CloseFile

DeleteFile

CopyFile FindFirstFile FindNextFile GetFileSize

так створюємо файл

{ Handle FileHandle; FileHandle=CreateFile("file1.txt",GENERIC_READ |

GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_NEW,

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);

CloseHandle(FileHandle);}

так відкриваємо файл

{Handle FileHandle;

FileHandle= OpenFile("Settings.ini", Buf, OF_Create | OF_READWRITE | OF_SHARE_EXCLUSIVE); CloseHandle(FileHandle);

}

так читаємо інфу

Handle FileHandle; char Buf[1000];

WriteFile(FileHandle, Buf, sizeof(buf),NULL);

}

так копіюємо файл

{ CopyFile("C:\Temp\test1.txt","C:\Temp\test2.txt", true); // если указать только имя файла, то все действия будут выполнены в папке из которой запущена прога

39. Завантаження регістру GDTR

Местоположение и размер GDT задаѐт регистр GDTR (очевидно, от GDT Register; это не ключевое слово ассемблера, а условное название, которое применяется в документации для обозначения этого регистра), вот описание его формата:

Положение

Описание

Два младших байта

Смещение последнего байта таблицы дескрипторов. То есть

 

размер таблицы в байтах минус 1. Так как дескрипторов должно

 

быть целое число, размер должен делиться на 8 (размер

 

дескриптора в байтах), а смещение последнего байта должно быть

 

равно 8n-1.

Оставшиеся четыре байта

Линейный базовый адрес таблицы дескрипторов.

Регистр GDTR

Для загрузки регистра GDTR существует специальная команда lgdt lgdt pointer_to_new_gdtr

Здесь pointer_to_new_gdtr это указатель на шестибайтную структуру, повторяющую формат GDTR. Инициализация GDT может выглядеть так:

; Вычисляем линейный адрес начала массива дескрипторов

mov

eax, 0

mov

ax, ds

shl

eax, 4

add

eax, offset GDT

; Записываем его в структуру mov dword ptr gdtr + 2, eax

;Загружаем GDTR.

;fword ptr – указатель на шестибайтную структуру

lgdt fword ptr gdtr

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]