Немного параноидальная проверка записи в файл в ДОС и изменение regs

Тема в разделе "WASM.BEGINNERS", создана пользователем Lurker, 3 июн 2008.

  1. Lurker

    Lurker New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2005
    Сообщения:
    6
    Здравствуйте, есть следующий код некоторой подпрограммы:
    Код (Text):
    1. ...
    2. mov  ah, 40h
    3. mov  bx, FileID
    4. mov  cx, SIZE
    5. mov  dx, offset Buffer
    6. int    21h
    7. jc     @@End
    8. sub   ax, cx    ; ОШИБКА, если записались не все байты.
    9. neg   ax
    10. @@End:
    11. ; CF = 1 -  признак ошибки.
    12. ret
    Собственно параноидальный вопрос следующий.
    В справочнике по прерываниям не сказано, какие существуют СТАНДАРТНЫЕ ПРАВИЛА для соотношений между AX и CX, когда ошибки нет.
    МОЖНО ЛИ НАДЕЯТЬСЯ НА ТО, ЧТО, КОГДА ОШИБКИ НЕТ, ТО AX всегда меньше или равен CX? И, если это входит в НЕИЗВЕСТНЫЙ МНЕ СТАНДАРТ, удалить NEG и заменить SUB на CMP?

    И ещё вопрос.
    1)Нужно ли при вызовах функций ДОС ВСЕГДА сохранять изменяемые/используемые ими регистры?
    Я обычно пишу например так:
    Код (Text):
    1. mov  ah, 9
    2. mov  dx, offset Text1
    3. int    21h
    4. mov  dx, offset Text2
    5. int    21h
    Это работает, но ПРАВИЛЬНО ЭТО ИЛИ НЕТ(СТАНДАРТ ИЛИ НЕСТАНДАРТ)?
    2)Нужно ли ВСЕГДА сохрянять регистр флагов?

    Извиняюсь за детские вопросы, просто ответов нигде нет.
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Lurker
    В справочнике по прерываниям не сказано, какие существуют СТАНДАРТНЫЕ ПРАВИЛА для соотношений между AX и CX
    Например, в шестом TECH Help'е, в описании DOS Fn 40H: Write to File via Handle есть замечание
    ...
    Notes: You should always compare the return value of AX (number of
    bytes written) to CX (requested write size):

    - if AX = CX, the write was successful
    - if AX < CX, an error occurred (most likely a full disk).
    Note that Carry is not set for this "error".
    ...


    Нужно ли при вызовах функций ДОС ВСЕГДА сохранять изменяемые/используемые ими регистры?
    Про "изменяемые", если тебе нужны их оригинальные значения, то сохраняй.
    Про "используемые". Если необходимо уменьшить код, то надо исследовать поведение конкретных функций, конкретных версий/клонов DOS. Если такая задача не стоит, то я бы не стал рассчитывать, что значение не изменится. Твой пример не показателен, т.к. нет необходимости сохранять и восстанавливать AH, достаточно добавить mov ah,9.

    2)Нужно ли ВСЕГДА сохрянять регистр флагов?
    Что значит "ВСЕГДА"? Надо смотреть по ситуации.

    ps мне не известны документированные правила/соглашения по используемым регистрам, кроме как в описании конкретных функций.
     
  3. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    Lurker
    Давно это было, при работе в DOS'е открытие, чтение и закрытие я делал так
    Код (Text):
    1.     MOV AX,3D00h
    2.     MOV DX,OFFSET FILENAME
    3.     INT 21h     ;открыть для чтения файл
    4.     MOV BX,AX
    5.     MOV AX,4202h
    6.     XOR CX,CX ;определяем длину файла для чего
    7.     XOR DX,DX ;позиционируемся в конец файла
    8.     INT 21h    
    9.     PUSH AX; в AX получаем длину файла
    10.     MOV AX,4200h    ;позиционируемся в начало файла
    11.     INT 21h
    12.     MOV AH,3Fh      ;читаем файл
    13.     MOV DX,OFFSET BUFFER ;указываем на буфер
    14.     POP CX; передаем длину файла в CX
    15.     INT 21h
    16.     MOV AH,3Eh
    17.     INT 21h     ;закрыли файл
    Это в случае если под буфер я могу отвести место большее, чем длина файла. Если я не могу себе позволить роскошь в виде большого буфера, например под буфер выделено всего 100 байт, тогда
    Код (Text):
    1.     MOV AX,3D00h
    2.     MOV DX,OFFSET FILENAME
    3.     INT 21h     ;открыть для чтения файл
    4.     MOV BX,AX
    5. a1: MOV AH,3Fh      ;читаем файл
    6.     MOV DX,OFFSET BUFFER ;указываем на буфер
    7.     MOV CX,100
    8.     INT 21h
    9.     pushf
    10. ; что-то делаем с прочитанными байтами
    11.     popf
    12.     jnc a1; если считано меннее 100 байт, значит файл закончился
    13.     MOV AH,3Eh; и нужно его закрыть
    14.     INT 21h
    По тексту программ видно, что handle файла отправленный в bx сразу после открытия файла не меняется до самого закрытия файла. INT 21h - если это не оговорено особо, меняет значения только в регистре флагов и в регистре AX. При выходе из функции записи, если ошибки не было, тогда CF=0 и в регистре AX находится количество записанных байт равеное числу в CX. Если произошла ошибка, CF=1 и в регистре AX находится число меньшее CX, что и говорит об ошибке. Поэтому твой фрагмент
    Код (Text):
    1. int    21h
    2. jc     @@End
    3. sub   ax, cx    ; на эту ветку попадаешь как раз тогда, когда ошибки нет и ax==cx
    4. neg   ax
    5. @@End:
    я бы переписал так
    Код:
    int 21h
    jnc @@End; нет ошибки - переходим к следующей фазе программы
    xchg cx,ax
    sub ax, cx ; иначе - в ax сколько байт не записалось из буфера
    @@End:
     
  4. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Mikl__
    я бы переписал так
    Поправь сам.
     
  5. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Mikl__
    jnc @@End; нет ошибки - переходим к следующей фазе программы
    А как же Tech help'овское "should always compare ... full disk ... Carry is not set for this error"?