Предыдущий раздел ОПЕРАЦИИ С ФАЙЛАМИ Следующая глава

16.5. Пример программы

Следующая программа выполняет копирование файла. Имя копируемого файла и имя файла-копии программа запрашивает у пользователя сама.

 

 ;             Программа копирует файл 

;             ----------------------------------

;       Имя копируемого файла и имя копии вводятся с клавиатуры

;

cr               equ    0dh                               ;  Код ASCII возврата каретки

lf                equ    0ah                               ;  Код ASCII перевода строки

             org    100h

Start:          jmp    Begin                           ; Переход через данные

;        Данные программы

Msg1          db     ‘Введите имя копируемого файла’, cr, lf, ‘$’ 

Msg2          db     ‘Копируемый файл отсутствует’, cr, lf, ‘$’

Msg3          db     ‘Введите имя файла-копии’, cr, lf, ‘$’        

Msg4          db     ‘Ошибка создания файла’, cr, lf, ‘$’

Msg5          db     ‘Ошибка чтения файла’, cr, lf, ‘$’            

Msg6          db     ‘Ошибка записи в файл’, cr, lf, ‘$’            

Msg7          db     ‘Копирование выполнено’, cr, lf, ‘$’            

Lname0      db     81                                  ; Максимальная длина имени файла

Lname        db     0                                   ; Фактическая длина имени файла

Namefile     times  81     db     0                ; Здесь размещается имя файла

Bufer          times  512   db     0                ; Буфер для копирования

Lognum1    dw     0                                  ; Логический номер файла 1         

Lognum2    dw     0                                  ; Логический номер файла 2

;           Команды программы

Begin:

;        Запрос и открытие копируемого файла                  

mov   dx, Msg3                       ;  Вывод сообщения с просьбой

mov   ah, 9                             ;  ввести имя

int     21h                               ; копируемого файла

mov   ah, 0ah                         ; Функция ввода строки

mov   dx, Lname0                   ; DX ß адрес-смещение буфера ввода

int     21h                              ; Ввод строки

xor    bx, bx                           ; BX ß 0

mov   bl, [Lname]                  ; BX ß длина имени файла

mov   [Namefile+bx], byte 0   ; Запись нулевого байта

mov   ah, 3dh                         ; Открытие

mov   dx, Namefile                 ;     копируемого

mov   al, 0                             ;         файла

int     21h                              ;              на чтение

jnc     .M1                             ; Если успешно

mov   dx, Msg2                      ;  Вывод сообщения

mov   ah, 9                            ;     об отсутствии

int     21h                              ;      копируемого файла

jmp    .Exit                            ; На завершение программы

.M1:   

mov   [Lognum1], ax        ; Сохранение логич. номера файла

                                                                    ;Создание и открытие файла-копии

mov   dx, Msg3                 ;  Вывод сообщения с просьбой

mov   ah, 9                       ;      ввести имя

int     21h                         ;           файла-копии

mov   ah, 0ah                   ; Функция ввода строки

mov   dx, Lname0             ; DX ß адрес-смещение буфера ввода

int     21h                         ; Ввод строки

xor    bx, bx                        ; BX ß 0

mov   bl, [Lname]               ; BX ß длина имени файла

mov   [Namefile+bx], byte 0; Запись нулевого байта

mov   ah, 3ch                      ; Создание

mov   dx, Namefile              ;      и

mov   cx, 0                         ;         открытие

int     21h                           ;              файла-копии

jnc     .M2                          ; Если успешно

mov   dx, Msg4                   ; Вывод сообщения

mov   ah, 9                         ;     об ошибке

int     21h                           ;           создания файла

jmp    .Exit                         ; На завершение программы

.M2:

mov   [Lognum2], ax    ; Сохранение логич. номера файла

                                                                ;            Копирование файла

.M3:  

mov   ah, 3fh                 ; Функция чтения из файла

mov   bx, [Lognum1]     ; BX ß логич. номер читаемого файла

mov   cx, 512                ; CX ß число читаемых байтов

mov   dx, Bufer             ;  DX ß адрес-смещение буфера

int     21h                     ; Чтение из файла в буфер

jnc     .M4                    ; Если успешно

mov   dx, Msg5             ;  Вывод сообщения

mov   ah, 9                   ;     об ошибке

int     21h                     ;           чтения файла

jmp    .Exit                   ; На завершение программы

.M4:          

mov   bx, [Lognum2]    ; BX ß логич. номер файла-копии

mov   cx, ax                 ; CX ß число записываемых байтов

mov   ah, 40h               ; Функция записи в файл

mov   dx, Bufer             ;  DX ß адрес-смещение буфера

int     21h                     ; Запись из буфера в файл

jnc     .M5                    ; Если успешно

mov   dx, Msg6             ;  Вывод сообщения

mov   ah, 9                   ;     об ошибке

int     21h                     ;           записи в файл

jmp    .Exit                   ; На завершение программы

.M5:         

cmp   ax, 512                          ; Конец файла?

jz       .M3                               ; Если нет

;        Завершение программы

mov   dx, Msg7                        ;  Вывод сообщения

mov   ah, 9                              ;     о  завершении

int     21h                                ;         копирования

.Exit:                    mov   ax, 4c00h                       ;  Возврат в DOS с

int     21h                               ;    кодом завершения 0

 

Данная программа сначала запрашивает у пользователя имя копируемого файла, используя для ввода символьной строки с клавиатуры системный вызов DOS – “int 21h” (функция 0Ah) – ввод с клавиатуры символьной строки. При этом в качестве последнего символа строки вводится символ 0Dh (возврат каретки). Этот символ помещается во вводимую строку драйвером клавиатуры при нажатии клавиши <Enter>.

Перед применением вызова программа помещает в регистры DS и DX соответственно адрес-сегмент и адрес-смещение для младшего байта буфера, в который должна быть введена строка. Данный буфер имеет три поля:

1) младший байт содержит максимальное число вводимых символов. Запись этого числа выполняет сама программа перед применением данного вызова;

2) второй байт содержит число фактически введенных символов. Запись в этот байт выполняет DOS;

3) остальные байты буфера содержат введенную строку, заканчивающуюся кодом 0Dh.

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

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

Обратим внимание, что программа не выполняет закрытие файлов. Это объясняется, во-первых, небольшим количеством файлов, открываемых в программе. Во-вторых, вскоре после последней операции записи в файл программа завершается.

Заслуживает внимания оператор:

mov   [Namefile+bx], byte 0 

Данный оператор выполняет загрузку числа 0, заданного в качестве второго операнда, в ячейку ОП, являющейся первым операндом. Адрес-смещение этой ячейки задан выражением в квадратных скобках и представляет собой сумму адреса-смещения байта, имеющего имя Namefile и содержимого регистра BX. Если бы квадратных скобок не было, то транслятор интерпретировал бы первый операнд не как содержимое ячейки ОП, а как ее адрес.

Для уточнения второго операнда в записанном операторе используется вспомогательный псевдооператор byte (байт). При отсутствии такого вспомогательного оператора транслятор не знает, какова длина пересылаемого данного – байт, слово или двойное слово. Оператор byte или word (слово), или dword (двойное слово) будет лишним, если хотя бы один из операндов есть регистр, так как длина регистра всегда известна транслятору.  

Рассмотренная программа пригодна для копирования любых обычных (не каталогов) файлов. Например, она может копировать себя. Допустим, что мы поместили загрузочный модуль программы в файл copir.com, тогда выполнив копирование этого файла в файл с именем, например, copir1.com, получим программу, которая также может выполнять копирование (проверьте это).

 


Предыдущий раздел В начало Следующая глава