- •Методическое пособие по выполнению лабораторных работ по курсу «Системное программное обеспечение и операционные системы»
- •Предисловие
- •1. Лабораторная работа № 1.
- •1.1. Теоретические сведения
- •1.3. Подключение отладчика
- •1.4. Контроль переменных и данных различного типа
- •1.5. Варианты заданий
- •2.1. Теоретические сведения
- •1.6. Контрольные вопросы
- •2. Лабораторная работа № 2 Отладка средствами ассемблера
- •3.2.Требования к программе.
- •Связь полей fat с физическим pасположением кластеров на диске показана на рис.4.1.
- •4.2.Требования к программе.
- •4.3. Варианты заданий.
- •4.4.Контрольные вопросы
- •5. Лабораторная работа № 5 Динамически подключаемые библиотеки dll в win32
- •5.1. Теоретические сведения
- •Создание файла Test.Def. Для создания файла Test.Def необходимо выполнить следующие инструкции:
- •5.2.Требования к программе:
- •5.3.Варианты заданий
- •5.4.Контрольные вопросы
- •6. Лабораторная работа №6 Функции и свойства потоков и процессов в win32
- •6.1. Теоретические сведения
- •6.2.Требования к программе:
- •6.3. Варианты заданий
- •6.4.Контрольные вопросы
- •7. Лабораторная работа № 7 Системный Реестр в windows nt.
- •7.1. Теоретические сведения
- •7.2.Требования к программе:
- •8.2.Требования к программе:
- •9.2.Требования к программе:
- •9.3. Варианты заданий.
- •9.4.Контрольные вопросы
- •10. Лабораторная работа № 10 Стили окон.
- •10.1. Теоретические сведения
- •Список рекомендуемой литературы
1.6. Контрольные вопросы
Какие существую проблемы в связи с ошибками?
Типы бывают типы ошибок, когда возникают?
Как к проекту подключаются дополнительные модули?
Как выполняется расшифровка сообщений об ошибках отладчика?
Как выполняется запуск отладчика.
Для чего предназначено меню Build и содержащиеся в нем команды? Привести краткое описание команд.
Для чего предназначена панель Debug и содержащиеся в ней команды? Привести краткое описание команд.
Какая информация отображается в окне Variables?
Какая информация отображается в окне Watch?
Какая информация отображается в окне Registers?
Какая информация отображается в окне Memory?
Какая информация отображается в окне Call Stack?
Какая информация отображается в окне Disassembly?
Как осуществляется форматирование представления переменных в окне Watch?
2. Лабораторная работа № 2 Отладка средствами ассемблера
Порой необходимо отлаживать программу, когда отладочная информация недоступна. В таком случае возможна только отладка дизассемблированного кода. В данной лабораторной работе вам предстоит изучить методы отладки средствами ассемблера.
Цель работы. Построить простейшее приложение, показать в окне отладчика дизассемблированный код, поставить в соответствие функциям С++ код ассемблера.
2.1. Теоретические сведения
Основные команды ассемблера. Ниже описаны все непривилегированные команды процессоров Intel серии х86, включая команды расширений IA NPX (чаще называемый FPU — расширение для работы с числами с плавающей запятой) и IA MMX (мультимедийное расширение). Для каждой команды указана форма записи, название и модель процессоров Intel, начиная с которой она поддерживается: 8086, 80186, 80286, 80386, 80486, Р5 (Pentium), MMX, P6 (Pentium Pro и Pentium II).
Пересылка данных. Табл. 2..1.
Команда: |
MOV приемник, источник |
Назначение: |
Пересылка данных |
Процессор: |
8086 |
Базовая команда пересылки данных. Копирует содержимое источника в приемник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда
mov ax,bx
эквивалентна выражению
ах := bх; языка Паскаль или
ах = bх; языка С,
за исключением того, что команда ассемблера позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора.
В качестве источника для MOV могут использоваться: число (непосредственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же размера — байт, слово или двойное слово.
Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой.
Нельзя помещать в сегментный регистр непосредственный операнд — , эти операции выполняют двумя командами (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.
Загрузка регистра SS командой MOV автоматически запрещает прерывания до окончания следующей за этим команды MOV, так что можно загрузить SS и ESP двумя последовательными командами MOV, не опасаясь, что в этот момент произойдет прерывание, обработчик которого получит неправильный стек. В любом случае для загрузки значения в регистр SS предпочтительнее команда
Пересылка данных. Табл. 2.2
Команда: |
CMOVcc приемник, источник |
Назначение: |
Условная пересылка данных |
Процессор: |
P6 |
Это набор команд, которые копируют содержимое источника в приемник, если удовлетворяется, то или иное условие (см. табл.2.3). Источником может быть регистр общего назначения или переменная, а приемником— только регистр. Условие, которое должно удовлетворяться,— просто равенство нулю или единице тех или иных флагов из регистра FLAGS, но, если использовать команды CMOVcc сразу после команды СМР (сравнение) с теми же операндами, условия приобретают особый смысл, например:
cmp ах,bх ; сравнить ах и bх
cmovl ax,bx ; если ах < bх, скопировать bх в ах
Слова «выше» и «ниже» в таблице 2.3. относятся к сравнению чисел без знака, слова «больше» и «меньше» учитывают знак.
Разновидности команды CMOVcc. Табл.2.3
Код команды |
Реальное условие |
Условие для CMP |
CMOVA CMOVNBE |
CF = 0 и ZF = 0 |
если выше если не ниже или равно |
CMOVAE CMOVNB CMOVNC |
CF = 0 |
если выше или равно если не ниже если нет переноса |
CMOVB CMOVNAE CMOVC |
CF = 1 |
если ниже если не выше или равно если перенос |
CMOVBE CMOVNA |
CF = 1 и ZF = 1 |
если ниже или равно если не выше |
CMOVE CMOVZ |
ZF = 1 |
если равно если ноль |
CMOVG CMOVNLE |
ZF = 0 и SF = OF |
если больше если не меньше или равно |
CMOVGE CMOVNL |
SF = OF |
если больше или равно если не меньше |
CMOVL CMOVNGE |
SF <> OF |
если меньше если не больше или равно |
CMOVLE CMOVNG |
ZF = 1 и SF <> OF |
если меньше или равно если не больше |
CMOVNE CMOVNZ |
ZF = 0 |
если не равно если не ноль |
CMOVNO |
OF = 0 |
если нет переполнения |
CMOVO |
OF = 1 |
если есть переполнение |
CMOVNP CMOVPO |
PF = 0 |
если нет четности если нечетное |
CMOVP CMOVPE |
PF = 1 |
если есть четность если четное |
CMOVNS |
SF = 0 |
если нет знака |
CMOVS |
SF = 1 |
если есть знак |
Табл.2.4.
Команда: |
XCHG операнд1, операнд2 |
Назначение: |
Обмен операндов между собой |
Процессор: |
8086 |
Содержимое операнда 2 копируется в операнд 1, а старое содержимое операнда 1 — в операнд 2. XCHG можно выполнять над двумя регистрами или над регистром и переменной.
xchg eax,ebx ; то же, что три команды на языке С:
temp = eax;
eax = ebx;
ebx = temp;
xchg al,al ; а эта команда не делает ничего
Табл.2.5
Команда: |
BSWAP регистр32 |
Назначение: |
Обмен байт внутри регистра |
Процессор: |
80486 |
Обращает порядок байт в 32-битном регистре. Биты 0—7 (младший байт младшего слова) меняются местами с битами 24—31 (старший байт старшего слова), а биты 8—15 (старший байт младшего слова) меняются местами с битами 16—23 (младший байт старшего слова).
mov eax,12345678h
bswap eax ; теперь в еах находится 78563412h
Чтобы обратить порядок байт в 16-битном регистре, следует использовать команду XCHG:
xchg al,ah ; обратить порядок байт в АХ
В процессорах Intel команду BSWAP можно использовать и для обращения порядка байт в 16-битных регистрах, но в некоторых совместимых процессорах других фирм этот вариант BSWAP не реализован.
Табл.2.6.
Команда: |
PUSH источник |
Назначение: |
Поместить данные в стек |
Процессор: |
8086 |
Помещает содержимое источника в стек. Источником может быть регистр, сегментный регистр, непосредственный операнд или переменная. Фактически эта команда копирует содержимое источника в память по адресу SS:[ESP] и уменьшает ESP на размер источника в байтах (2 или 4). Команда PUSH практически всегда используется в паре с POP (считать данные из стека). Так, например, чтобы скопировать содержимое одного сегментного регистра в другой (что нельзя выполнить одной командой MOV), можно использовать такую последовательность команд:
push cs
pop ds ; теперь DS указывает на тот же сегмент, что и CS
Другое частое применение команд PUSH/POP— временное хранение переменных, например:
push eax ; сохраняет текущее значение ЕАХ
... ; здесь располагаются какие-нибудь команды,
; которые используют ЕАХ, например CMPXCHG
pop eax ; восстанавливает старое значение ЕАХ
Начиная с 80286, команда PUSH ESP (или SP) помещает в стек значение ESP до того, как эта же команда его уменьшит, в то время как на 8086 SP помещался в стек уже уменьшенным на два.
Табл.2.7
Команда: |
POP приемник |
Назначение: |
Считать данные из стека |
Процессор: |
8086 |
Помещает в приемник слово или двойное слово, находящееся в вершине стека, увеличивая ESP на 2 или 4 соответственно. POP выполняет действие, полностью обратное PUSH. Приемником может быть регистр общего назначения, сегментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменная. Если в роли приемника выступает операнд, использующий ESP для косвенной адресации, команда POP вычисляет адрес операнда уже после того, как она увеличивает ESP.
Табл.2.8
Команда: |
PUSHA PUSHAD |
Назначение: |
Поместить в стек все регистры общего назначения |
Процессор: |
80186 80386 |
PUSHA помещает в стек регистры в следующем порядке: АХ, СХ, DX, ВХ, SP, ВР, SI и DI. PUSHAD помещает в стек ЕАХ, ЕСХ, EDX, ЕВХ, ESP, EBP, ESI и EDI. (В случае SP и ESP используется значение, которое находилось в этом регистре до начала работы команды.) В паре с командами POPA/POPAD, считывающими эти же регистры из стека в обратном порядке, это позволяет писать подпрограммы (обычно обработчики прерываний), которые не должны изменять значения регистров по окончании своей работы. В начале такой подпрограммы вызывают команду PUSHA, а в конце— РОРА.
На самом деле PUSHA и PUSHAD— одна и та же команда с кодом 60h. Ее поведение определяется тем, выполняется ли она в 16- или в 32-битном режиме. Если программист использует команду PUSHAD в 16-битном сегменте или PUSHA в 32-битном, ассемблер просто записывает перед ней префикс изменения размерности операнда (66h).
Это же будет распространяться на некоторые другие пары команд: РОРА/POPAD, POPF/POPFD, PUSHF/PUSHFD, JCXZ/JECXZ, CMPSW/CMPSD, INSW/INSD, LODSW/LODSD, MOVSW/MOVSD, OUTSW/OUTSD, SCASW/SCASD и STOSW/STOSD.
Табл.2.9
Команда: |
POPA POPAD |
Назначение: |
Загрузить из стека все регистры общего назначения |
Процессор: |
80186 80386 |
Эти команды выполняют действия, полностью обратные действиям PUSHA и PUSHAD, за исключением того, что помещенное в стек значение SP или ESP игнорируется. РОРА загружает из стека DI, SI, BP, увеличивает SP на два, загружает ВХ, DX, CX, AX, a POPAD загружает EDI, ESI, ЕВР, увеличивает ESP на 4 и загружает ЕВХ, EDX, ЕСХ, ЕАХ.
Табл.2.10.
Команда: |
IN приемник, источник |
Назначение: |
Считать данные из порта |
Процессор: |
8086 |
Копирует число из порта ввода-вывода, номер которого указан в источнике, в приемник. Приемником может быть только AL, АХ или ЕАХ. Источник— или непосредственный операнд, или DX, причем можно указывать только номера портов не больше 255.
Табл.2.11.
Команда: |
OUT приемник, источник |
Назначение: |
Записать данные в порт |
Процессор: |
8086 |
Копирует число из источника (AL, АХ или ЕАХ) в порт ввода-вывода, номер которого указан в приемнике. Приемник может быть либо непосредственным номером порта, либо регистром DX. На командах IN и OUT строится все общение процессора с устройствами ввода-вывода — клавиатурой, жесткими дисками, различными контроллерами, и используются они, в первую очередь, в драйверах устройств. Например, чтобы включить динамик ПК, достаточно выполнить команды:
in al,61h
or al,3
out 61h,al
Табл.2.12.
Команда: |
CWD |
Назначение: |
Конвертирование слова в двойное слово |
Процессор: |
8086 |
Табл.2.13.
Команда: |
CDQ |
Назначение: |
Конвертирование двойного слова в учетверенное |
Процессор: |
80386 |
Команда CWD превращает слово в AХ в двойное слово, младшая половина которого (биты 0—15) остается в АХ, а старшая (биты 16—31) располагается в DX. Команда CDQ выполняет аналогичное действие по отношению к двойному слову в ЕАХ, расширяя его до учетверенного слова в EDX:EAX. Эти команды всего лишь устанавливают все биты регистра DX или EDX в значение, равное значению старшего бита регистра АХ или ЕАХ, сохраняя таким образом его знак.
Табл.2.14.
Команда: |
CBW |
Назначение: |
Конвертирование байта в слово |
Процессор: |
8086 |
Табл.2.15.
Команда: |
CWDE |
Назначение: |
Конвертирование слова в двойное слово |
Процессор: |
80386 |
CBW расширяет байт, находящийся в регистре AL, до слова в АХ, CWDE расширяет слово в АХ до двойного слова в ЕАХ. CWDE и CWD отличаются тем, что CWDE располагает свой результат в ЕАХ, в то время как CWD, команда, выполняющая точно такое же действие, располагает результат в паре регистров DX:AX. Так же как и команды CWD/CDQ, расширение выполняется путем установки каждого бита старшей половины результата равным старшему биту исходного байта или слова, то есть:
mov al,0F5h ; AL = 0F5h = 245 = -11
cbw ; теперь АХ = 0FFF5h = 65 525 = -11
Так же как и в случае с командами PUSHA/PUSHAD, пара команд CWD/CDQ— это одна команда с кодом 99h, и пара команд CBW/CWDE— одна команда с кодом 98h. Интерпретация этих команд зависит от того, в каком (16-битном или в 32-битном) сегменте они исполняются, и точно так же, если указать CDQ или CWDE в 16-битном сегменте, ассемблер поставит префикс изменения разрядности операнда.
Табл.2.16.
Команда: |
MOWSX приемник, источник |
Назначение: |
Пересылка с расширением знака |
Процессор: |
80386 |
Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет знак аналогично командам CBW/CWDE.
Табл.2.17.
Команда: |
MOWZX приемник, источник |
Назначение: |
Пересылка с расширением нулями |
Процессор: |
80386 |
Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет нулями, то есть команда
movzx ax,bl
эквивалентна паре команд
mov al,bl
mov ah,0.
Табл.2.18.
Команда: |
XLAT адрес XLATB |
Назначние: |
Трансляция в соответствии с таблицей |
Процессор: |
8086 |
Команда: помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX) со смещением относительно начала таблицы равным AL. В качестве аргумента для XLAT в ассемблере можно указать имя таблицы, но эта информация никак не используется процессором и служит только как комментарий. Если этот комментарий не нужен, можно применить форму записи XLATB. В качестве примера использования XLAT можно написать следующий вариант преобразования шестнадцатеричного числа в ASCII-код соответствующего ему символа:
mov al,0Ch
mov bx, offset htable
xlatb
Если в сегменте данных, на который указывает регистр, было записано
htable db "0123456789ABCDEF"
то теперь AL содержит не число 0Сh, а ASCII-код буквы «С». Разумеется, это преобразование можно выполнить, используя гораздо более компактный код всего из трех арифметических команд, который будет рассмотрен в описании команды DAS, но с XLAT можно выполнять любые преобразования такого рода.
Табл.2.19.
Команда: |
LEA приемник, источник |
Назначение: |
Вычисление эффективного адреса |
Процессор: |
8086 |
Вычисляет эффективный адрес источника (переменная) и помещает его в приемник (регистр). С помощью LEA можно вычислить адрес переменной, которая описана сложным методом адресации, например по базе с индексированием. Если адрес 32-битный, а регистр-приемник 16-битный, старшая половина вычисленного адреса теряется, если наоборот, приемник 32-битный, а адресация 16-битная, то вычисленное смещение дополняется нулями.
Команду LEA часто используют для быстрых арифметических вычислений, например умножения:
lea bx,[ebx+ebx*4] ; ВХ=ЕВХ*5
или сложения: lea ebx,[eax+12] ; ЕВХ=ЕАХ+12
(эти команды меньше, чем соответствующие MOV и ADD, и не изменяют флаги)
2.2. Варианты задани
2.3.Контрольные вопросы:
Основные команды ассемблера
Команды пересылки
Арифметические команды
Способы адресации
Окно дизассемблера в отладчике
3.Лабораторная работа № 3
Логические диски в операционной системе Windows NT
В операционных системах Windows 98/NT/XP реализована поддержка 32-битного доступа к файлам и дискам.
Цель работы: написать программу , которая отображает информацию о логических дисках в текстовом виде.
3.1. Теоретические сведения
Основные функции API для работы с логическими томами. DWORD GetLogicalDrives (void) определяет логические диски на данном ПК, возвращает 32-битное значение, каждый бит которого указывает , существует ли соответствующий логический диск (например, бит 0 установлен, если в системе виден диск A:\).
UINT GetDriveType(LPTSTR lpszRootPathName) возвращает тип диска, идентифицируемого параметром lpszRootPathName – указателем на корневой каталог.
Следующая функция, формирует информацию о конкретной файловой системе и определяет указатели
GetVolumeInformation (LPTSTR lpRootPathName,
LPTSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPTSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize), где
параметр lpVolumeNameBuffer.возвращает метку тома,
параметр nVolumeNameSize определяет максимальный размер буфера в символах,
параметр lpVolumeSerialNumber - серийный номер тома,
параметр lpMaximumComponentLength - максимальное количество допустимых символов, допустимое в именах каталогов и файлах,
параметр lpFileSystemFlags - флаги файловой системы,
параметр lpFileSystemNameBuffer указывает на буфер файловой системы, параметр nFileSystemNameSize определяет максимальный размер этого буфера.
BOOL SetVolumeLabel (LPTSTR lpRootPathName, LPTSTR lpVolumeName) изменяет метку тома . Первый параметр задает корневой каталог, а второй определяет новую метку тома.
BOOL GetDiskFreeSpace (LPTSTR lpRootPathName,
LPDWORD lpSectorPerCluster,
LPDWORD lpBytesPerSector,
LPDWORD lpFreeCluster,
LPDWORD lpClusters)
определяет метку тома, где
параметр lpSectorPerCluster возвращает количество секторов в кластере;
параметр lpBytesPerSector – количество байтов в секторе;
параметр lpFreeCluster - количество свободных кластеров;
параметр lpClusters - общее количество кластеров.
