Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29213
Скачиваний: 1689
Часть II. Усложняем задачи
82
cx
— количество читаемых или записываемых байтов,
ds:dx
— адрес буфера для
чтения/записи. Пример чтения файла в память с использованием функции
40h
при-
веден в разд. 8.3.
8.3. Программа для практики
Чтобы полностью понять приведенный далее пример, придется рассмотреть
много нового. В данном случае мы поступим так же, как и в главе 1: о некоторых
операторах (командах) скажем позже.
Итак, в листинге 8.5 приведен образец чтения файла (до 65 000 (0FDE8h) байт)
в память, а точнее, в наш сегмент (\008\prog08.asm).
Листинг 8.5. Чтение файла в память
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
;Начало
Begin: mov ax,3D00h
mov dx,offset File_name
int 21h
jc Error_file
mov Handle,ax
mov bx,ax
mov ah,3Fh
mov cx,0FDE8h
mov dx,offset Buffer
int 21h
mov ah,3Eh
mov bx,Handle
int 21h
mov dx,offset Mess_ok
Out_prog:
mov ah,9
int 21h
int 20h
Error_file:
mov dx,offset Mess_error
Глава 8. Учимся работать с файлами
83
jmp Out_prog
;=== Переменные ===
Handle dw 0
Mess_ok db 'Файл загружен в память! Смотрите в отладчике!$'
Mess_error db 'Не удалось открыть файл '
;Будем читать этот файл:
File_name db 'c:\msdos.sys',0,'!$'
Buffer equ $
CSEG ends
end Begin
Из этого примера вы узнаете очень много. Чтобы досконально разобраться
в этой программе, необходимо, как обычно, воспользоваться отладчиком. В нем
внимательно изучайте дамп (содержимое) памяти, на который указывает пара реги-
стров
ds:dx
.
Глава 9
Работа с файлами
9.1. Программа из прошлой главы
В листинге 9.1 приведены выдержки программы из главы 8 с комментариями.
Листинг 9.1. Программа из главы 8
...
;Опустим код CSEG и пр.
(01) Begin: mov ax,3D00h ;будем открывать файл для чтения
;Обратите внимание, как мы записываем операторы (сразу за меткой).
(02) mov dx,offset File_name
;ds:dx указывают на путь к файлу
(03) int 21h ;открываем
(04) jc Error_file
;Если произошла ошибка (нет такого файла, слишком много открытых файлов,
;ошибка чтения), то переходим на метку Error_file
;Запомним номер файла в переменной Handle.
;Для того чтобы прочитать файл, нужно в bx указать его номер, полученный
;после открытия, который находится в ax. Загрузка числа в один регистр из
;другого (а тем более, если используется ax) происходит быстрее, чем
;из памяти (переменной). Поэтому загружаем из ax, а не из переменной. Хотя
;запись mov bx,Handle не будет ошибочной.
(05) mov Handle,ax ;запомним номер файла в переменной Handle
(06) mov bx,ax
(07) mov ah,3Fh ;функция 3Fh — чтение файла
(08) mov cx,0FDE8h ;будем читать 0FDE8h = 65000 байт
;ds:dx должен указывать на буфер в памяти для чтения
(09) mov dx,offset Buffer
(10) int 21h ;все готово. Читаем...
(11) mov ah,3Eh ;закрываем файл
Глава 9. Работа с файлами
85
;Номер файла должен находиться в bx. Но т. к. регистр bx менялся, то
;загрузим его с нашей переменной (Handle)
(12) mov bx,Handle
(13) int 21h ;закрываем файл
;загрузим в dx строку с сообщением о том, что все в порядке.
(14) mov dx,offset Mess_ok
(15)Out_prog: mov ah,9 ;функция 09h — вывод строки на экран
(16) int 21h ;выводим строку
(17) int 20h ;выходим из программы
;Загрузим в dx строку с сообщением о том, что не смогли открыть файл...
(18)Error_file: mov dx,offset Mess_error
;...и пойдем на метку Out_prog (зачем нам дублировать код, если он уже есть?)
(19) jmp Out_prog
;=== Данные ===
(20) Handle dw 0 ;резерв 2 байта для нашей переменной
(21) Mess_ok db 'Файл загружен! Смотрите в отладчике!$'
;Строки (22)—(23) рассмотрим ниже
(22) Mess_error db 'Не удалось открыть (найти) файл '
(23) File_name db 'c:\msdos.sys',0,'!$'
(24) Buffer equ $
...
Запомните оператор
$
, который нами впервые используется в строке (24). При
ассемблировании нашей программы ассемблер заменит этот знак адресом, по кото-
рому он расположен (листинг 9.2).
Листинг 9.2. Использование оператора $
(01) CSEG segment
(02) assume cs:CSEG
(03) org 100h
(04) Begin:
(05) My_lab equ $
(06) My_lab2 equ $+2
(07) mov bx,offset My_lab
Часть II. Усложняем задачи
86
(08) mov dx,offset My_lab2
(09) int 20h
(10) CSEG ends
(11) end Begin
Строки (5) и (6) места в памяти не занимают (как и метки). Ассемблер-
программа запомнит, что метка
My_lab
находится по адресу
100h
(
org 100h
), а мет-
ка
My_lab2
—
102h
. На рис. 9.1 показан фрагмент приведенной выше программы,
который иллюстрирует использование оператора
$
.
Рис. 9.1. Использование оператора $
В программе из главы 8 мы размещаем метку
Buffer
в конце кода. Таким обра-
зом, команда
mov dx,offset Buffer
занесет в
dx
последний свободный байт в нашем
сегменте
CSEG
. По этому адресу мы и будем загружать программу в память. В от-
ладчике это хорошо видно.
В строке (22) находится переменная с сообщением о том, что файл открыть не-
возможно. Однако она не заканчивается символом
$
, как обычно. Это значит, что
функция
09h
прерывания
21h
продолжит выводить символы до тех пор, пока в па-
мяти не встретится этот символ. Если мы посмотрим на строку (23), то увидим, что
она как раз заканчивается знаком
$
. Это значит, что при выводе символов из строки
(22) функция выведет также и те символы, которые находятся в строке (23).
(22) Mess_error db 'Не удалось открыть (найти) файл '
(23) File_name db 'c:\msdos.sys',0,'!$'
Если файл не был найден, функция
09h
выведет на экран буквально следующее
(рис. 9.2):
Не удалось открыть (найти) файл c:\msdos.sys !