Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Архитектура процессора Intel 8086.



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

 

Архитектура процессора Intel 8086.

Цель. Изучение структуры процессора Intel 8086, и основ его программирования.

Задание. Используя представленный теоретический материал, имеющуюся литературу и предоставленное преподавателем обучающее программное обеспечение студент должен изучить структуру микропроцессора Inlet 8086. В результате выполнения практической работы студент должен знать:

- структуру микропроцессора Intel 8086;

- назначение входящих в него блоков и устройств;

- регистры микропроцессора и их основное назначение;

- структуру и назначение регистра флагов;

- структуру памяти и особенности принципа сегментации;

- принцип прерываний;

- режимы адресации;

- последовательность написания программ на языке Ассемблера;

- назначение программ, входящих в пакет Turbo Assembler.

Структура EXE- и COM- программы. Вывод на экран

Цель. Изучение структуры EXE- и COM-программы. Получение навыков вывода данных на экран монитора.

Задание. Разработать EXE-программу вывода символа на экран, и COM- программу вывода на экран строки.

Теоретические сведения

Структура программы

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

Команда на языке ассемблера состоит не более чем из четырех полей. Ниже приведен формат и пример команды с указанием названия его полей:

Метка Код операции Операнды; Комментарий

MET: MOVE AX, BX; Пересылка

 

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

Оператор директивы состоит из символического имени, кода псевдооперации, поля операндов и комментария. Структура директивы аналогична структуре команды. Второе поле – код псевдооперации определяет смысловое содержание директивы. Как и команды, у директивы есть операнды, причем их может быть один или несколько и они отделяются друг от друга запятыми. Допустимое число операндов в директиве определяется кодом псевдооперации. Например:

DB 0, 0, 0, 0, 0

END START

 

Директива может быть помечена символическим именем и содержать поле комментария. Символическое имя, стоящее в начале директивы распределения памяти, называется переменной. В отличие от метки команды после символического имени директивы двоеточие не ставиться.

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

Каждый модуль разбивается на отдельные части директивами сегментации, определяющими начало и конец сегмента. Любой сегмент начинается директивой начала сегмента – SEGMENT и заканчивается директивой конца сегмента – ENDS. В начале директив сегментации ставится имя сегмента.

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

Программный сегмент может разбиваться на части директивами определения процедур – некоторых выделенных блоков программы. Как и для определения сегмента, имеются две такие директивы – директива начала PROC и директива конца ENDP. Процедура имеет имя, которое должно включаться в обе директивы, процедуры в сегменте могут располагаться последовательно одна за другой, могут быть также вложенными одна в другую.

Принципиальной особенностью COM-программы является то, что в отличие от EXE-программы, которая содержит отдельные сегменты данных, стека и кода, COM-программ, в большинстве случаев, может содержать лишь один основной сегмент (сегмент кода), в котором размещаются и код, и данные, и стек. Кроме того, EXE-программа, в отличие от COM-программы, содержит так называемый EXE-заголовок (256 байт), при помощи которого загрузчик выполняет настройку ссылок на сегменты в загруженном модуле, а так как и COM- и EXE- программа должна загружаться с адреса PSP: 0100h (100h=256), COM-программа должна содержать в начале сегмента кода директиву, позволяющую осуществить такую загрузку (ORG 100H).

Ниже приведены примеры, иллюстрирующие основные особенности структуры EXE- и COM-программ, написанных на языке ассемблера:

Пример. Структура EXE-программы:

; Определение сегмента стека

STAK SEGMENT STACK

DB 256 DUP (? )

STAK ENDS

; Определение сегмента данных

DATA SEGMENT

SYMB DB '#'; Описание переменной с именем SYMB

; типа Byte и со значением «#»

...; Определение других переменных

DATA ENDS

; Определение сегмента кода

CODE SEGMENT

ASSUME CS: CODE, DS: DATA, SS: STAK

; Определение подпрограммы

PROC1 PROC

...; Текст подпрограммы

PROC1 ENDP

START:

XOR AX, AX; Точка входа в программу START

MOV BX, data; и обязательная инициализация

MOV DS, BX; регистра DS в начале программы

CALL PROC1; Пример вызова подпрограммы

...; Текст программы

MOV AH, 4CH; Операторы завершения программы

INT 21H

CODE ENDS

END START

 

Пример. Структура COM-программы:

; Определение сегмента кода

CODE SEGMENT

ASSUME CS: CODE, DS: CODE, SS: CODE

ORG 100H; Начало необходимое для COM-программы

START:

...; Текст программы

MOV AH, 4CH

INT 21H; Операторы завершения программы

; ===== Data =====

BUF DB 6; Определение переменной типа Byte

...; Определение других переменных

CODE ENDS

END START

 

Вывод на экран

Вывод информации в ассемблерных программах осуществляется обычно при помощи сервисных функций DOS (прерывание 21h) или BIOS (прерывание 10h). Процесс вывода состоит в следующем:

- определенные регистры микропроцессора загружаются выводимой информацией или адресом буфера, содержащего выводимую информацию;

- в регистр AH заносится номер используемой для операции вывода функции;

- инициируется прерывание.

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

Прерывание 21h.

Функция 02h

Вывод на дисплей.

Вход. AH=02h

DL=выводимый символ

Выход. Нет

 

Описание. Посылает символ из DL на стандартный вывод. Обрабатывает символ Backspace (ASCII 8), перемещая курсор влево на одну позицию и оставляя его в новой позиции.

Функция 05h

Вывод на принтер.

Вход. AH=05h

DL= символ, записываемый на стандартный принтер

Выход. Нет

 

Описание. Посылает символ в DL на стандартное устройство принтера, обычно LPT1. Команда DOS MODE может перенаправить этот вывод в последовательный порт.

 

Функция 09h

Выдать строку.

Вход. AH=09h

DS: DX=адрес строки, заканчивающейся символом '$'.

Выход. Нет

 

Описание. Строка, исключая завершающий ее символ '$', посылается на стандартный вывод. Символы Backspace обрабатываются как в функции 02h. Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 13H и ASCII 0aH). Строки, содержащие '$', можно выдать через 40h (BX=0), которая посылает символ в DL на стандартное устройство принтера, обычно LPT1.

 

Прерывание 10h.

Функция 02h

Вход. AH=02h

BH = видео страница

DH, DL = строка, колонка (считая от 0)

Выход. Нет

 

Описание. Устанавливает курсор в позицию DH, DL. Установка курсора на строку 25 делает курсор невидимым.

Функция 09h

Писать символ/атрибут в текущей позиции курсора.

Вход. AH=09h

BH = номер видео страницы

AL = записываемый символ

CX = счетчик (сколько экземпляров символа записать)

BL = видео атрибут (текст) или цвет (графика)

Выход. Нет

 

Описание. Выводит на экран в текущую позицию курсора символ с заданным атрибутом.

 

Функция 0ah

Писать символ в текущей позиции курсора.

Вход. AH=0ah

BH = номер видео страницы

AL = записываемый символ

CX = счетчик (сколько экземпляров символа записать)

Выход. Нет

 

Описание. Выводит на экран в текущую позицию курсора заданный символ.

 

Функция 13h

Вывод строки.

Вход. AH=13h

ES: BP – выводимая строка

CX = длина строки (подсчитываются только символы)

DH, DL = позиция (строка, колонка) начала вывода

BH = номер страницы

AL = код подфункции:

0=атрибут в BL; курсор без изменения

1=атрибут в BL; курсор – в конец строки

2=формат строки: char, attr,...; курсор без изменения

3=формат строки: char, attr,...; курсор – в конец строки

Выход. Нет

 

Описание. Выдает строку в позиции курсора. Символы 0dH (CarRet), 0aH (LineFeed), 08H (backspace) и 07H (Beep) трактуются как команды управления и не высвечиваются.

 

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

fgB background brt foreground

foreground – цвет переднего плана (от 0 до 0fH);

brt – интенсивность: 1=передний план яркий;

background – фоновый цвет (от 0 до 7);

fgB – мерцание: 1=передний план мерцает;

Видеоадаптер поддерживает следующие цвета:

00H черный 01H синий 02H зеленый 03H голубой 04H красный 05H розовый 06H коричневый 07H серый 08H темно-серый 09H ярко-синий 0aH светло-зеленый 0bH светло-голубой 0cH светло-красный 0dH светло-розовый 0eH желтый 0fH белый

Вычислить значение атрибута можно, используя следующее выражение:

(фон * 16) + передний план + (128 для мерцания)

 

Приведенный ниже фрагмент программы иллюстрирует процесс вывода строки на экран.

MOV AH, 09H; Выбор функции прерывания

MOV DX, OFFSET STR; Занесение в DX адреса выводимой строки

INT 21H

...

STR DB 10, 13, 'Hello$'

; Описание строки

 

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

Циклы. Ввод с клавиатуры

Цель. Получение навыков организации циклических структур в ассемблерных программах. Ввод символов с клавиатуры.

Задание. Разработать программу, ввода строковых данных с клавиатуры. Произвести обработку введенных строк в соответствии с вариантом и вывести результат на экран.

Таблица. Варианты заданий

Вариант Задание
Произвести замену всех латинских символов «а» на символ «А».
Произвести удаление лишних пробелов (лишними считаются двойные, тройные и т.д. пробелы на месте одного).
Произвести замену всех строчных латинских символов прописными латинскими символами.
Произвести замену всех прописных русских символов строчными русскими символами.
Произвести запись строки в обратной последовательности.
Произвести замену всех первых букв в словах строки на соответствующие прописные.
Произвести поиск самого длинного слова в строке.
Произвести сравнение строк введенных с клавиатуры, сравнение выполнить независимо от регистра букв (т.е. прописные и строчные буквы считаются эквивалентными).
Произвести преобразование строки к верхнему регистру (UPCASE).
Произвести анализ введенного в строке имени файла схеме 8.3 (т.е. имя должно содержать не более 8 символов, а расширение не более 3, имя и расширение разделяются точкой).

 

 

Теоретические сведения

Ввод с клавиатуры

Процесс ввода информации в ассемблерных программах осуществляется аналогично выводу:

- в регистр AH заносится номер функции ввода;

- инициируется прерывание, после выполнения которого определенные регистры процессора содержат либо введенную информацию, либо адрес буфера с введенной информацией.

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

Функция 01h

Ввод с клавиатуры.

Вход. AH=02h

Выход. AL= символ, полученный с клавиатуры

 

Описание. Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и т.п.) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.

 

Функция 07h

Нефильтруемый консольный ввод без эха.

Вход. AH=07h

Выход. AL= символ, полученный с клавиатуры

 

Описание. Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не фильтрует. Не проверяет на Ctrl-Break, backspace и т.п. Необходимо вызывать дважды для ввода расширенного символа ASCII.

 

Функция 08h

Консольный ввод без эха.

Вход. AH=08h

Выход. AL= символ, полученный с клавиатуры

 

Описание. Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23H. Необходимо вызывать дважды для ввода расширенного символа ASCII.

 

Функция 0ah

Буферизированный ввод строки.

Вход. AH=0ah

DS: DX=адрес входного буфера (смотри ниже)

Выход. Буфер содержит ввод, заканчивающийся символом CR

(ASCII 0dH)

 

Описание. При входе буфер по адресу DS: DX должен быть оформлен следующим образом:

max ? ? ? ? ? ?

MAX - максимально допустимая длина ввода (от 1 до 254) При выходе буфер заполнен данными следующим образом:

max len T E X T 0dh

LEN - действительная длина данных без завершающего CR (здесь – 0dH).

Символы считываются со стандартного ввода вплоть до CR (ASCII 0dH) или до достижения длины MAX-1. Если достигнут MAX-1, включается консольный звонок для каждого очередного символа, пока не будет введен возврат каретки CR (нажатие Enter). Второй байт буфера заполняется действительной длиной введенной строки, не считая завершающего CR. Последний символ в буфере – всегда CR (который не засчитан в байте длины). Символы в буфере (включая LEN) в момент вызова используются как «шаблон». В процессе ввода действительны обычные клавиши редактирования: Esc выдает " \" и начинает с начала, F3 выдает буфер до конца шаблона, F5 выдает " @" и сохраняет текущую строку как шаблон, и так далее. Большинство расширенных кодов ASCII игнорируются. При распознавании Ctrl-Break выполняется прерывание INT 23H (буфер остается неизменным).

 

Функция 0ch

Ввод с очисткой

Вход. AH=0ch

AL= номер функции ввода (01H, 06H, 07H, 08H или 0aH)

Выход. Нет

 

Описание. Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа. Следующие значения допустимы в AL: 01H – ввод с клавиатуры; 06H – ввод с консоли; 07H – нефильтрующий без эха; 08H – ввод без эха; 0aH – буферизованный ввод.

 

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

MOV AH, 0AH; занесение в AH номера функции

LEA DX, BUF; загрузка DX адресом буфера BUF

INT 21H

...

BUF DB 30, 00, 30 DUP ('$'), ’$’

 

При организации буфера BUF (размер буфера 30 байт), он весь заполняется символами «$», что удобно, если введенную строку в дальнейшем необходимо выводить на экран или в файл (при условии, конечно, что для ввода буфер будет использоваться лишь однократно).

Теоретические сведения

Ввод числовой информации

Ввод числовой информации в ассемблерную программу обычно осуществляется в два этапа:

- ввод строки содержащей число;

- перевод строки в число.

Ввод строк рассматривался в предыдущих практических работах.

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

2398=2*1000+3*100+9*10+8=2*103+3*102+9*101+8*100

 

Таким образом, для перевода строки в число из введенной строки «2398» необходимо последовательно выделять цифры и производить суммирование произведений этих цифр и множителей соответствующих позиции цифры в числе. Если буфер для ввода строки был организован, например, следующим образом:

BUF 05, 00, 05 DUP (? )

 

то после ввода строки «2398» он будет выглядеть (в шестнадцатеричной системе счисления) так:

05, 04, 32, 33, 39, 38, 0d

 

где первый байт – размер буфера, второй – количество введенных символов (без завершающего символа CR), третий, четвертый, пятый, шестой и седьмой – коды символов «2», «3», «9», «8» и «CR» соответственно. Легко заметить, что для того, чтобы из кода цифры получить саму цифру необходимо из соответствующего кода вычесть 30h (шестнадцатеричный код нуля). Затем, последовательно в цикле (второй байт – количество введенных символов) выбирая цифры, формировать соответствующий множитель, вычислять произведение и производить суммирование. Нижеследующий фрагмент программы иллюстрирует описанный алгоритм (символы рассматриваются справа налево).

; Ввод числа в виде строки

MOV AH, 0AH; в AH номер функции

LEA DX, BUF; DS: DX адрес буфера для ввода

INT 21H

; Перевод строки в число, результат в DI

MOV DI, 0

LEA BX, BUF+1; в BX адрес второго элемента буфера

MOV CX, [BX]; в CX количество введенных символов

XOR CH, CH

MOV SI, 1; в SI множитель

MET: PUSH SI; сохраняем SI (множитель) в стеке

MOV SI, CX; в SI помещаем номер текущего символа

MOV AX, [BX+SI]; в AX помещаем текущий символ

XOR AH, AH

POP SI; извлекаем множитель (SI)из стека

SUB AX, 30H; получаем из символа (AX) цифру

MUL SI; умножаем цифру (AX)на множитель (SI)

ADD DI, AX; складываем с результирующим числом

MOV AX, SI; помещаем множитель (SI) в AX

MOV DX, 10

MUL DX; увеличиваем множитель (AX) в 10 раз

MOV SI, AX; перемещаем множитель (AX) назад в SI

LOOP MET; переходим к предыдущему символу

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

Теоретические сведения

Подпрограммы

Как уже было сказано выше, программный сегмент может разбиваться на части директивами определения подпрограмм (процедур). Для определения процедур используются две директивы – директива начала PROC и директива конца ENDP. Процедура должна иметь имя, которое включается в обе директивы. В сегменте кода процедуры могут располагаться последовательно, а могут быть вложенными одна в другую. Определение подпрограмм имеет следующий синтаксис:

имя_процедуры PROC параметр

тело_процедуры

имя_процедуры ENDP

 

Передавать фактические параметры процедуре можно несколькими способами. Простейший способ – передача параметров через регистры: основная программа записывает параметры в какие-либо регистры, а процедура по мере необходимости извлекает их из этих регистров и использует в своей работе. Такой способ имеет один основной недостаток: передавать параметры через регистры можно если их немного (если много, то просто не хватит регистров). Решить это проблему можно, передавая параметры через стек. В этом случае основная программа записывает параметры в стек и вызывает подпрограмму, подпрограмма работает с параметрами и, возвращая управление, очищает стек.

Существует несколько разновидностей команды вызова процедуры CALL. Все команды вызова безусловны и используются для передачи управления процедуре. Внутрисегментный вызов NEAR CALL используется для передачи управления процедуре, находящейся в том же сегменте. Межсегментный вызов FAR CALL используется для передачи управления процедуре, находящейся в другом сегменте или даже программном модуле.

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

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

CODE SEGMENT

...

PROC1 PROC

MOV BP, SP; загрузка в BP текущего адреса стека

MOV BX, [BP+4]; выборка из стека 1 параметра (ca)

...

MOV BX, [BP+2]; выборка из стека 2 параметра (ll)

...

RET 4; Возврат с удалением 4 слов из стека

PROC1 ENDP

START:

...

MOV AX, ’ca’; Загрузка в AX символов

MOV CX, ’ll’; Загрузка в CX символов

PUSH AX; Сохранение AX в стек

PUSH CX; Сохранение CX в стек

CALL PROC1

...

CODE ENDS

 

Работа с файлами

Используется два метода доступа к файлам: метод управляющего блока файла (FCB) и метод дескриптора файла. С помощью метода FCB можно получить доступ только к файлам, находящимся в текущем каталоге. Метод дескриптора файла позволяет получить доступ к любому файлу, независимо от того, какой каталог является текущим.

Начиная с DOS версии 2.0, в набор функций прерывания 21h включены UNIX-подобные файловые функции. Идея их состоит в том, что, когда программа открывает файл, DOS возвращает 16-битовое значение «описателя файла» (дескриптора файла) (handle). После этого, когда программа читает, позиционирует, пишет или закрывает файл, она ссылаетесь на него через описатель. Одно из самых больших удобств – то, что можно обращаться к некоторым устройствам так, как будто это дисковые файлы, через зарезервированные описатели DOS:

Таблица.Предопределенные описатели DOS

Handle Наименование и описание
Стандартное устройство ввода (обычно клавиатура)
Стандартное устройство вывода (обычно экран)
Стандартное устройство ошибок (всегда CON - экран. Для сообщений)
Стандартное устройство AUX (асинхронный адаптер; 1-й послед. порт - COM1)
Стандартный принтер (1-й параллельный порт принтера- LPT1)

Ниже приведен перечень наиболее часто используемых функций прерывания 21h для работы с файлами через описатели.

Функция 3cH

Создать файл.

Вход. AH=3ch

DS: DX=адрес строки ASCIIZ с именем файла

CX=атрибут файла

Выход. AX=код ошибки, если CF установлен и описатель файла,

если ошибки нет.

 

Описание. Файл создается в указанном (или умалчиваемом) оглавлении и открывается в режиме доступа «чтение/запись». Если файл уже существует, то при открытии файл усекается до нулевой длины. Если атрибут файла – «только чтение», открытие отвергается (атрибут можно изменить функцией 43H).

 

Функция 5bH

Создать новый файл (не должен существовать).

Вход. AH=5bh

DS: DX=адрес строки ASCIIZ с именем файла

CX=атрибут файла

Выход. AX=код ошибки, если CF установлен и описатель файла,

если ошибки нет

 

Описание. Этот вызов идентичен функции 3ch, с тем исключением, что он вернет ошибку, если файл с заданным именем уже существует.

 

Функция 5aH

Создать уникальный файл.

Вход. AH=5ah

DS: DX=адрес строки ASCIIZ с путем (заканчивается \)

CX=атрибут файла

Выход. AX=код ошибки, если CF установлен и описатель файла,

если ошибки нет

DS: DX (не изменяется) становится полным

ASCIIZ-именем нового файла.

 

Описание. Открывает (создает) файл с уникальным именем в оглавлении, указанном строкой ASCIIZ, на которую указывает DS: DX. Описание пути должно быть готово к присоединению в его конец имени файла. Необходимо обеспечить минимум 12 байт в конце строки. После возврата строка DS: DX будет дополнена именем файла. DOS создает имя файла из шестнадцатеричных цифр, получаемых из текущих даты и времени. Если имя файла уже существует, DOS продолжает создавать новые имена, пока не получит уникальное имя.

 

Функция 3dH

Открыть файл.

Вход. AH=3dh

DS: DX=адрес строки ASCIIZ с именем файла

AL=режим открытия

Выход. AX=код ошибки, если CF установлен и описатель файла,

если ошибки нет

 

Описание. В момент открытия файл должен существовать. Файл открывается в выбранном режиме доступа (AL = 0 – для чтения; AL = 1 – для записи; AL = 2 – для чтения и записи) и указатель «чтения/записи» устанавливается в 0.

 

Функция 3eH

Закрыть файл.

Вход. AH=3eh

BX=описатель файла

Выход. AX= код ошибки, если CF установлен

 

Описание. BX содержит описатель файла (handle), возвращенный при открытии. Файл, представленный этим описателем, закрывается, его буфер сбрасываются, а оглавление обновляется корректными размером, временем и датой.

 

Функция 41H

Удалить файл.

Вход. AH=41h

DS: DX=адрес строки ASCIIZ с именем файла

Выход. AX=код ошибки, если CF установлен

 

Описание. Имя файла не может содержать обобщенные символы («? » и «*»). Файл удаляется из заданного оглавления заданного диска. Если файл имеет атрибут только чтение, то перед удалением необходимо изменить этот атрибут через функцию 43H.

 

Функция 42H

Установить указатель чтения/записи (можно также узнать размер файла).

Вход. AH=42h

BX=описатель файла

CX: DX=смещение указателя: (CX * 65536) + DX

AL=0 переместить к началу файла + CX: DX

AL=1 переместить к текущей позиции + CX: DX

AL=2 переместить к концу файла - CX: DX

Выход. AX=код ошибки, если CF установлен

DX: AX=новая позиция указателя файла (если нет

ошибки)

 

Описание. Перемещает логический указатель чтения/записи к нужному адресу, с которого начнется очередная операция чтения или записи. Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX: AX. DX здесь старшее значащее слово: действительная длина (DX * 65536) + AX.

 

Функция 3fH

Читать из файла/устройства.

Вход. AH=3fh

BX=описатель файла

DS: DX=адрес буфера для чтения данных

CX=число считываемых байт

Выход. AX=код ошибки, если CF установлен

AX=число действительно прочитанных байт

 

Описание. CX байт данных считываются из файла или устройства с описателем, указанным в BX. Данные читаются с текущей позиции указателя чтения/записи файла и помещаются в буфер вызывающей программы, адресуемый через DS: DX.

Всегда необходимо сравнивать возвращаемое значение AX (число прочитанных байт) с CX (запрошенное число байт):

- если AX=CX, (и CF сброшен) – чтение было корректным без ошибок;

- если AX=0 – достигнут конец файла (EOF);

- если AX< CX (но ненулевой), то возможны два варианта: при чтении с устройства – входная строка имеет длину AX байт; при чтении из файла – в процессе чтения достигнут EOF.

Функция 40H

Писать в файл/устройство.

Вход. AH=40h

BX=описатель файла

DS: DX=адрес буфера, содержащего данные

CX=число записываемых байт

Выход. AX=код ошибки, если CF установлен

AX=число действительно записанных байт

 

Описание. CX байт данных записывается в файл или на устройство с описателем, заданным в BX. Данные берутся из буфера, адресуемого через DS: DX и записываются, начиная с текущей позиции указателя чтения/записи файла. Необходимо всегда сравнивать возвращаемое значение AX (число записанных байт) с CX (запрошенное число байт для записи): если AX = CX, запись была успешной; если AX < CX, встретилась ошибка (скорее всего, переполнение).

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

x x A D V S H R

R- только чтение (нельзя обновлять или удалять);

H- скрытый;

S- системный;

V- метка тома;

D- элемент подоглавления;

A- архивный;

x- не используются.

 

ASCIIZ строка, содержащая имя файла, имеет вид:

«‘d: \путь\имя_файла’, 0»

 

Если диск и/или путь опущены, они принимаются по умолчанию. После вызова функции описатель файла должен быть сохранен для последующих операций. Количество описателей в системе регламентируется файлом CONFIG.SYS.

Приведенный ниже пример иллюстрирует процесс работы с файлом через описатели в ассемблерной программе.

; Создание файла

MOV AH, 3CH

MOV CX, 0

LEA DX, BUF; DS: DX – адрес ASCIIZ строки с именем

INT 21H

JC NO_CREATE; Проверка флага переноса

...; Работа с файлом

NO_CREATE:

...

BUF DB ‘d: \Users\1.txt’, 0

 

Теоретические сведения

Структура DTA

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

Буфер, используемый методом FCB доступа к файлам, называется областью обмена с диском или DTA. На этот буфер указывает условный указатель, который хранится операционной системой и который может быть изменен программой. В документации этот указатель на DTA часто сам называют DTA. Указатель на DTA устанавливается специальной функцией DOS и после того как он установлен все функции чтения/записи автоматически обращаются к нему. Это означает, что сами функции не должны содержать адрес временного буфера.

Для установки указателя на DTA используется функцию 1AH прерывания 21H (DS: DX должны указывать на первый байт DTA). Функция 2FH прерывания 21H сообщает текущую установку указателя DTA (при возврате ES: BX содержат сегмент и смещение DTA).

Префикс программного сегмента PSP обеспечивает каждую программу 128-байтным встроенным DTA, начиная со смещения 80H и до 9FH. Программа может использовать его при нехватке памяти. Первоначально указатель на DTA указывает именно на этот буфер, поэтому если программа будет использовать его, то нет нужды устанавливать указатель. Этот буфер по умолчанию особенно удобно использовать с COM файлами, где DS указывает на начало префикса программного сегмента. Для файлов EXE может потребоваться небольшой добавочный код, чтобы использовать DTA по умолчанию.

 

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

Смещение Длинна Содержимое в DTA
+00h 15h резервируется (используется в последующих вызовах 4fH Find Next)
+15h 01h атрибут файла для найденного файла (см.часть 1 данной лабораторной работы)
+16h 02h время создания/модификации в формате filetime
+18h 02h дата создания/модификации в формате filetime
+1ah 04h размер файла в байтах в формате DWORD
+1eh 0dh 13-байтовое ASCIIZ имя: " filename.ext", 0
+2ch   требуемый размер буфера

 

Формат FileTime:

часы (0-23) минуты (0-60) 2-секундные единицы (0-30)  
                                     

 

год (1-119) месяц (1-12) день (1-31)

Примечание: после извлечения года к нему необходимо прибавить 1980.

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

Функция 1ah

Установить адрес DTA.

Вход. AH=1aH

DS: DX=адрес для DTA

Выход. Нет

 

Описание. Устанавливает адрес DTA.

 

Функция 2fh

Дать текущий DTA.

Вход. AH=2fH

Выход. ES: BX=адрес для DTA

 

Описание. Возвращает адрес начала области ввода-вывода (DTA). Поскольку DTA глобальна для всех процессов, в рекурсивной процедуре (например, при проходе по дереву оглавления) может потребоваться сохранить адрес DTA, а впоследствии восстановить его посредством функции 1aH.

 

Функция 4eh

Найти 1-й совпадающий файл.

Вход. AH=4eH

DS: DX=адрес строки ASCIIZ с именем файла

CX=атрибут файла для сравнения

Выход. AX=код ошибки, если CF установлен

DTA=заполнена данными (если не было ошибки)

 

Описание. DS: DX указывает на строку ASCIIZ в форме: " d: \путь\имяфайла", 0. Если диск и/или путь опущены, они подразумеваются по умолчанию. Обобщенные символы * и? допускаются в имени файла и расширении. DOS находит имя первого файла в оглавлении, которое совпадает с заданным именем и атрибутом, и помещает найденное имя и другую информацию в DTA.

 

Функция 4fh

Найти следующий совпадающий файл.

Вход. AH=4fH

DS: DX= адрес данных, возвращенных предыдущей 4eH.

Выход. AX=код ошибки, если CF установлен

DTA=заполнена данными (если не было ошибки)

 

Описание. DS: DX указывает на 2bH-байтовый буфер с информацией, возвращенной функцией 4eH (либо DTA, либо буфер, скопированный из DTA).Необходимо использовать эту функцию после вызова 4eH. Следующее имя файла, совпадающее по обобщенному имени и атрибуту файла, копируется в буфер по адресу DS: DX вместе с другой информацией (см. функцию 4eH о структуре файловой информации в буфере, заполняемом DOS).

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

; Установить адрес DTA

MOV AH, 01AH

LEA DX, FDTA

INT 21H

...

; Наити первый совпадающий файл

MOV AH, 4EH

LEA DX, MASKA

MOV CX, 10H

INT 21H

JC EXIT

NEXT:

...

; Найти следующий совпадающий файл

MOV AH, 4FH

MOV CX, 10H

LEA DX, MASKA

INT 21H

JNC NEXT

EXIT:

...

; ========== DTA =========

FDTA DB 15H DUP (? )

FATTR DB?

FTIME DW?

FDATA DW?

FSIZE DD?

FNAME DB 0DH DUP ('$')

; ========================

MASKA DB '*.*', 0

 

Структура PSP

Префикс программного сегмента PSP (Program Segment Prefics) – специальная область оперативной памяти размером 256 (100h) байт. PSP может использоваться в программе для определения имен файлов и параметров из командной строки, введенной при запуске программы на выполнение, объема доступной памяти, переменных окружения системы и так далее. После загрузки программы в память сегментные регистры DS и ES указывают на начало PSP этой программы.

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


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-08-31; Просмотров: 642; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.241 с.)
Главная | Случайная страница | Обратная связь