Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 16.02.2019

Просмотров: 29214

Скачиваний: 1689

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Глава 8. Учимся работать с файлами 

77 

int 21h 
... 
 
File_name db 'command.com',0 
... 

Обратите  внимание,  что  в  регистр 

ax

  загружаются  сразу  два  числа: 

3Dh

  и 

02h

Такой метод работает быстрее и занимает меньше байтов, чем если бы мы загру-
жали оба числа по отдельности: 

... 
mov ah,3Dh 
mov al,02h 
... 

Строку 

File_name  db  'command.com',0

 можно размещать в любом месте кода, 

но только не смешивая непосредственно с кодом. Например, нельзя вставлять дан-
ные между операторами ассемблера: 

... 
mov ax,3D02h 
mov dx,offset File_name 
File_name db 'command.com',0 
int 21h 
... 

Обратите  внимание,  что  между  командами 

mov  dx,offset  File_name

  и 

File_name db 

'

command.com

' не стоит многоточие. В данном случае, программа сас-

семблируется  без  ошибок,  но  зависнет  при  запуске.  Процессор  распознает 

'command.com'

 как набор инструкций, а не строку символов. Эти инструкции, ско-

рее всего, не имеют никакой логики (рис. 8.1). После команды 

mov  dx,0106h

 (

mov 

dx,offset  File_name

)  мы  видим  шестнадцатеричный  код  строки 

File_name

 —

 

"command.com"

.  Как  только  процессор  загрузит  в 

dx

  адрес  этой  строки,  он  начнет 

выполнять  следующую  за  ней  команду 

aprl

,  затем 

insw

  и  т. д.,  что,  безусловно, 

приведет к "зависанию" компьютера. 

Из этого делаем вывод, что процессор "не отличает" данные от кода. Он просто 

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

Вернемся к функциям работы с файлами. При открытии файла можно указывать 

не только его имя, но и полный путь к нему: 

File_name db 'C:\ASSM\command.com',0 

Если имя диска или путь к нему опущены, то операционная система будет пы-

таться открыть файл на текущем диске в текущем каталоге. Если же указан полный 
путь,  то  файл-система  попытается  открыть  файл  только  по  указанному  пути. 
ПРОПИСНЫЕ и строчные символы значения не имеют. Можно записать и так: 

My_file db 'a:myfile.doc',0 


background image

 

Часть II. Усложняем задачи 

78 

 

Рис. 8.1. Недопустимость перемешивания данных с кодом 

В данном случае ОС попытается открыть файл myfile.doc, который должен быть 

расположен на диске A: в текущем каталоге. 

Теперь о том, что возвращает функция. Вот код: 

... 

mov ax,3D00h 

mov dx,offset Just_file 

int 21h 

... 

Just_file db 'file',0 

... 

Допустим, в текущем каталоге файл с именем file (см. последнюю строку в при-

веденном выше примере) не был найден. Тогда функция 

3Dh

 устанавливает в еди-

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

Для  проверки  состояния  флага  переноса  используются  операторы 

jc

  (от  англ. 

jump if carry — переход, если установлен флаг переноса) и 

jnc

 (от англ. jump if not 

carry — переход, если флаг переноса не установлен): 

... 

    int 21h 

    jc Error 

Ok: 

... 

Error: 

... 


background image

Глава 8. Учимся работать с файлами 

79 

или так: 

... 
    int 21h 
    jnc Ok 
Error: 
... 
Ok: 
... 

Естественно,  вместо  меток 

Ok

  (порядок)  и 

Error

  (ошибка)  можно  задавать  лю-

бые другие имена. По аналогии с 

je

  и 

jne

, можно сделать вывод, что 

jc

 и 

jnc

 — 

команды условного перехода. 

Все  функции  прерывания 

21h

  устанавливают  в  единицу  флаг  переноса,  если 

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

 

файл не найден. Имя файла или путь к нему не найдены; 

 

файл уже открыт какой-то программой. Файл не может быть одновременно от-
крыт двумя и более программами (процессами); 

 

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

FILES=XX

  файла 

config.sys, где 

XX

 — число не более 99. MS-DOS резервирует для каждого файла 

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

 

попытка  открыть  файл  с  атрибутом  "только  чтение"  для  чтения  и/или  записи. 
Прежде  необходимо  снять  этот  атрибут,  а  затем  уже  открывать  файл  для  чте-
ния/записи. 
В  листинге 8.3  приведен  код,  который  открывает  файл  и  выводит  сообщение  

о том, открыт файл или нет. 

Листинг 8.3. Открытие файла 

... 
    mov ax,3D00h 
    mov dx,offset File_name 
    int 21h 
    jc Bad_file 
 
    mov dx,offset Mess1 
Quit_prog: 
    mov ah,9 
    int 21h 
 
    int 20h 
 
Bad_file: 
    mov dx,offset Mess2 


background image

 

Часть II. Усложняем задачи 

80 

    jmp Quit_prog 
... 
 
File_name db 'c:\assm\masm\binr\ml.exe',0 
Mess1 db 'Файл успешно открыт!$' 
Mess2 db 'Не удалось открыть файл!$' 
... 

 

Рис. 8.2. Успешное открытие файла 

При  успешном  открытии  файла  в 

ax

  возвращается  уникальный  идентификаци-

онный номер файла. В дальнейшем, при обращении к данному файлу, будет указы-
ваться не его имя, а этот номер. Флаг переноса сброшен. После вызова функции 

3Dh

 необходимо сохранить номер файла, переданный ею в регистре 

ax

! Состояние 

регистров после открытия файла в отладчике отображено на рис. 8.2. 

После  того как программист закончил работу с файлом (записал или прочитал 

что-нибудь), файл необходимо закрыть функцией 

3Eh

 прерывания 

21h

 (табл. 8.2). 

Таблица 8.2. Функция 

3Eh

 

прерывания 

21h

 

— закрытие файла 

Вход 

Выход 

ah = 3Eh 

bx 

= номер файла 

Ничего 

 
Все  данные,  которые  мы  записывали  в  файл,  на  самом  деле  не  записываются  

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


background image

Глава 8. Учимся работать с файлами 

81 

Не забывайте закрывать файл! В любом случае, при завершении работы про-

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

Handle

... 
mov ah,3Eh 
mov bx,Handle 
int 21h       ;Файл закрыт 
... 

Обратите  внимание  на  запись 

mov  bx,Handle

. Здесь 

Handle

 —  это  переменная,  

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

Handle

. Вот пример: 

Handle dw 0 

Здесь мы резервируем два байта для хранения некоторых данных. В нашем слу-

чае — для хранения номера файла. В листинге 8.4 приведен фрагмент программы, 
который открывает файл для чтения, сохраняет номер файла в переменной, а затем 
закрывает файл. 

Листинг 8.4. Корректное открытие и закрытие файла 

... 
    mov ax,3D00h 
    mov dx,offset File_name 
    int 21h 
    jc Error 
    mov Handle,ax 
;файл открыт успешно... 
 
    mov ah,3Eh 
    mov bx, Handle 
    int 21h 
;файл закрыт 
 
Error: 
    int 20h 
    ... 
    Handle dw 0 
... 

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

3Fh

,  а  для  записи  

в  файл — 

40h

. При этом 

bx

  должен  содержать  тот  самый  номер  файла — 

Handle