Друзья, подскажите, как записать файл с длиной, меньше считанной. Вначале думал, глюк, потом создал маленькую программу и убедился, что запись производится с длиной, не меньшей, чем она была, даже если в cx число 1: Код (Text): ;Всё, что следует за значком ";" - это комментарий. .286 ;Разрешает ассемблирование непривилегированных инструкций ;процессора 80286 (реальный режим) и инструкций арифметического ;сопроцессора 80287. CSEG segment ;Даём имя сегменту, а точнее определяем абсолютный ;сегмент в памяти программ по определённому адресу. ;Имя нашего сегмента будет CSEG. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG ;Задаём сегментные регистры, которые будем использовать для ;вычисления действующего адреса для всех меток и переменных, опре- ;делённых для сегмента или группы сегментов с указанным именем. ;У нас их четыре, - CS, DS, ES, SS и они будут указывать на наш ;единственный сегмент (мы его назвали CSEG). org 100h ;Устанавливаем счётчик инструкций в текущем сегменте в соот- ;ветствии с адресом, задаваемым "выражением". ;Сейчас этот счётчик равен 100h - используется для всех программ ;типа .com begin: ;Метка начала программы. mov ax,3D02h ;Загружаем в регистр ah число 3Dh (функция открытия ;файла с записью), а в al число 02h (пишем в конец). ;Можно было записать и так - mov ah,3Dh ;mov al,02h mov dx,offset File_mask ;Указываем адрес файла в DTA (по умолчанию он 1Eh от начала DTA, int 21h ;Выполняем функцию. mov Handle,ax ;При открытии файлу будет присвоен номер, его и ;сохраняем для дальнейших действий, mov bx,ax ;а заодно и сохраняем его в bx. mov ah,3Fh ;Читаем файл mov cx,1024 ;с длиной 1Кб. mov dx,offset Finish int 21h ;Выполняем функцию. mov dx,0h ;Устанавливаем указатель с начала файла +0h. mov cx,0h ;+0h мы указали потому, что будем mov ax,4200h ;перезаписывать считанный файл с первого байта. int 21h mov ah,40h ;Записываем программу (в т.ч.$) из смещения Finish mov dx,offset Finish ;по адресу, указанному выше. mov cx,1 int 21h mov ah,3Eh ;Используем функцию закрытия файла. mov bx,Handle ;Для закрытия обязательно "вспоминаем" его номер, ;номер у нас был сохранён в Handle. int 21h ;Выполняем функцию. Message_ok: ;Подпрограмма успешного вывода строки и выхода. mov dx,offset Mess_ok call Print int 20h Print proc mov ah,9 int 21h ret Print endp File_mask db 'HELLO.COM',0,'!$' ;Маска файла. Mess_ok db 'Готово!$' ;Успешное сообщение. Handle dw 0FFFFh ;Определяем переменную (для идентификатора файла). Finish equ $ ;Метка конца нашей программы! CSEG ends end begin В качестве теста можно создать в этом же каталоге HELLO.COM с длиной > 1 байт. Что делать? У меня что-то не так, или всё так и есть? Создавать новый файл (3Ch) с нулевой длиной под тем же именем, и туда записывать? А что тогда с предыдущим BX? Заранее спасибо.
mov ah,40h ;Записываем программу (в т.ч.$) из смещения Finish mov dx,offset Finish ;по адресу, указанному выше. mov cx,0 <-----------------файл будет обрезан или расширен до текущего положения файлового указателя. int 21h
Нашёл решение: перед функцией 4200h нужно создать новый файл: Код (Text): mov ah,3Ch ;Создадим новый файл xor cx,cx ;с нулевой длиной mov dx,offset dta+1Eh ;и храняшимся в DTA именем. int 21h mov bx,Handle Только неясно, что делать с дескрипторами в bx и нужно ли закрывать старый открытый файл.
Попробовал - что-то не получается... Как этот указатель устанавливать, и тоже функцией 4200h (с начала)?
ну думаю так: Код (Text): .286 ;Разрешает ассемблирование непривилегированных инструкций ;процессора 80286 (реальный режим) и инструкций арифметического ;сопроцессора 80287. CSEG segment ;Даём имя сегменту, а точнее определяем абсолютный ;сегмент в памяти программ по определённому адресу. ;Имя нашего сегмента будет CSEG. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG ;Задаём сегментные регистры, которые будем использовать для ;вычисления действующего адреса для всех меток и переменных, опре- ;делённых для сегмента или группы сегментов с указанным именем. ;У нас их четыре, - CS, DS, ES, SS и они будут указывать на наш ;единственный сегмент (мы его назвали CSEG). org 100h ;Устанавливаем счётчик инструкций в текущем сегменте в соот- ;ветствии с адресом, задаваемым "выражением". ;Сейчас этот счётчик равен 100h - используется для всех программ ;типа .com begin: ;Метка начала программы. mov ax,3D02h ;Загружаем в регистр ah число 3Dh (функция открытия ;файла с записью), а в al число 02h (пишем в конец). ;Можно было записать и так - mov ah,3Dh ;mov al,02h mov dx,offset File_mask ;Указываем адрес файла в DTA (по умолчанию он 1Eh от начала DTA, int 21h ;Выполняем функцию. mov Handle,ax ;При открытии файлу будет присвоен номер, его и ;сохраняем для дальнейших действий, mov bx,ax ;а заодно и сохраняем его в bx. mov ah,3Fh ;Читаем файл mov cx,1024 ;с длиной 1Кб. mov dx,offset Finish int 21h ;Выполняем функцию. mov dx,0h ;Устанавливаем указатель с начала файла +0h. mov cx,0h ;+0h мы указали потому, что будем mov ax,4200h ;перезаписывать считанный файл с первого байта. int 21h mov ah,40h ;Записываем программу (в т.ч.$) из смещения Finish mov dx,offset Finish ;по адресу, указанному выше. mov cx,1 int 21h mov ah,40h mov cx,0 <-----------------файл будет обрезан или расширен до текущего положения файлового указателя. int 21h mov ah,3Eh ;Используем функцию закрытия файла. mov bx,Handle ;Для закрытия обязательно "вспоминаем" его номер, ;номер у нас был сохранён в Handle. int 21h ;Выполняем функцию. Message_ok: ;Подпрограмма успешного вывода строки и выхода. mov dx,offset Mess_ok call Print int 20h Print proc mov ah,9 int 21h ret Print endp File_mask db 'HELLO.COM',0,'!$' ;Маска файла. Mess_ok db 'Готово!$' ;Успешное сообщение. Handle dw 0FFFFh ;Определяем переменную (для идентификатора файла). Finish equ $ ;Метка конца нашей программы! CSEG ends end begin
Ура! НЕ сообразил, что можно использовать функцию повторно! Спасибо! А если создавать новый файл, что с дескрипторами и закрытием старого файла?
_mm_ Не совсем понял вопроса, но можно считывать фаил в память, закрывать его, затем удалять. Снова создавать фаил с тем же именем и из памяти записывать его. Примерно такой алгоритм, но зачем оно надо?