Чтение, запись, позиционирование в файле
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 в приведенной выше программе можно закомментировать.