40h: запись файла с меньшей длиной.

Тема в разделе "WASM.BEGINNERS", создана пользователем _mm_, 30 май 2011.

  1. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Друзья, подскажите, как записать файл с длиной, меньше считанной.
    Вначале думал, глюк, потом создал маленькую программу и убедился, что запись производится с длиной, не меньшей, чем она была, даже если в cx число 1:

    Код (Text):
    1.                         ;Всё, что следует за значком ";" - это комментарий.
    2.  
    3. .286                        ;Разрешает ассемблирование   непривилегированных   инструкций
    4.                             ;процессора 80286  (реальный  режим) и инструкций арифметического
    5.                             ;сопроцессора 80287.
    6.  
    7. CSEG segment                    ;Даём имя сегменту, а точнее определяем абсолютный
    8.                         ;сегмент в памяти программ по определённому адресу.
    9.                         ;Имя нашего сегмента будет CSEG.
    10.  
    11. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG       ;Задаём сегментные регистры, которые будем использовать для
    12.                             ;вычисления действующего адреса для всех меток и переменных, опре-
    13.                             ;делённых  для  сегмента  или группы сегментов с указанным именем.
    14.                         ;У нас их четыре, - CS, DS, ES, SS и они будут указывать на наш
    15.                         ;единственный сегмент (мы его назвали CSEG).
    16.  
    17. org 100h                    ;Устанавливаем счётчик инструкций в текущем сегменте в  соот-
    18.                             ;ветствии с адресом, задаваемым "выражением".
    19.                         ;Сейчас этот счётчик равен 100h - используется для всех программ
    20.                         ;типа .com
    21.  
    22. begin:                      ;Метка начала программы.
    23.  
    24.                                            
    25. mov ax,3D02h                    ;Загружаем в регистр ah число 3Dh (функция открытия
    26.                         ;файла с записью), а в al число 02h (пишем в конец).
    27.                         ;Можно было записать и так - mov ah,3Dh
    28.                         ;mov al,02h
    29.  
    30. mov dx,offset File_mask                           ;Указываем адрес файла в DTA (по умолчанию он 1Eh от начала DTA,
    31. int 21h                     ;Выполняем функцию.
    32.  
    33. mov Handle,ax                   ;При открытии файлу будет присвоен номер, его и
    34.                         ;сохраняем для дальнейших действий,
    35. mov bx,ax                   ;а заодно и сохраняем его в bx.
    36.  
    37. mov ah,3Fh                  ;Читаем файл
    38. mov cx,1024                                     ;с длиной 1Кб.
    39. mov dx,offset Finish
    40. int 21h                     ;Выполняем функцию.
    41.  
    42.  
    43. mov dx,0h                   ;Устанавливаем указатель с начала файла +0h.
    44. mov cx,0h                                       ;+0h мы указали потому, что будем
    45. mov ax,4200h                                    ;перезаписывать считанный файл с первого байта.
    46. int 21h                                        
    47.  
    48. mov ah,40h                                      ;Записываем программу (в т.ч.$) из смещения Finish
    49. mov dx,offset Finish                            ;по адресу, указанному выше.
    50. mov cx,1
    51. int 21h  
    52.                                      
    53. mov ah,3Eh                                      ;Используем функцию закрытия файла.
    54. mov bx,Handle                                   ;Для закрытия обязательно "вспоминаем" его номер,
    55.                         ;номер у нас был сохранён в Handle.
    56. int 21h                                         ;Выполняем функцию.
    57.  
    58. Message_ok:                 ;Подпрограмма успешного вывода строки и выхода.
    59. mov dx,offset Mess_ok
    60. call Print
    61. int 20h
    62.  
    63. Print proc
    64. mov ah,9
    65. int 21h
    66. ret
    67. Print endp
    68.          
    69. File_mask db 'HELLO.COM',0,'!$'             ;Маска файла.
    70.  
    71. Mess_ok db 'Готово!$'      ;Успешное сообщение.
    72.  
    73. Handle dw 0FFFFh                                ;Определяем переменную (для идентификатора файла).
    74.  
    75. Finish equ $                    ;Метка конца нашей программы!
    76.  
    77. CSEG ends
    78. end begin
    В качестве теста можно создать в этом же каталоге HELLO.COM с длиной > 1 байт.

    Что делать? У меня что-то не так, или всё так и есть? Создавать новый файл (3Ch) с нулевой длиной под тем же именем, и туда записывать? А что тогда с предыдущим BX?

    Заранее спасибо.
     
  2. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    mov ah,40h ;Записываем программу (в т.ч.$) из смещения Finish
    mov dx,offset Finish ;по адресу, указанному выше.
    mov cx,0 <-----------------файл будет обрезан или расширен до текущего положения файлового указателя.
    int 21h
     
  3. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Нашёл решение: перед функцией 4200h нужно создать новый файл:


    Код (Text):
    1. mov ah,3Ch                  ;Создадим новый файл
    2. xor cx,cx                   ;с нулевой длиной
    3. mov dx,offset dta+1Eh               ;и храняшимся в DTA именем.
    4. int 21h
    5.  
    6. mov bx,Handle
    Только неясно, что делать с дескрипторами в bx и нужно ли закрывать старый открытый файл.
     
  4. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Попробовал - что-то не получается... Как этот указатель устанавливать, и тоже функцией 4200h (с начала)?
     
  5. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    ну думаю так:
    Код (Text):
    1. .286                        ;Разрешает ассемблирование   непривилегированных   инструкций
    2.                                ;процессора 80286  (реальный  режим) и инструкций арифметического
    3.                                ;сопроцессора 80287.
    4.  
    5. CSEG segment                    ;Даём имя сегменту, а точнее определяем абсолютный
    6.                         ;сегмент в памяти программ по определённому адресу.
    7.                         ;Имя нашего сегмента будет CSEG.
    8.  
    9. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG       ;Задаём сегментные регистры, которые будем использовать для
    10.                                ;вычисления действующего адреса для всех меток и переменных, опре-
    11.                                ;делённых  для  сегмента  или группы сегментов с указанным именем.
    12.                         ;У нас их четыре, - CS, DS, ES, SS и они будут указывать на наш
    13.                         ;единственный сегмент (мы его назвали CSEG).
    14.  
    15. org 100h                     ;Устанавливаем счётчик инструкций в текущем сегменте в  соот-
    16.                                ;ветствии с адресом, задаваемым "выражением".
    17.                         ;Сейчас этот счётчик равен 100h - используется для всех программ
    18.                         ;типа .com
    19.  
    20. begin:                        ;Метка начала программы.
    21.  
    22.                                            
    23. mov ax,3D02h                    ;Загружаем в регистр ah число 3Dh (функция открытия
    24.                         ;файла с записью), а в al число 02h (пишем в конец).
    25.                         ;Можно было записать и так - mov ah,3Dh
    26.                         ;mov al,02h
    27.  
    28. mov dx,offset File_mask                           ;Указываем адрес файла в DTA (по умолчанию он 1Eh от начала DTA,
    29. int 21h                        ;Выполняем функцию.
    30.  
    31. mov Handle,ax                    ;При открытии файлу будет присвоен номер, его и
    32.                         ;сохраняем для дальнейших действий,
    33. mov bx,ax                    ;а заодно и сохраняем его в bx.
    34.  
    35. mov ah,3Fh                     ;Читаем файл
    36. mov cx,1024                                     ;с длиной 1Кб.
    37. mov dx,offset Finish
    38. int 21h                        ;Выполняем функцию.
    39.  
    40.  
    41. mov dx,0h                    ;Устанавливаем указатель с начала файла +0h.
    42. mov cx,0h                                       ;+0h мы указали потому, что будем
    43. mov ax,4200h                                    ;перезаписывать считанный файл с первого байта.
    44. int 21h                                        
    45.  
    46. mov ah,40h                                      ;Записываем программу (в т.ч.$) из смещения Finish
    47. mov dx,offset Finish                            ;по адресу, указанному выше.
    48. mov cx,1
    49. int 21h  
    50. mov ah,40h                                    
    51.  
    52. mov cx,0  <-----------------файл будет обрезан или расширен до текущего положения файлового указателя.
    53. int 21h
    54.  
    55.                                      
    56. mov ah,3Eh                                      ;Используем функцию закрытия файла.
    57. mov bx,Handle                                   ;Для закрытия обязательно "вспоминаем" его номер,
    58.                         ;номер у нас был сохранён в Handle.
    59. int 21h                                         ;Выполняем функцию.
    60.  
    61. Message_ok:                    ;Подпрограмма успешного вывода строки и выхода.
    62. mov dx,offset Mess_ok
    63. call Print
    64. int 20h
    65.  
    66. Print proc
    67. mov ah,9
    68. int 21h
    69. ret
    70. Print endp
    71.          
    72. File_mask db 'HELLO.COM',0,'!$'                ;Маска файла.
    73.  
    74. Mess_ok db 'Готово!$'      ;Успешное сообщение.
    75.  
    76. Handle dw 0FFFFh                                ;Определяем переменную (для идентификатора файла).
    77.  
    78. Finish equ $                    ;Метка конца нашей программы!
    79.  
    80. CSEG ends
    81. end begin
     
  6. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Ура! НЕ сообразил, что можно использовать функцию повторно! Спасибо!

    А если создавать новый файл, что с дескрипторами и закрытием старого файла?
     
  7. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    _mm_
    Не совсем понял вопроса, но можно считывать фаил в память, закрывать его, затем удалять. Снова создавать фаил с тем же именем и из памяти записывать его. Примерно такой алгоритм, но зачем оно надо?