Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

44

было освоить ассемблер. Впрочем, в этой книге мы познакомимся со всеми основными функциями DOS и BIOS.

2.8. Префикс программного сегмента (PSP)

Префикс программного сегмента (PSP, Program Segment Prefix) в ОС MS-DOS

предшествует в памяти каждой COM или EXE-программе, и занимает 256 (100h) байт, причем структура PSP одинакова для файлов обоих типов. В COM-программе для PSP необходимо освобождать память директивой org 100h, в программах типа EXE этого делать не требуется. Префикс программного сегмента строит MS-DOS перед загрузкой в память каждой программы и использует его в своих целях, а также предоставляет возможность использовать PSP загруженной программе. Некоторые поля PSP существуют только лишь для совместимости с ранними версиями DOS и с древней операционной системой CP/M.

В табл. 2.2 показана структура префикса программного сегмента.

Я не буду подробно описывать назначение каждого поля, т. к. вряд ли вам это понадобится при программировании в настоящее время, но иметь общее представление о структуре PSP полезно. Единственное вам может оказаться полезным поле, расположенное по смещению PSP:80h, в котором сохраняются параметры командной строки (в том случае если они были переданы программе при запуске). Подробнее о том, как считать параметры командной строки рассказано в разд. 6.1.

С PSP тесно связаны структуры FCB (File Control Block — блок управления файлом)

иDTA (Disk Transfer Address — область передачи данных). Фактически эти структуры являются частью PSP.

Есть два вида FCB: обычный и расширенный, расположенные соответственно по смещениям PSP:005Ch и PSP:006Ch. В табл. 2.3 приводится структура обычного FCB (всего 37 байт). В табл. 2.4 показан расширенный FCB (всего 44 байта). Эти структуры существуют только для совместимости со старыми версиями MS-DOS и CP/M.

Структура DTA (общий размер 43 байта) располагается по смещению PSP:0080h. Однако адрес начала этой структуры может быть переопределен с помощью функции 1Ah (INT 21h). Структура DTA заполняется и используется функциями поиска файлов.

Таблица 2.2. Структура префикса программного сегмента (PSP)

Относительный

Размер поля

Описание поля PSP

адрес

(в байтах)

 

 

 

 

0000h

2

Команда INT 20h (0CD20h). Если COM-программа

 

 

завершается командой RETN, управление передается на

 

 

эту команду. Существует для совместимости с системой

 

 

CP/M

 

 

 

0002h

2

Адрес следующего сегмента в памяти, расположенного

 

 

после программы. Это поле можно использовать, чтобы

 

 

узнать размер памяти доступной программе (вычитая

 

 

адрес, на которое оно указывает от смещения 0000 PSP).

 

 

Значение возвращается в параграфах, поэтому его

 

 

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

 

 

 

0004h

1

Зарезервировано

 

 

 

0005h

5

Длинный вызов (CALL FAR) диспетчера функций DOS.

 

 

Существует для совместимости с системой CP/M

 

 

 

000Ah

4

Предыдущее содержимое вектора прерывания INT 22h

 

 

(выход из программы). Если программа изменит этот

 

 

вектор для своих целей, то после ее завершения DOS

 

 

восстановит исходный вектор из PSP

 

 

 

000Eh

4

Предыдущее содержимое вектора прерывания INT 23h

 

 

(обработчик нажатия Ctrl-Break). Если программа

 

 

изменит этот вектор для своих целей, то DOS

 

 

восстановит исходный вектор из PSP

 

 

 

 

http://www.sklyaroff.ru

 

 

45

 

 

 

 

Таблица 2.2. (окончание)

 

 

 

 

 

0012h

4

Предыдущее содержимое вектора прерывания INT 24h

 

 

 

(обработчик критических ошибок). Если программа

 

 

 

изменит этот вектор для своих целей, то DOS

 

 

 

восстановит исходный вектор из PSP

 

 

 

 

 

0016h

2

Сегментный адрес PSP программы, которая запустила

 

 

 

данную программу (программы-родителя). Обычно

 

 

 

программой-родителем является COMMAND.COM

 

 

 

 

 

0018h

20

Таблица открытых файлов (JFT, Job File Table). Это

 

 

 

массив из 20 однобайтных элементов, где один байт

 

 

 

отводит на идентификатор. В свободных элементах

 

 

 

таблицы находятся байты 0FFh

 

 

 

 

 

002Ch

2

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

 

 

 

котором содержится набор ASCIIZ-строк, задающих

 

 

 

значения некоторых глобальных переменных

 

 

 

 

 

002Eh

4

Адрес стека SS:SP программы (при последнем вызове

 

 

 

INT 21h)

 

 

 

 

 

 

 

0032h

2

Максимальное число открытых файлов (число элементов

 

 

 

JFT) (по умолчанию 20)

 

 

 

 

 

0034h

4

Дальний адрес JFT (по умолчанию PSP:0018)

 

 

 

 

 

0038h

4

Дальний адрес предыдущего PSP

 

 

 

 

 

003Ch

1

Флаг, указывающий, что консоль находится в состоянии

 

 

 

ввода 2-байтного символа

 

 

 

 

 

003Dh

1

Флаг, устанавливаемый функцией 0B711h прерывания

 

 

 

2Fh (при следующем вызове INT 21h для работы с

 

 

 

файлом имя файла будет заменено новым)

 

 

 

 

 

 

 

003Eh

2

Зарезервировано

 

 

 

 

 

 

 

0040h

2

Версия DOS, которую вернет функция DOS 30h

 

 

 

 

 

 

 

0042h

12

Зарезервировано

 

 

 

 

 

 

 

0050h

2

Команда INT 21h (0CD21h)

 

 

 

 

 

0052h

1

Команда RETF (0СВh)

 

 

 

 

 

 

 

0053h

2

Зарезервировано

 

 

 

 

 

 

 

0055h

7

Область для расширения первого FCB

 

 

 

 

 

005Ch

16

Первый FCB (File Control Block), заполняемый из

 

 

 

первого аргумента командной строки. Это устаревший

 

 

 

способ для получения доступа к файлам (существует для

 

 

 

совместимости со старыми версиями DOS и CP/M).

 

 

 

Смотрите структуру FCB в табл. 2.3

 

 

 

 

 

006Ch

16

Второй FCB, заполняемый из второго аргумента

 

 

 

командной строки

 

 

 

 

 

 

 

 

 

007Ch

4

Зарезервировано

 

 

 

 

 

 

 

 

0080h

128

Это поле может

содержать либо командную строку

 

 

 

(точнее параметры командной строки с пробелами), либо

 

 

 

область DTA (disk transfer area). Эти данные не могут

 

 

 

существовать вместе, поэтому если необходимы

 

 

 

параметры командной строки, то их необходимо

 

 

 

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

 

 

 

какую-нибудь переменную в программе). Первый байт

 

 

 

командной строки, который расположен по адресу

 

 

 

PSP:80h содержит

длину командной строки, а дальше

 

 

 

находятся реальные параметры. Структура DTA показана

 

 

 

в табл. 2.5

 

 

 

 

 

 

 

 

 

http://www.sklyaroff.ru

 

 

46

 

 

 

 

 

 

Таблица 2.3. Обычный блок управления файлом (FCB)

 

 

 

 

 

 

 

 

 

Относительный

Размер поля

 

Описание поля FCB

 

 

адрес

(в байтах)

 

 

 

 

 

 

 

 

 

 

 

 

 

0000h

1

 

 

Буква привода

 

 

 

 

 

 

 

 

 

0001h

8

 

 

Имя файла с пробелами

 

 

 

 

 

 

 

 

 

0009h

3

 

 

Расширение файла с пробелами

 

 

 

 

 

 

 

 

 

000Ch

2

 

 

Номер текущего блока

 

 

 

 

 

 

 

 

 

000Eh

2

 

 

Логический размер записи

 

 

 

 

 

 

 

 

 

0010h

4

 

 

Размер файла

 

 

 

 

 

 

 

 

 

0014h

2

 

 

Дата создания/обновления файла

 

 

 

 

 

 

 

 

 

0016h

2

 

 

Время создания/обновления файла

 

 

 

 

 

 

 

 

 

0018h

8

 

 

Зарезервировано

 

 

 

 

 

 

 

 

 

0020h

1

 

 

Номер текущей записи

 

 

 

 

 

 

 

 

 

0021h

2

 

 

Номер относительно записи

 

 

 

 

 

 

 

 

 

 

 

 

Таблица 2.4. Расширенный блок управления файлом (FCB)

 

 

 

 

 

 

 

 

 

Относительный

Размер поля

 

Описание поля FCB

 

 

адрес

(в байтах)

 

 

 

 

 

 

 

 

 

 

 

 

 

0000h

1

 

 

0FFh (сигнатура расширенного FCB)

 

 

 

 

 

 

 

 

 

0001h

5

 

 

Зарезервировано (нули)

 

 

 

 

 

 

 

 

 

0006h

1

 

 

Атрибуты файла

 

 

 

 

 

 

 

 

 

0007h

1

 

 

Буква привода

 

 

 

 

 

 

 

 

 

0008h

8

 

 

Имя файла с пробелами

 

 

 

 

 

 

 

 

 

0010h

3

 

 

Расширение файла с пробелами

 

 

 

 

 

 

 

 

 

0013h

2

 

 

Номер текущего блока

 

 

 

 

 

 

 

 

 

0015h

2

 

 

Логический размер записи

 

 

 

 

 

 

 

 

 

0017h

4

 

 

Размер файла

 

 

 

 

 

 

 

 

 

001Bh

2

 

 

Дата создания/обновления файла

 

 

 

 

 

 

 

 

 

001Dh

2

 

 

Время создания/обновления файла

 

 

 

 

 

 

 

 

 

001Fh

8

 

 

Зарезервировано

 

 

 

 

 

 

 

 

 

0027h

1

 

 

Номер текущей записи

 

 

 

 

 

 

 

 

 

0028h

2

 

 

Номер относительно записи

 

 

 

 

 

 

 

 

 

 

 

 

 

Таблица 2.5. Структура DTA

 

 

 

 

 

 

 

Относительный

Размер

Описание поля DTA

 

 

адрес

поля (в

 

 

 

 

 

 

 

байтах)

 

 

 

 

 

 

 

 

 

 

 

0000h

1

биты 0-6: ASCII-код буквы привода

 

 

 

 

бит 7: диск сетевой

 

 

 

 

 

 

 

0001h

11

Шаблон (маска) поиска (без пути)

 

 

 

 

 

 

 

000Ch

1

Атрибуты для поиска

 

 

 

 

 

 

 

000Dh

2

Порядковый номер файла в директории

 

 

 

 

 

 

 

000Fh

2

Номер кластера начала внешней директории

 

 

 

 

 

 

 

0011h

4

Зарезервировано

 

 

 

 

 

 

 

 

 

 

http://www.sklyaroff.ru

 

47

 

 

 

Таблица 2.5. (окончание)

 

 

 

 

 

0015h

1

Атрибут найденного файла

 

 

 

 

 

0016h

2

Время создания файла в формате DOS:

 

 

 

биты 15-11: час (0-23)

 

 

 

биты 10-5: минута

 

 

 

биты 4-0: номер секунды, деленный на 2 (0-30)

 

 

 

 

 

0018h

2

Дата создания файла в формате DOS:

 

 

 

биты 15-9: год, начиная с 1980

 

 

 

биты 8-5: месяц

 

 

 

биты 4-0: день

 

 

 

 

 

001Ah

4

Размер файла

 

 

 

 

 

001Eh

13

ASCIIZ-имя найденного файла с расширением

 

 

 

 

 

2.9. Знакомство с отладчиком

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

Существует большое количество отладчиков под MS-DOS, наиболее известными из них являются: Turbo Debugger от фирмы Borland, CodeView от Microsoft, AFDPRO.

Существует даже стандартный консольный отладчик, встроенный во всех версиях DOS/Windows, который вызывается командой debug.exe, но он очень убогий.

Чтобы вам нигде не искать и не скачивать отладчик, мы будем использовать только отладчик CodeView, т. к. он стандартно входит в пакет MASM и обычно расположен в поддиректории \BINR (файл cv.exe). У большинства отладчиков пользовательский интерфейс подобен CodeView, поэтому если вы научитесь пользоваться CodeView, то без проблем при желании сможете воспользоваться любым другим отладчиком.

Замечу, что отладчики под DOS не подходят для отладки Windows-приложений. Под Windows можно посоветовать такие популярные отладчики как SoftIce и OllyDbg.

В качестве примера загрузим файл hello1.com (листинг 2.1) в отладчик CodeView. Для этого скопируйте файл в каталог отладчика (\BINR) и запустите из командной строки следующим образом:

cv hello1.com

Отладчик CodeView у вас должен выглядеть примерно так, как на рис. 2.3.

Сразу хочу предупредить, что пока загружен DOS-отладчик Windows будет скорее всего заметно подтормаживать, увы, с этим нельзя ничего поделать.

http://www.sklyaroff.ru

48

Рис. 2.3. Программа, запущенная в отладчике CodeView

Как видно экран отладчика состоит из нескольких окон. У каждого окна в левом верхнем углу стоит свой уникальный номер. Обычно по умолчанию открыты следующие окна:

Окно 3 — дизассемблированный код.

Окно 5 — содержимое памяти (в шестнадцатеричных кодах и в соответствующих им ASCII-символах).

Окно 7 — регистры процессора.

Окно 9 — командная строка.

Спомощью меню отладчика "Windows" (меню расположено в самом верху отладчика) можно открыть другие окна отладчика, просто выбирая пункты меню с соответствующими названиями. Пункты меню можно выбирать мышью или нажатием клавиши <Alt> и выделяя стрелками нужный пункт с последующим нажатием <Enter> для выбора.

Закрыть любое окно можно, щелкнув мышью в его левом верхнем углу.

Посмотрим содержимое окна регистров (окно 7). Как видите сразу после загрузки регистр IP=100h, а сегментные регистры CS, DS, ES, SS имею одно и то же значение равное адресу PSP (см. табл. 2.1). В нижней части окна регистров показаны значения флагов процессора. Отладчик CodeView использует особые условные обозначения, показывающие состояния флагов (табл. 4.1).

Обычно по умолчанию в окне регистров показываются только 16-битные регистры

(AX, BX, CX, ...), но вы можете включить в меню "Options" пункт "32-bit registers"

для отображения 32-битных регистров (EAX, EBX, ECX, ...).

Таблица 4.1. Перечень и значения флагов, выводимых в отладчике CodeView

Название флага

Выводимые значения CodeView

 

 

Флаг установлен

Флаг не установлен

 

 

 

 

Левый столбец

 

 

Флаг переполнения OF

OV

NV

Флаг прерывания IF

EI

DI

Флаг нуля ZF

ZR

NZ

Флаг паритета PF

PE

PO

Правый столбец

DN

UP

Флаг направления DF

NG

PL

Флаг знака SF

 

 

Флаг вспомогательного

 

 

переноса AF

AC

NA

Флаг переноса CF

CY

NC