1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Работа с PSP и функция 4Eh.

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

  1. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Всем добрый день.
    Имеется небольшая программка под DOS, ищущая файлы в текущем каталоге. Функция 4Eh пишет имя файла в DTA. Перед этим надо сохранять PSP (я его кидаю в конец файла в памяти, потом возвращаю). DTA находится по адресу 80h, а имя найденного файла, как я понимаю - в 9Eh.

    Проблема в строке 40. При вызове функции открытия файла с установкой dx на это самое имя mov dx,9Eh - com-файл отказывается создаваться! Причём нет никаких сообщений об ошибках - говорит, что всё нормально (obj-файл создаётся). Если же просто поменять mov dx,9Eh на mov dx,80h - всё создаётся, но мне это, понятно, не нужно.

    В чём проблема? Мне кажется, я что-то недопонимаю в PSP.
    Подскажите, пожалуйста.
    Вот сам текст:

    Код (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. mov si,0                    ;Сохраняем PSP.
    25. mov di,offset Finish                ;Куда перемещать.
    26. mov cx,100h                 ;Перемещаем 100h байт.
    27. rep movsb
    28.  
    29. call Find_first                 ;Ищем первый файл.
    30. jc Error_file_metka             ;Нет txt-файлов - на выход.
    31.  
    32. goto_cikl:                  ;Начало цикла.
    33.                                                
    34. mov ax,3D02h                    ;Загружаем в регистр ah число 3Dh (функция открытия
    35.                         ;файла с записью), а в al число 02h (пишем в конец).
    36.                         ;Можно было записать и так - mov ah,3Dh
    37.                         ;mov al,02h
    38.  
    39. ;mov dx,80h
    40. mov dx,9Eh                                      ;Указываем адрес файла в DTA (по умолчанию он 80h,
    41.                         ;+1Eh - имя файла.
    42. int 21h                     ;Выполняем функцию.
    43.  
    44. mov Handle,ax                   ;При открытии файлу будет присвоен номер, его и
    45.                         ;сохраняем для дальнейших действий,
    46. mov bx,ax                   ;а заодно и сохраняем его в bx.
    47.  
    48. mov ax,4202h                    ;Используем функцию установки указателя.
    49.                         ;al=02h - устанавливаем в конец.
    50. mov cx,0                                        ;Нам надо записать прямо в конец файла, поэтому
    51. mov dx,0                                        ;обнулим cx и dx (иначе будет писать далее на
    52.                                                 ;значение (CX * 65536) + DX
    53. int 21h                     ;Выполняем функцию.
    54.  
    55. mov ah,40h                  ;Используем функцию записи в файл.
    56. mov dx,offset one               ;В dx занесём адрес смещения к записываемому
    57.                         ;тексту.
    58. mov cx,1                    ;Число записываемых байт - 1.
    59. int 21h                                         ;Выполняем функцию.
    60.  
    61. mov ah,3Eh                                      ;Используем функцию закрытия файла.
    62. mov bx,Handle                                   ;Для закрытия обязательно "вспоминаем" его номер,
    63.                         ;номер у нас был сохранён в Handle.
    64. int 21h                                         ;Выполняем функцию.
    65.  
    66. call Find_next                  ;Ищем следующий файл.
    67. jc goto_cikl                    ;Нашли ещё один файл; прыгаем на метку.
    68.  
    69. mov si,offset Finish                ;Восстанавливаем PSP.
    70. mov di,0   
    71. mov cx,100h                 ;Перемещаем 100h байт.
    72. rep movsb
    73.  
    74.  
    75. mov ah,9                    ;Загружаем в регистр ah число 9 (указываем функцию).
    76. mov dx,offset Vse_ok                ;Указываем, что за фразу мы будем выводить.
    77. int 21h                     ;Выводим фразу.
    78.  
    79. mov ah,4Ch                  ;Используем для выхода из программы.
    80. int 21h
    81.  
    82. Error_file_metka:               ;Вывод сообщения об ошибке.
    83.  
    84. mov si,offset Finish                ;Восстанавливаем PSP.
    85. mov di,0   
    86. mov cx,100h                 ;Перемещаем 100h байт.
    87. rep movsb
    88.  
    89. mov ah,9                    ;Загружаем в регистр ah число 9 (указываем функцию).
    90. mov dx,offset Error_file            ;Указываем, что за фразу мы будем выводить.
    91. int 21h                     ;Выводим фразу.
    92.  
    93. mov ah,4Ch                  ;Используем для выхода из программы.
    94. int 21h
    95.  
    96. Find_first proc                                 ;Подпрограмма поиска первого файла.
    97. mov ah,4Eh                  ;Ищем первый файл по маске (функция 4Eh).
    98. xor cx,cx                   ;Атрибуты обычные. Смотрим, что в CX.
    99. mov dx,offset File_name             ;Адрес маски в DS:DX
    100. int 21h                     ;В DTA заносится имя найденного файла.
    101. ret
    102. Find_first endp
    103.                                                 ;Подпрограмма поиска следующего файла.
    104. Find_next proc
    105. xor dx,dx                   ;DS:DX указывают на DTA (DX=0).
    106. xor cx,cx                                   ;CX=0.
    107. mov ah,4Fh                                  ;4Fh - поиск следующего файла.
    108. int 21h                                         ;В DTA заносится имя найденного файла.
    109. ret
    110. Find_next endp
    111.          
    112. File_name db '*.txt',0              ;Маска файла.
    113.  
    114. Handle dw 0FFFFh                ;Определяем переменную Handle, которую используем для
    115.                         ;хранения номера файла. По умолчанию она равна 0FFFFh.
    116.  
    117. one db '1'                  ;Определяем переменную one, содержащую символ "1",
    118.                         ;которую мы будем приписывать в конец файла.
    119. Vse_ok db 'Файл найден и обновлён. Всем спасибо.$';Успешное сообщение и сообщение об ошибке (ниже).
    120.  
    121. Error_file db 'Файлы не найдены. Поместите файл *.txt в каталог с программой.$'
    122.  
    123. Finish equ $                                    ;Метка конца программы.
    124.  
    125. CSEG ends
    126. end begin
     
  2. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    не проще ли сделать так
    Код (Text):
    1. mov ah, 26
    2. mov dx, Finish
    3. int 33
    и получать информацию о файле в не в psp, а по метке Finish
     
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    А простите у Вас Масм(Тасм)
    Код (Text):
    1. mov ah, 26
    2. mov dx, offset Finish
    3. int 33
     
  4. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    не целевое у вас использование mov :)

    Код (Text):
    1. mov ah, 26 ;set addr(dta)
    2. lea dx, Finish
    3. int 33
     
  5. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Код (Text):
    1. mov ah,1Ah
    2. mov dx,offset Finish
    3. int 21h
    К своей программе я это добавлял в самом начале (но не помогло). Но я правильно понимаю, что по адресу 80h располагается изначально командная строка? А тогда где она располагается при переустановке DTA? Там же или на Finish + 80h? Спрашиваю для того, чтобы программа не зависла. Имеет ли смысл переброс PSP с DTA в принципе?

    Как бы то ни было, всё равно имя файла, необходимое для функции открытия, располагается по адресу:

    Код (Text):
    1. mov ax,3D02h                    ;Загружаем в регистр ah число 3Dh (функция открытия
    2.                         ;файла с записью), а в al число 02h (пишем в конец).
    3.                         ;Можно было записать и так - mov ah,3Dh
    4.                         ;mov al,02h
    5.  
    6. mov dx,offset Finish
    7. add dx,1Eh
    8.                                             ;Указываем адрес файла в DTA (по умолчанию он 80h,
    9.                         ;+1Eh - имя файла.
    10. int 21h                     ;Выполняем функцию.
    В этом вся и беда.
    В этом виде при ml tratata.asm /AT программа сообщений об ошибок не выдаёт, но создаёт только obj-файл.
    Если же изменить add dx,1Eh хотя бы на add dx,1Dh - всё работает.
    В чём прикол? Почему линковщик не создаёт com-файл из-за точного указания смещения в dx?
     
  6. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    _mm_
    при запуске она располагается по адресу psp+80h
    потом, после переустановки с помощью 1ah сразу по адресу в вашем случае с Finish
     
  7. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    этот код вызывает у меня недоверие - я немогу утверждать глядя на ваш код что dta начинается с finish
     
  8. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    В отладчике я вижу имя первого найденного файла по адресу Finish+1Eh. Проблема в том, что как только указываешь это смещение в dx, com-файл не создаётся. А укажешь +1Dh или 1Fh - создаётся. Но мне-то нужно +1Eh.
     
  9. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Вот последняя версия кода под masm.

    Код (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. mov ah,1Ah
    25. mov dx,offset Finish
    26. int 21h
    27.  
    28. call Find_first                 ;Ищем первый файл.
    29. jc Error_file_metka             ;Нет txt-файлов - на выход.
    30.  
    31. goto_cikl:                  ;Начало цикла.
    32.                                                
    33. mov ax,3D02h                    ;Загружаем в регистр ah число 3Dh (функция открытия
    34.                         ;файла с записью), а в al число 02h (пишем в конец).
    35.                         ;Можно было записать и так - mov ah,3Dh
    36.                         ;mov al,02h
    37.  
    38. mov dx,offset Finish
    39. add dx,1Eh
    40.                                             ;Указываем адрес файла в DTA (по умолчанию он 80h,
    41.                         ;+1Eh - имя файла.
    42. int 21h                     ;Выполняем функцию.
    43.  
    44. mov Handle,ax                   ;При открытии файлу будет присвоен номер, его и
    45.                         ;сохраняем для дальнейших действий,
    46. mov bx,ax                   ;а заодно и сохраняем его в bx.
    47.  
    48. mov ax,4202h                    ;Используем функцию установки указателя.
    49.                         ;al=02h - устанавливаем в конец.
    50. mov cx,0                                        ;Нам надо записать прямо в конец файла, поэтому
    51. mov dx,0                                        ;обнулим cx и dx (иначе будет писать далее на
    52.                                                 ;значение (CX * 65536) + DX
    53. int 21h                     ;Выполняем функцию.
    54.  
    55. mov ah,40h                  ;Используем функцию записи в файл.
    56. mov dx,offset one               ;В dx занесём адрес смещения к записываемому
    57.                         ;тексту.
    58. mov cx,1                    ;Число записываемых байт - 1.
    59. int 21h                                         ;Выполняем функцию.
    60.  
    61. mov ah,3Eh                                      ;Используем функцию закрытия файла.
    62. mov bx,Handle                                   ;Для закрытия обязательно "вспоминаем" его номер,
    63.                         ;номер у нас был сохранён в Handle.
    64. int 21h                                         ;Выполняем функцию.
    65.  
    66. call Find_next                  ;Ищем следующий файл.
    67. jc goto_cikl                    ;Нашли ещё один файл; прыгаем на метку.
    68.  
    69. mov ah,9                    ;Загружаем в регистр ah число 9 (указываем функцию).
    70. mov dx,offset Vse_ok                ;Указываем, что за фразу мы будем выводить.
    71. int 21h                     ;Выводим фразу.
    72.  
    73. mov ah,4Ch                  ;Используем для выхода из программы.
    74. int 21h
    75.  
    76. Error_file_metka:               ;Вывод сообщения об ошибке.
    77.  
    78. mov ah,9                    ;Загружаем в регистр ah число 9 (указываем функцию).
    79. mov dx,offset Error_file            ;Указываем, что за фразу мы будем выводить.
    80. int 21h                     ;Выводим фразу.
    81.  
    82. mov ah,4Ch                  ;Используем для выхода из программы.
    83. int 21h
    84.  
    85. Find_first proc                                 ;Подпрограмма поиска первого файла.
    86. mov ah,4Eh                  ;Ищем первый файл по маске (функция 4Eh).
    87. xor cx,cx                   ;Атрибуты обычные. Смотрим, что в CX.
    88. mov dx,offset File_name             ;Адрес маски в DS:DX
    89. int 21h                     ;В DTA заносится имя найденного файла.
    90. ret
    91. Find_first endp
    92.                                                 ;Подпрограмма поиска следующего файла.
    93. Find_next proc
    94. xor dx,dx                   ;DS:DX указывают на DTA (DX=0).
    95. xor cx,cx                                   ;CX=0.
    96. mov ah,4Fh                                  ;4Fh - поиск следующего файла.
    97. int 21h                                         ;В DTA заносится имя найденного файла.
    98. ret
    99. Find_next endp
    100.          
    101. File_name db '*.txt',0              ;Маска файла.
    102.  
    103. Handle dw 0FFFFh                ;Определяем переменную Handle, которую используем для
    104.                         ;хранения номера файла. По умолчанию она равна 0FFFFh.
    105.  
    106. one db '1'                  ;Определяем переменную one, содержащую символ "1",
    107.                         ;которую мы будем приписывать в конец файла.
    108. Vse_ok db 'Файлы найдены и обновлены. Всем спасибо.$';Успешное сообщение и сообщение об ошибке (ниже).
    109.  
    110. Error_file db 'Файлы не найдены. Поместите файлы *.txt в каталог с программой.$'
    111.  
    112. Finish equ $                                    ;Метка конца программы.
    113.  
    114. CSEG ends
    115. end begin
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Rockphorr
    результаты не всегда эквивалентны, конкретно тут без разницы, а вообще нужно семь раз подумать и один раз отрезать)
     
  11. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    _mm_
    домой с работы приду попробую скомпилить - на работе под рукой масма нет
     
  12. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    Great
    конкретно тут - это где ???

    в фасме разницы нет, а в масме между двумя этими кусками разница принципиальная
    и в фасме разницы между lea и mov если смотреть на первый фрагмент не видно

    именно про это я и говорю
     
  13. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Спасибо! Вот на всякий случай созданный объектный файл: http://asm.ms/test.obj
     
  14. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    А жаль. Бился, бился, но ничего не выходит.
     
  15. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    _mm_
    я до компа дома не добрался - теща приехала - полный дом народу

    если есть объектник то почему не попробовать скормить его линкеру вручную ???
     
  16. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Так вручную и не кормится. И ничего не пишет.
     
  17. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    я скомпилил и отлинковал ваш исходник согласно #9
    ком файл получился работает насколько может - в ней дефектный алгоритм - если текстовый файл один - он зацикливается на запись единиц в него - так как dta в случае ошибки не очищается

    другими словами после find_next должен быть jnc вместо jc


    упд: линковал с ключем /tiny

    если нужно могу выложить обрезок от пакета masm который будет собирать ком файл

    расскажите как вы компилите и линкуете поподробнее
     
  18. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Насчёт алгоритма - не беда, я же набросал примерный код, ещё не отлаживал по понятным причинам.
    Компилил так: ml lalala.asm /AT Линковщиком просто собирал без аргументов. Попробую завтра с /tiny.
    Интересно, почему же он не собрался сам? Может модель в самом коде прописать?
     
  19. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.552
    Адрес:
    Russia
    вы его откуда запускаете ??? из cmd или под farом ???
     
  20. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Всё заработало. И даже без .model tiny. И причина глупая - оказалось ESET NOD32 втихую удалял мой com-файл, принимая его за неизвестный вирус. Проблема выявилась при модификации кода (с моделью), когда информационное окно всё же всплыло.
    Чувствую себя весьма неловко. Первый класс, вторая четверть.