Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1328.pdf
Скачиваний:
0
Добавлен:
07.01.2021
Размер:
1.07 Mб
Скачать

3.СДВИГИ И ЦИКЛИЧЕСКИЕ СДВИГИ

3.1.Перечень сдвиговых операций

Впроцессорах 8086 имеется возможность сдвигать биты регистра или переменной в памяти влево или вправо.

Возможны следующие операции:

логический сдвиг влево или вправо;

арифметический сдвиг влево или вправо;

циклический сдвиг влево или вправо;

циклический сдвиг через флаг переноса влево или вправо.

3.2.Логический сдвиг

Инструкция shl (сдвиг влево, синоним sal) перемещает каждый бит операнда-приемника на один разряд влево, по направлению к самому значащему биту. Значение 10010110b (96h или 150 в десятичном представлении без знака), записанное в al, сдвигается влево с помощью инструкции shl al,1. В результате получается значение 00101100b (2Ch), которое записывается обратно в регистр al. Флаг переноса устанавливается в значение 1.

Самый значащий (старший) бит сдвигается из операнда и попадает во флаг переноса, а в наименее значащий бит заносится 0.

Сдвиг влево чаще всего используется для выполнения с помощью операции shl умножения на степень числа 2. Например, с помощью следующих инструкций dx умножается на 8:

shl dx,1 ; dx := dx * 2 shl dx,1 ; dx := dx * 2 shl dx,1 ; dx := dx * 2

Умножение с помощью сдвига выполняется гораздо быстрее, чем с помощью операции mul.

В предыдущем примере в инструкции shl используется второй операнд значение 1 указывает, что содержимое dx нужно сдвинуть на 1 бит. Процессор 8086 не поддерживает использования в качестве константы сдвига других, отличных от единицы, постоянных значений: 2, 3 и т.д. Однако в качестве счетчика сдвигов допускается использование регистра cl.

Например:

 

mov cl,3

 

shl dx,cl

;dx := dx *8

умножают содержимое регистра dxна 8 (как и в предыдущем примере).

21

Инструкция shr (сдвиг вправо) выполняет сдвиг разрядов операнда вправо на 1 или cl битов, затем сдвигает наименее значащий бит во флаг переноса и помещает 0 в самый значащий бит. Инструкция shr дает быстрый способ выполнения беззнакового деления на степень числа 2.

3.3. Арифметический сдвиг

Инструкция sar (арифметический сдвиг вправо) сдвигает наиболее значащий бит операнда вправо в следующий бит, а затем копирует обратно. Значение 10010110b (96h или -106 в десятичном представлении со знаком), записанное в регистре al, сдвигается вправо с помощью инструкции sar al,1. В результате получается значение 11001011b (0cbh или -53 в десятичном представлении со знаком), которое записывается обратно в регистр al.

Флаг переноса устанавливается в значение 0.

Таким образом, при выполнении данной инструкции сохраняется знак операнда, поэтому инструкцию sar полезно использовать для выполнения деления со знаком на степень числа 2. Например, в результате выполнения инструкций:

mov bx,-4 sar bx,1

в регистре bx будет записано значение -2.

3.4. Циклический сдвиг

Инструкция циклического сдвига вправо ror наименее значащий бит сдвигает в наиболее значащий бит, а также во флаг переноса. Значение 10010110b, записанное в регистре al, циклически сдвигается вправо с помощью инструкции ror al,1. В результате получается значение 01001011b, которое записывается обратно в регистр al. Флаг переноса устанавливается в значение 0.

Операция циклического сдвига влево rol сдвигает наиболее значащий бит в наименее значащий.

22

3.5. Циклический сдвиг через флаг переноса

Инструкция циклического сдвига вправо через флаг переноса rcr сдвигает операнд вправо, при этом наиболее значащий бит сдвигается из флага переноса. Значение 10010110b (96h или 159 в десятичном представлении), записанное в регистре al, циклически сдвигается вправо через флаг переноса, начальное значение которого равно 1, с помощью инструкции rcr al,1. В результате получается значение 11001011b, которое записывается обратно в регистр al. Флаг переноса устанавливается в значение 0, т.к. наименее значащий бит равен нулю.

Инструкция циклического сдвига влево через флаг переноса rcl сдвигает операнд влево, при этом наименее значащий бит сдвигается из флага переноса. Инструкции rcr и rcl полезно использовать для сдвига операнда, состоящего из нескольких слов. Например, следующие инструкции выполняют умножение значения в dx:ax, размером в двойное слово, на 4:

shl

ax,1

; бит 15 регистра ax сдвигается во флаг переноса

rcl

dx,1

; флаг переноса сдвигается в бит 0 регистра dx

shl

ax,1

; бит 15 регистра ax сдвигается во флаг переноса

rcl

dx,1

; флаг переноса сдвигается в бит 0 регистра dx

Инструкции циклического сдвига, аналогично инструкциям сдвига, могут сдвигать операнд на 1 бит или на число битов, заданных регистром cl.

Контрольные вопросы

1.Можно ли применять инструкции (команды) сдвига по отношению к регистрам:

al, ah, bl, bh, cl, ch, dl,dh;

ax, bx, cx, dx, si, di, cs, ds, ss, es, sp, bp, ip, flags;

eax, ebx, ecx, edx, esi, edi, esp, ebp, eip, eflags?

2.Можно ли применять инструкции (команды) сдвига по

отношению к ячейкам памяти:

размером один байт (b1, b2, …)

размером одно слово (w1, w2, …)

размером одно двойное слово (d1, d2,…)?

3.Назовите виды сдвигов.

4.Каков результат выполнения программы:

mov ax, 1 shl ax,1 ror ax,1?

5. Перечислите все восемь инструкций сдвигов.

23

6. Каков результат выполнения программы: mov ax, 1

shr ax,1 rol ax,1?

7. Каков результат выполнения программы: mov ax, 32768

shl ax,1 ror ax,1?

8. Каков результат выполнения программы: mov ax, 32768

shr ax,1 rol ax,1?

9. Каков результат выполнения программы: mov ax, 32768

sal ax,1 ror ax,1?

10. Каков результат выполнения программы: mov ax, 32768

sar ax,1 rol ax,1?

11. Каков результат выполнения программы: mov ax, 32768

rcl ax,1 ror ax,1?

12. Каков результат выполнения программы: mov ax, 32768

rcr ax,1 rol ax,1?

13. Каков результат выполнения программы: mov ax, 32768

rcl ax,1 rcr ax,1?

14. Каков результат выполнения программы: mov ax, 32768

rcr ax,1 ror ax,1?

15. Каков результат выполнения программы: mov ax, 32768

mov dx,0 rcl ax,1 rcr dx,1?

24

4. ПРОГРАММИРОВАНИЕ ОБРАБОТКИ ДИСКОВЫХ ФАЙЛОВ

4.1. Общие сведенья о работе с файлами

Обработка дисковых файлов в базовой DOS включает определение блока управления файлом (FCB file control block), который описывает файл и его записи. Передача адреса блока FCB в DOS обязательна для всех дисковых операций ввода-вывода.

Запись файла на диск требует, чтобы прежде он был "создан" и DOS сгенерировала соответствующий элемент в оглавлении. Когда все записи файла будут записаны, программа должна "закрыть" файл, чтобы DOS завершила обработку оглавления. Чтение файла требует, чтобы он был сначала "открыт" для того, чтобы убедиться в его существовании. Так как записи имеют фиксированную длину, обработка записей дискового файла может осуществляться как последовательно, так и произвольно.

Метод доступа к дисковой памяти, поддерживающий использование оглавления, "блокирование" и "разблокирование" записей, обеспечивается прерыванием DOS 21h. Более низкий уровень, обеспечивающий абсолютную адресацию дисковых секторов также через DOS, выполняется посредством прерываний 25h и 26h. Самый низкий уровень обеспечивается прерыванием BIOS 13h, которое позволяет выполнить произвольную адресацию в дисковой памяти по номеру дорожки и сектора. Методами DOS осуществляют некоторую предварительную обработку до передачи управления в BIOS.

Термин “кластер” определяет один или более секторов с данными в зависимости от дискового устройства.

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

4.2. Блок управления файлом (FCB)

Для выполнения ввода-вывода на диск в базовой DOS необходимо определить блок FCB. Блок FCB не поддерживает путь доступа к файлу, поэтому он используется для обработки файлов в текущей директории. Блок FCB содержит (рис. 4.2) описание файла и его

25

записей. Пользователь должен инициализировать байты 0 15 и 32 36, DOS устанавливает байты 16 31.

Создать

файл

Записать в файл

Закрыть

файл

а)

Открыть

файл

Записать в файл

Записать в файл

Записать в файл

Закрыть

файл

г)

Открыть

файл

Записать в файл

Закрыть

файл

б)

Открыть

файл

Чтение из файла

Вычисления

Записать в файл

Закрыть

файл

26д)

Открыть

файл

Чтение из файла

Закрыть

файл

в)

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

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

Чтение из файла 1

Вычисления

Записать в файл 2

Закрыть

файлы

е)

Рис.4.1 Примеры работы с файлами и использования операций создания,

Помните, что открытиячисловые, записизначенияили чтенияв словахи закрытияи двойных словах записываются в обратной последовательности байтов.

 

 

 

 

Таблица 4.2

 

 

 

 

 

 

Байты

 

 

 

Назначение

 

0

Указывает дисковод: 01 для дисковода A, 02 для B и т.д.

 

1-8

Имя файла, выровненное по левой границе с конечными пробелами, если

 

имя меньше 8 байтов. Поле может содержать зарезервированные имена,

 

например LPT1 для принтера

 

 

9-11

Тип файла для дополнительной идентификации, например dat или asm. Если

 

тип файла меньше трех байтов, то он должен быть выровнен по левой

 

границе и дополнен конечными пробелами. DOS хранит имя и тип файла в

 

оглавлении

 

 

 

 

12-13

Номер текущего блока. Блок содержит 128 записей. Для

локализации

 

конкретной записи используются номер текущего блока и номер текущей

 

записи (байт 32). Первый блок файла имеет номер 0, второй 1 и т.д.

 

Операция открытия файла устанавливает в данном поле 0

 

14-15

Логический размер записи. Операция открытия инициализирует размер

 

записи значением 128 (т.е. 80h). После открытия и перед любой операцией

 

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

 

значение длины записи

 

 

 

16-19

Размер файла. При создании файла DOS вычисляет и записывает это

 

значение (произведение числа записей на размер записей) в оглавление.

 

Операция открытия выбирает размер файла из оглавления и заносит его в

 

данное поле. Программа может читать это поле, но не может менять его

20-21

Дата. При создании или последней модификации файла DOS записывает

 

дату в оглавление. Операция открытия выбирает дату из оглавления и

 

заносит в данное поле

 

 

 

22-31

Зарезервировано для DOS

 

 

 

32

Текущий номер записи. Данное поле содержит текущий номер записи (0-

 

127) в текущем блоке (см. байты 12 13). Система использует текущие

 

значения блока и записи для локализации записи в дисковом файле. Обычно

 

номер начальной записи в данном поле 0, но его можно заменить для

 

начала последовательной обработки на любое значение от 0 до 127

33-36

Относительный номер записи. Для произвольного доступа при операциях

 

чтения или записи данное поле должно содержать относительный номер

 

записи. Например, для произвольного чтения записи номер 25 (т.е. 19h),

 

необходимо установить в данном поле 19000000h. Произвольный доступ

 

характеризуется

тем,

что

система автоматически

преобразует

 

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

 

ограничения на максимальный размер файла (1 073 741 824 байта), файл с

 

короткими записями может содержать больше записей и иметь больший

 

относительный номер записи. Если размер записи больше 64, то байт 36

 

всегда содержит 00

 

 

 

 

27

4.3. Использование блока FCB для создания файла на диске

Для ссылки на каждый дисковый файл программа должна содержать правильно составленный блок управления файлом (в той части COM-программы, где описываются данные, или в сегменте данных EXE-программы). Операции ввода-вывода на диск требуют установки адреса блока FCB в регистре dx. Доступ к полям блока FCB осуществляется по этому адресу с помощью регистровой пары ds:dx. Для создания нового файла программа использует функцию 16h в прерывании DOS int 21h следующим образом:

mov ah,16h

; создание

lea dx,FCBname

; дискового файла

int 21h

; вызов DOS

DOS осуществляет поиск имени и типа файла, взятого из соответствующих полей FCB в оглавлении. Если элемент оглавления, содержащий необходимое имя (и тип), будет найден, то DOS очищает найденный элемент для нового использования; если такой элемент не найден, то DOS ищет свободный элемент. Затем операция устанавливает размер файла в 0 и "открывает" файл. На этапе открытия происходит проверка доступного дискового пространства, результат такой проверки устанавливается в регистре al (табл. 4.3).

 

Таблица 4.3

al

Результат проверки

00

На диске есть свободное пространство

FF

На диске нет свободного пространства

При открытии в блок FCB также устанавливаются номер текущего блока 0 и размер записей (по умолчанию) 128 байтов. Прежде чем начать запись файла, можно заменить это значение на требуемый размер записей.

В DTA не требуется устанавливать ограничитель конца записи, т.к. блок FCB содержит размер записей. Для указания на начало выводимой на диск информации необходимо с помощью функции 1ah сообщить DOS адрес DTA, т.е. области передачи данных (DTA disk trausfer area). В любой момент времени может быть активна только одна область DTA. В следующем примере инициализируется адрес DTA:

mov ah,1ah

; установка адреса

lea dx,DTAname

; DTA

int 21h

; вызов DOS

 

28

Если программа обрабатывает только один дисковый файл, то должна быть только одна установка адреса DTA для всего выполнения. При обработке нескольких файлов программа должна устанавливать соответствующий адрес DTA непосредственно перед каждой операцией чтения или записи. Для последовательной записи на диск существует функция 15h:

mov ah,15h

; последовательная

lea dx,FCBname

; запись

int 21h

; вызов DOS

Операция записи использует информацию из блока FCB и адрес текущего буфера DTA. Если длина записи равна размеру сектора, то запись заносится на диск. В противном случае записи заполняют буфер по длине сектора и затем буфер записывается на диск. Например, если длина каждой записи составляет 128 байтов, то буфер заполняется четырьмя записями (4*128=512) и затем буфер записывается в дисковый сектор. После успешного занесения записи на диск DOS увеличивает в блоке FCB размер файла на размер записи и текущий номер записи на 1. Когда номер текущей записи достигает 128, про исходит сброс этого значения в 0 и в FCB увеличивается номер текущего блока на 1. Операция возвращает в регистре al следующие коды:

 

Таблица 4.4

 

 

al

Результат проверки

00

Успешная запись

01

Диск полный

02

В области DTA нет места для одной записи

Когда запись файла завершена, можно, хотя и не всегда обязательно, записать маркер конца файла (1Ah). Для закрытия файла используется функция 10h:

mov ah,10h

; закрыть

lea dx,FCBname

; файл

int 21h

; вызов DOS

Эта операция записывает на диск данные, которые ещё остались в дисковом буфере DOS, и изменяет в соответствующем элементе оглавления дату и размер файла. В регистре al возвращаются следующие значения:

Таблица 4.5

al

Результат проверки

00

Успешная запись

FFОписание файла оказалось в неправильном элементе оглавления (возможно, в результате смены дискеты)

29

4.4.Последовательное чтение дискового файла

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

mov ah,0fh

; открытие

lea dx,FCBname

; файла

int 21h

; вызов DOS

Операция открытия начинается с поиска в оглавлении элемента с именем и типом файла, определенными в FCB. Если такой элемент не будет найден в оглавлении, то в регистре al устанавливается FFh. Если элемент найден, то в регистре al устанавливается 00 и в FCB заносится действительный размер файла, а также устанавливаются номер текущего блока в 0, длина записи в 80h. После открытия можно заменить длину записи на другое значение.

DTA должно содержать определение считываемой записи в соответствии с форматом, который использовался при создании файла. Для установки адреса DTA используется функция 1ah (не путать с маркером конца файла EOF 1ah) аналогично созданию дискового файла:

mov ah,1ah

; установка

lea dx,DTAname

; адреса DTA

int 21h

; вызов DOS

Для последовательного чтения записей с диска используется функция

14h:

mov ah,14h

; последовательное

lea dx,FCBname

; чтение записей

int 21h

; вызов DOS

Чтение записи с диска по адресу DTA осуществляется на основе информации в блоке FCB. Операция чтения устанавливает в регистре al следующие коды возврата:

 

Таблица 4.6

al

Результат проверки

00

Успешное чтение

01

Конец файла, данные не прочитаны

02

В DTA нет места для чтения одной записи

03

Конец файла, прочитана частичная запись, заполненная нулями

Первая операция чтения заносит содержимое всего сектора в буфер DOS. Затем операция определяет из блока FCB размер записи и

30

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

После успешной операции чтения в блоке FCB автоматически увеличивается номер текущей записи на 1. Завершение последовательного чтения определяется программой по маркеру конца файла (EOF), для чего в программе имеется соответствующая проверка. Так как оглавление при чтении файла не изменяется, то обычно нет необходимости закрывать файл после завершения чтения. Исключение составляют программы, которые открывают и читают несколько файлов одновременно. Такие программы должны закрывать файлы, так как DOS ограничивает число одновременно открытых файлов.

4.5. Прямой доступ

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

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

Примечание. Файл создается последовательно, а доступ к записям может быть последовательным или прямым (произвольным). Требования прямой обработки, использующей вызов DOS, заключаются в установке требуемого номера записи в соответствующее поле FCB и выдаче команды прямого чтения или записи.

Произвольный доступ использует относительный номер записи (байты 33 36) в блоке FCB. Поле имеет размер двойного слова и использует обратную последовательность байтов в словах.

Для локализации требуемой записи система автоматически преобразует относительный номер записи в номер текущего блока (байты 12 13) и номер текущей записи (байт 32).

31

4.6. Прямое чтение

Операции открытия и установки DTA одинаковы как для прямой, так и для последовательной обработки. Предположим, что программа должна выполнить прямой доступ к пятой записи файла. Установим значение 05 в поле FCB для относительного номера записи и выполним команды для прямого чтения. В результате успешной операции содержимое пятой записи будет помещено в

DTA.

Для прямого чтения записи необходимо поместить требуемое значение относительного номера записи в FCBи вызвать функцию21h:

mov ah,21h

; запрос на

lea dx,FCBname

; прямое чтение

int 21h

; вызов DOS

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

 

Таблица 4.7

 

 

al

Результат проверки

00

Успешное завершение

01

Данные не доступны

02

Чтение прекращено из-за нехватки места в DTA

03

Прочитана частичная запись, заполненная нулями

Как видно, среди перечисленных кодов возврата отсутствует состояние “конец файла”. При корректном чтении записи предполагается единственный код возврата 00. Остальные коды возврата могут являться результатом установки неправильного относительного номера записи или некорректной установки адреса DTA или FCB. Так как такие ошибки легко допустить, то полезно выполнять проверку регистра al на ненулевое значение.

4.7. Прямая запись

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

mov ah,22h

; запрос на

lea dx,FCBname

; прямую запись

 

32

int 21h

; вызов DOS

Операция устанавливает в регистре al следующие коды возврата:

 

Таблица 4.8

al

Результат проверки

00

Успешная операция

01

На диске нет места

02

Операция прекращена, т.к. недостаточно места в DTA

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

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

4.8. Прямой блочный доступ

Если в программе имеется достаточно места, то одна прямая блочная операция может записать весь файл из DTA на диск, а также прочитать весь файл с диска в DTA. Данная особенность весьма полезна для записи на диск таблиц, которые другие программы могут считывать в память для обработки.

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

Для операции прямой блочной записи необходимо установить в регистре cx требуемое число записей, установить в FCB стартовый относительный номер записи и выдать функцию 28h:

mov

ah,28h

; операция прямой блочной записи

mov

cx,records

; установка числа записей

lea dx,FCBname

 

int 21h

; вызов DOS

Операция преобразует относительный номер записи (байты 33 36) в номер текущего блока (байты 12 13) и текущий номер записи (байт 32). Полученные значения используются для определения

33

начального адреса на диске. В результате операции в регистре al устанавливаются следующие коды возврата:

 

Таблица 4.9

al

Значение кода возврата

00

Успешное завершение для всех записей

01

На диске недостаточно места

Кроме того, операция устанавливает в FCB в поле относительного номера записи и в полях текущих номеров блока и записи значения, соответствующие следующему номеру записи. Например, если были записаны записи с 00 до 24, то следующий номер записи будет 25 (19h).

Для операции прямого блочного чтения необходимо установить в регистре cx требуемое число записей и использовать функцию 27h:

mov

ah,27h

; операция прямого блочного чтения

mov

cx,records

; установка числа записей

lea dx,FCBname

 

int 21h

; вызов DOS

Операция чтения возвращает в регистре al следующие значения:

 

Таблица 4.10

 

 

al

Значение кода возврата

00

Успешное чтение всех записей

01

Прочитана последняя запись файла

02

Прочитано предельное для DTA число записей

03

Прочитана последняя запись файла не полностью

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

Если необходимо загрузить в память весь файл, но число записей неизвестно, то следует после операции открытия разделить размер файла на длину записи. Например, для размера файла 320h (800) и длины записи 20h (32) число записей будет 19h (25).

4.9. Абсолютные операции дискового ввода-вывода

Для непосредственного доступа к диску можно использовать операции абсолютного чтения и абсолютной записи с помощью функций DOS int 25h и 26h. В этом случае не используются

34

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

Абсолютные операции предполагают, что все записи имеют размер сектора, поэтому прямой доступ осуществляется к полному сектору или блоку секторов. Адресация диска выполняется по "логическому номеру записи" (абсолютный сектор). Для определения логического номера записи на двухсторонних дискетах с девятью секторами счет секторов ведется с дорожки 0 сектора 1 следующим образом:

 

 

 

 

 

Таблица 4.11

 

 

 

 

 

 

Дорожка

Сектор

Логический

Дорожка

Сектор

Логический

 

 

номер

 

 

номер

 

 

записи

 

 

записи

0

1

0

1

4

12

0

2

1

1

. . .

 

0

3

2

1

9

17

0

. . .

 

2

1

18

0

9

8

2

2

19

1

1

9

2

. . .

 

1

2

10

2

9

26

1

3

11

 

. . .

 

Фрагмент программы для абсолютных операций ввода-вывода:

mov

al,drive#

; 0 для A, 1 для B и т.д.

mov bx,addr

; адрес области ввода-вывода

mov

cx,sectors

; число секторов

mov dx,record#

; начальный логический номер записи

int 25h или 26h

; абсолютное чтение или запись

Операции абсолютного чтения или запись разрушают содержимое всех регистров, кроме сегментных, и устанавливают флаг cf для индикации успешной (0) или безуспешной (1) операции. В случае безуспешной операции содержимое регистра al описывает характер ошибки:

Таблица 4.12

al

Причина

1000 0000

Устройство не отвечает

0100 0000

Ошибка установки головок

0010 0000

Ошибка контролера

0001 0000

Ошибка дискеты?

0000 1000

Переполнение DMA при чтении

0000 0100

Сектор не найден

0000 0011

Попытка записи на защищенной дискете

 

35

0000 0010 Не найден адресный маркер

Команда int записывает содержимое флагового регистра в стек. После завершения команды int следует восстановить флаги, но проверив перед этим флаг cf.

4.10. Другие операции

Кроме основных дисковых функций DOS имеется несколько дополнительных полезных дисковых операций.

4.11. Сброс диска

Обычно нормальное закрытие файла приводит к занесению всех оставшихся в буфере записей на диск и корректировке оглавления. В особых случаях (например, при аварийном завершении) может потребоваться сброс диска. Функция DOS 0dh освобождает все файловые буферы и не корректирует оглавление диска. Если необходимо, то вначале данная функция закрывает все файлы.

mov ah,0dh

; запрос на сброс диска

int 21h

; вызов DOS

 

4.12. Установка текущего дисковода

Основное назначение функции DOS 0eh установка номера текущего (по умолчанию) дисковода. Номер дисковода помещается в регистр dl, причем 0 соответствует дисководу A, 1 B и т.д.

mov

ah,0eh

; запрос на установку

mov

dl,02

; дисковода C

int 21h

; вызов DOS

Операция возвращает в регистр al число дисководов (независимо от типа). Так как для DOS необходимо, по крайней мере, два логических дисковода (A и B), то DOS возвращает значение 02 и для систем с одним дисководом. Для определения действительного числа дисководов используется команда int 11h.

4.13. Поиск элементов оглавления

Для доступа к имени файла, например при удалении или переименовании, может потребоваться поиск в оглавлении. Для доступа к первому или единственному элементу оглавления

36

необходимо загрузить в регистр dx адрес неоткрытого блока FCB и выполнить функцию 11h. При использовании расширенного блока FCB можно также получить код атрибута:

mov ah,11h

; запрос на первый элемент

lea dx,FCBname

; неоткрытый FCB

int 21h

; вызов DOS

В регистре al операция возвращает следующие значения:

 

Таблица 4.13

al

Значение кода возврата

00

Элемент найден

FF

Элемент не найден

Операция устанавливает в DTA номер дисковода (1=A, 2=B и т.д.), имя файла и тип файла. Если найдено несколько элементов при выборке по шаблону (например, *.asm), то для локализации элементов подмножества директории используется функция 12h:

mov ah,12h

; запрос следующего элемента

lea dx,FCBname

; неоткрытый FCB

int 21h

; вызов DOS

Коды возврата в регистре al аналогичны кодам функции 11h.

4.14. Удаление файла

Для удаления файла в программе используется функция 13h. Операция удаления устанавливает специальный байт в первой позиции имени файла в оглавлении.

mov ah,13h

; запрос на удаление файла

lea dx,FCBname

; неоткрытый FCB

int 21h

; вызов DOS

Если операция находит и удаляет элемент, то в регистре al устанавливается код возврата 00, иначе код равен шестнадцатеричному FF.

4.15. Переименование файла

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

mov ah,17h

; запрос на переименование

lea dx,FCBname

; адрес FCB

int 21h

; вызов DOS

 

37

Символы ? и * в новом имени приводят к сохранению в соответствующих позициях символов из старого имени. Успешная операция устанавливает в регистре al код возврата 00, а безуспешная (файл по старому имени не найден или по новому имени уже существует) код FF.

4.16. Получение текущего номера дисковода

Функция 19h позволяет определить текущий номер дисковода:

mov ah,19h

; получить текущий дисковод

int 21h

; вызов DOS

Операция возвращает шестнадцатеричный номер дисковода в регистре al (0=A, 1=B и т.д.). Полученное значение можно поместить непосредственно в FCB для доступа к файлу с текущего дисковода.

Кроме перечисленных существуют функции для получения информации из таблицы FAT (1B и 10), установки поля прямой записи (24), установки вектора прерываний (25), создания нового программного сегмента (26) и анализа имени файла (29). Эти функции описаны в техническом руководстве по DOS.

Контрольные вопросы

1.Общие сведенья о работе с файлами.

2.Назначение блока управления файлом (FCB).

3.Как осуществляется создание, запись и закрытие файла.

4.Как осуществляется открытие, запись и закрытие файла.

5.Как осуществляется открытие, чтение и закрытие файла.

6.Какие значения принимают по умолчанию номер текущего блока и размер записей при открытии файла?

7.Назначение области DTA? Как инициализируется адрес DTA?

8.Как инициализируется адрес DTA при обработке нескольких файлов (например, чтение из двух файлов, побайтное суммирование и запись полученных сумм в третий файл)?

9.Последовательное чтение дискового файла. Замена длины записи.

10.Прямой доступ к дисковому файлу. Относительный номер

записи.

11.Прямое чтение записей дискового файла. Использование относительного номера записи.

12.Прямая запись в дисковый файл. Использование относительного номера записи.

38

13.Прямой блочный доступ: прямая блочная запись, задание количества записей, стартовый относительный номер записи. Как используются номер текущего блока и текущий номер записи?

14.Прямой блочный доступ: как загрузить в память весь файл, когда число записей неизвестно?

15.Абсолютные операции дискового ввода-вывода. Длина записи при выполнении операций абсолютного чтения и абсолютной записи

спомощью функций DOS.

16.Сброс диска. В каких случаях осуществляется, и что при этом выполняется. Получение текущего номера дисковода.

17.Установка текущего дисковода. Удаление файла.

18.Напишите функции базовой версии DOS для следующих операций:

а) создание файла; б) установка DTA;

в) последовательная запись; г) открытие файла; д) последовательное чтение.

19.Программа использует размер записи, устанавливаемый при открытии файла по умолчанию.

а) сколько записей содержит один сектор?

б) сколько записей содержит дискета с тремя дорожками по девять секторов на каждой?

в) если на дискете (б) находится один файл, то при последовательном чтении сколько произойдет физических обращений к диску?

20.Определите текущий блок и запись для следующих номеров записей при прямом доступе: а) 45, б) 73, в) 150, г) 260.

21.В каком виде номер записи 2652 (десятичное) устанавливается в поле относительной записи блока FCB?

22.Укажите шестнадцатеричные номера функций для следующих операций:

а) прямая запись, б) прямое чтение,

в) прямая блочная запись, г) прямое блочное чтение.

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

Имена полей с размером файла fcbflsz и размером записи fcbfcsz.

39

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

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

40

5. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ НАД ЦЕЛЫМИ ДВОИЧНЫМИ ЧИСЛАМИ СО ЗНАКОМ

5.1. Общие сведения об арифметических операциях над числами со знаком

Рассмотрим особенности каждого из четырех основных арифметических действий (сложение, вычитание, умножение и деление) для двоичных чисел со знаком.

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

5.2. Сложение двоичных чисел со знаком

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

флаг переноса cf, установка которого в 1 говорит о том, что произошел выход за пределы разрядности операндов;

команда adc, которая учитывает возможность такого выхода (перенос из младшего разряда).

Другое средство – это регистрация состояния старшего (знакового) разряда операнда, которое осуществляется с помощью флага переполнения of (бит 11).

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

Пример 1.

30566 = 01110111 01100110

+

41

00687 = 00000010 10101111

=

31253 = 01111010 00010101

Следим за переносами из 14-го и 15-го разрядов и правильностью результата: переносов нет, результат правильный.

Пример 2.

30566 = 01110111 01100110

+

30566 = 01110111 01100110

=

61132 = 11101110 11001100

Произошел перенос из 14-го разряда; из 15-го разряда переноса нет. Результат неправильный, так как имеется переполнение - значение числа получилось больше, чем то, которое может иметь 16битное число со знаком (+32 767).

Пример 3.

-30566 = 10001000 10011010

+

-04875 = 11101100 11110101

=

-35441 = 01110101 10001111

Из 14-го разряда нет переноса, а из 15-го разряда произошел перенос. Результат неправильный, так как вместо отрицательного числа получилось положительное (в старшем бите находится 0).

Пример 4.

-4875 = 11101100 11110101

+

-4875 = 11101100 11110101

=

-9750 = 11011001 11101010

Есть переносы из 14-го и 15-го разрядов. Результат правильный. Таким образом, переполнения не происходит (то есть флагу of присваивается 0), если есть перенос из обоих разрядов или из 14-го и

из 15-го разрядов перенос отсутствует.

И наоборот, переполнение (установка of в 1) происходит при переносе:

из 14-го разряда (для положительных чисел со знаком);

из 15-го разряда (для отрицательных чисел).

Дополнительно к флагу of при переносе из старшего разряда

устанавливается в 1 и флаг переноса cf. Так как процессор не знает о

42

существовании чисел со знаком и без знака, то вся ответственность за правильность действий с получившимися числами ложится на программиста. Проанализировать флаги cf и of можно командами условного перехода jc\jnc и jo\jno соответственно.

Сложение двух операндов, занимающих по 8 битов (т.е.сложение байтов), аналогично, но переполнение возникает при переносе из 6-го разряда для положительных и из 7-го разряда для отрицательных чисел. Для процессора 80386 и выше кроме этих двух случаев возможно сложение двойных слов. Переполнение при таком сложении возникает при переносе из 30-го для положительных и из 31-го – для отрицательных чисел.

Что же касается команд сложения чисел со знаком, то они те же, что и для чисел без знака.

5.3. Вычитание двоичных чисел со знаком

Процессору незачем иметь два устройства - сложения и вычитания. Достаточно наличия только одного - устройства сложения. Но для вычитания способом сложения чисел со знаком необходимо представлять в дополнительном коде оба операнда - и уменьшаемое, и вычитаемое. Результат тоже нужно рассматривать как значение в дополнительном коде. Здесь возникают сложности. Прежде всего, они связаны с тем, что старший бит операнда рассматривается как знаковый. Рассмотрим пример вычитания отрицательного числа из положительного:

45 = 0010 1101

-

-127 = 1000 0001

=

-44 = 1010 1100

Судя по знаковому разряду, результат получился отрицательный, что, в свою очередь, говорит о том, что число нужно рассматривать как дополнение, равное –44. Правильный результат должен быть равен 172. Здесь мы, как и в случае знакового сложения, встретились с переполнением, когда значащий разряд числа изменил знаковый разряд операнда. Отследить такую ситуацию можно по содержимому флага переполнения of. Его установка в 1 говорит о том, что результат вышел за диапазон представления знаковых чисел (то есть изменился старший бит) для операнда данного размера, и

43

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

Пример вычитания положительного числа из отрицательного числа как сложение двух отрицательных чисел: -45 - 45 = -45 + (-45)= -90.

-45 = 1101 0011

+

-45 = 1101 0011

=

-90 = 1010 0110

Здесь все нормально, флаг переполнения of сброшен в 0, а 1 в знаковом разряде говорит о том, что значение результата – число в дополнительном коде.

5.4. Умножение чисел со знаком

5.4.1. Эта команда имеет три формы, различающиеся числом операндов:

imul источник

imul приемник, источник

imul приемник, источник1, источник2

5.4.2. Если используется форма imul источник,

то источник (регистр или переменная) умножается на al или ax (в зависимости от размера операнда) и результат располагается в ax или dx:ax соответственно.

5.4.3. Если используется форма imul приемник, источник,

то источник (число, регистр или переменная) умножается на приемник (регистр) и результат заносится в приемник.

5.4.4. Если используется форма imul приемник, источник1, источник2,

то источник 1 (регистр или переменная) умножается на источник 2 (число) и результат заносится в приемник (регистр).

5.4.5.Во всех трех вариантах считается, что результат может занимать в два раза больше места, чем размер источника. В первом случае приемник автоматически оказывается достаточно большим, но во втором и третьем случаях могут произойти переполнение и потеря старших битов результата.

5.4.6.Флаги of и cf будут равны:

44

единице, если это произошло;

нулю, если результат умножения поместился целиком в приемник (во втором и третьем случаях) или в младшую половину приемника (в первом случае).

Значения флагов sf, zf, af и pf после команды imul не определены.

5.4.7. Эта команда выполняется так же, как и команда mul. Отличительной особенностью команды imul является только формирование знака.

Если результат мал и умещается в одном регистре (то есть если cf = of = 0), то содержимое другого регистра (старшей части) является расширением знака - все его биты равны старшему биту (знаковому разряду) младшей части результата.

Впротивном случае (если cf = of = 1) знаком результата является знаковый бит старшей части результата, а знаковый бит младшей части является значащим битом двоичного кода результата.

5.5.Деление чисел со знаком

Для деления чисел со знаком предназначена команда idiv делитель

Выполняет целочисленное деление со знаком ax или dx:ax (в зависимости от размера источника) на источник (регистр или переменная) и помещает результат в al или ax, а остаток — в ah или dx соответственно. Результат всегда округляется в сторону нуля, знак остатка всегда совпадает со знаком делимого, абсолютное значение остатка всегда меньше абсолютного значения делителя. Значения флагов cf, of, sf, zf, af и pf после этой команды не определены, а переполнение или деление на ноль вызывает исключение #DE (ошибка при делении) в защищенном режиме и прерывание 0 — в реальном.

Для этой команды справедливы все рассмотренные положения, касающиеся команд и чисел со знаком. Отметим лишь особенности возникновения исключения 0, “деление на ноль” в случае чисел со знаком. Оно возникает при выполнении команды idiv по одной из следующих причин:

делитель равен нулю;

частное не входит в отведенную для него разрядную сетку.

45

Последнее, в свою очередь, может произойти:

при делении делимого величиной в слово со знаком на делитель величиной в байт со знаком, причем значение делимого более чем в 128 раз больше значения делителя (т.к. частное не должно находиться вне диапазона от –128 до +127);

при делении делимого величиной в двойное слово со знаком на делитель величиной в слово со знаком, причем значение делимого более чем в 32 768 раз больше значения делителя (т.к. частное не должно находиться вне диапазона от –32 768 до +32 767).

Вспомогательные команды для целочисленных операций – рассматриваются ниже.

Контрольные вопросы

1.Общие сведенья об арифметических операциях над числами со знаком.

2.Сложение двоичных чисел со знаком. В каких случаях происходит переполнение и получается неправильный результат.

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

4.Умножение чисел со знаком.

5.Деление чисел со знаком. Причины возникновения ситуации «деление на ноль».

46

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