Иллюстрированный самоучитель по задачам и примерам Assembler

Чтение, запись, позиционирование в файле

cycl2: lea si,buf,buf_in
mov al.buf.lenjn
cbw ptush si
add si.ax
incsi учитываем неучтенный в lenjn символ 0dh
;добавляем Oah в конец введенной строки
mov byte ptr [si],Oah;выводим в файл:
popdx указатель на область, откуда будем выводить строку
add ах.2 учитываем неучтенный в len_in символ 0dh
movcx.ax:длина выводимых данных
movprev.ax.сохраним длину для корректировки при выводе следующей строки
mov bx.handle movah.40h int 21h jc exit
;сбрасываем буфер, чтобы смотреть изменения в файле при работе в отладчике –
:легче запретить (см. обсуждение ниже)
mov bx,handle
mov ah,68h Int 21h:вводим очередную строку с клавиатуры
lea dx.buf
mov ah.Oah
Int 21h:для красоты ввода выводим на экран символ Oah
mov dl.Oah
mov ah,2
int21h
;……использование 42h с отрицательным смещением относительно
:текущего значения файлового указателя:
устанавливаем файловый указатель в позицию вывода следующей строки
;с учетом того, что выводим с конца (текущей позиции) файла:
хоr есх.есх
mov al.buf,len_in
cbw
add prev.ax
add prev.2 учитываем наличие OdOah
sub ecx.prev_d:получаем отрицательное смещение – сформируем его в паре СХ:DX
shrd edx,ecx,16
shr edx.16:довернем edx
shr ecx.16:и есх устанавливаем файловую позицию для записи очередной строки
mov bx,handle
mov ah.42h
moval.l;смещение от текущей позиции
int 21h:сравним текущую позицию с middle
shl eax.16
shld edx,eax,16
cmp edx,middle
jl exit
jmp cycl2 exit:

Программа выглядит не очень эстетично, но главная ее цель достигнута – показать работу с файловым указателем при записи в файл. Мы попробовали разные варианты: позиционирование на конец файла (при этом можно узнать длину файла); использование отрицательного смещения (задавая нулевое значение в CX:DX при al = 1 можно получить в DX:AX текущую позицию в файле); расширение файла путем задания в СХ: DX заведомо большего значения, чем длина файла. Как видно из программы выше, все эти и другие эффекты достигаются за счет манипулирования значениями в парах СХ:DX и DX:AX, а также в регистре AL, где задается начальное положение в файле, относительно которого производится операция чтения-записи.

В заключение рассмотрения функции 40h записи в файл отметим то, для чего мы использовали функцию сброса буферов на диск 68h. Для этого коротко необходимо коснуться проблемы буферизации ввода-вывода в MS DOS. MS DOS использует буферизацию ввода-вывода для ускорения работы с диском. При этом, р частности, данные, записываемые на диск, не записываются на него сразу, а помещаются вначале в буфер. Запись буфера на диск производится при его заполнении.

Буферизацию эффективно использовать при интенсивной работе с одними и теми же данными. Тогда при необходимости чтения данных с диска они 6уДУт читаться из буфера. В нашей программе буферизация нам только мешала, так как при работе в отладчике мы не могли своевременно наблюдать за изменениями выходного файла my_file.txt. Для этого нам приходилось использовать функцию 68h для принудительного сохранения буферов на диск.

Вход: АН = 68h; BX = дескриптор файла. Выход: CF = 0 в случае успеха; CF = 1 – АХ = код ошибки.

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

Для нашей задачи буферизацию лучше вовсе запретить, тогда отпадет необходимость в принудительном сохранении строк в файле для того, чтобы в динамике отслеживать его изменения. Для этого при вызове функции 6ch в регистре ВН необходимо установить бит 6 следующим образом: 6 = 0 – использовать стандартную для MS DOS буферизацию; 6 = 1 – отменить стандартную для MS DOS буферизацию. В нашем примере это можно сделать так:

:……открываем файл-------------------------------------
хоrсх.сх атрибуты файла – обычный файл
mov bx.4002h:режим доступа – доступ для чтения-записи, запрет буферизации
movdx,12h:если файл существует, то открыть его без сохранения прежнего
содержимого, в обратном случае создать файл Ids si.point_fname
:формируем указатель на имя файла movah.6ch
:номер функции DOS int21h открываем (создаем) файл jc exit
:если ошибка, то переход на конец
--------------------------------------------------------------------------

Все вызовы функции 68h в приведенной выше программе можно закомментировать.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.