Всем добрый день. Имеется небольшая программка под DOS, ищущая файлы в текущем каталоге. Функция 4Eh пишет имя файла в DTA. Перед этим надо сохранять PSP (я его кидаю в конец файла в памяти, потом возвращаю). DTA находится по адресу 80h, а имя найденного файла, как я понимаю - в 9Eh. Проблема в строке 40. При вызове функции открытия файла с установкой dx на это самое имя mov dx,9Eh - com-файл отказывается создаваться! Причём нет никаких сообщений об ошибках - говорит, что всё нормально (obj-файл создаётся). Если же просто поменять mov dx,9Eh на mov dx,80h - всё создаётся, но мне это, понятно, не нужно. В чём проблема? Мне кажется, я что-то недопонимаю в PSP. Подскажите, пожалуйста. Вот сам текст: Код (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 si,0 ;Сохраняем PSP. mov di,offset Finish ;Куда перемещать. mov cx,100h ;Перемещаем 100h байт. rep movsb call Find_first ;Ищем первый файл. jc Error_file_metka ;Нет txt-файлов - на выход. goto_cikl: ;Начало цикла. mov ax,3D02h ;Загружаем в регистр ah число 3Dh (функция открытия ;файла с записью), а в al число 02h (пишем в конец). ;Можно было записать и так - mov ah,3Dh ;mov al,02h ;mov dx,80h mov dx,9Eh ;Указываем адрес файла в DTA (по умолчанию он 80h, ;+1Eh - имя файла. int 21h ;Выполняем функцию. mov Handle,ax ;При открытии файлу будет присвоен номер, его и ;сохраняем для дальнейших действий, mov bx,ax ;а заодно и сохраняем его в bx. mov ax,4202h ;Используем функцию установки указателя. ;al=02h - устанавливаем в конец. mov cx,0 ;Нам надо записать прямо в конец файла, поэтому mov dx,0 ;обнулим cx и dx (иначе будет писать далее на ;значение (CX * 65536) + DX int 21h ;Выполняем функцию. mov ah,40h ;Используем функцию записи в файл. mov dx,offset one ;В dx занесём адрес смещения к записываемому ;тексту. mov cx,1 ;Число записываемых байт - 1. int 21h ;Выполняем функцию. mov ah,3Eh ;Используем функцию закрытия файла. mov bx,Handle ;Для закрытия обязательно "вспоминаем" его номер, ;номер у нас был сохранён в Handle. int 21h ;Выполняем функцию. call Find_next ;Ищем следующий файл. jc goto_cikl ;Нашли ещё один файл; прыгаем на метку. mov si,offset Finish ;Восстанавливаем PSP. mov di,0 mov cx,100h ;Перемещаем 100h байт. rep movsb mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset Vse_ok ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. mov ah,4Ch ;Используем для выхода из программы. int 21h Error_file_metka: ;Вывод сообщения об ошибке. mov si,offset Finish ;Восстанавливаем PSP. mov di,0 mov cx,100h ;Перемещаем 100h байт. rep movsb mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset Error_file ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. mov ah,4Ch ;Используем для выхода из программы. int 21h Find_first proc ;Подпрограмма поиска первого файла. mov ah,4Eh ;Ищем первый файл по маске (функция 4Eh). xor cx,cx ;Атрибуты обычные. Смотрим, что в CX. mov dx,offset File_name ;Адрес маски в DS:DX int 21h ;В DTA заносится имя найденного файла. ret Find_first endp ;Подпрограмма поиска следующего файла. Find_next proc xor dx,dx ;DS:DX указывают на DTA (DX=0). xor cx,cx ;CX=0. mov ah,4Fh ;4Fh - поиск следующего файла. int 21h ;В DTA заносится имя найденного файла. ret Find_next endp File_name db '*.txt',0 ;Маска файла. Handle dw 0FFFFh ;Определяем переменную Handle, которую используем для ;хранения номера файла. По умолчанию она равна 0FFFFh. one db '1' ;Определяем переменную one, содержащую символ "1", ;которую мы будем приписывать в конец файла. Vse_ok db 'Файл найден и обновлён. Всем спасибо.$';Успешное сообщение и сообщение об ошибке (ниже). Error_file db 'Файлы не найдены. Поместите файл *.txt в каталог с программой.$' Finish equ $ ;Метка конца программы. CSEG ends end begin
не проще ли сделать так Код (Text): mov ah, 26 mov dx, Finish int 33 и получать информацию о файле в не в psp, а по метке Finish
Код (Text): mov ah,1Ah mov dx,offset Finish int 21h К своей программе я это добавлял в самом начале (но не помогло). Но я правильно понимаю, что по адресу 80h располагается изначально командная строка? А тогда где она располагается при переустановке DTA? Там же или на Finish + 80h? Спрашиваю для того, чтобы программа не зависла. Имеет ли смысл переброс PSP с DTA в принципе? Как бы то ни было, всё равно имя файла, необходимое для функции открытия, располагается по адресу: Код (Text): mov ax,3D02h ;Загружаем в регистр ah число 3Dh (функция открытия ;файла с записью), а в al число 02h (пишем в конец). ;Можно было записать и так - mov ah,3Dh ;mov al,02h mov dx,offset Finish add dx,1Eh ;Указываем адрес файла в DTA (по умолчанию он 80h, ;+1Eh - имя файла. int 21h ;Выполняем функцию. В этом вся и беда. В этом виде при ml tratata.asm /AT программа сообщений об ошибок не выдаёт, но создаёт только obj-файл. Если же изменить add dx,1Eh хотя бы на add dx,1Dh - всё работает. В чём прикол? Почему линковщик не создаёт com-файл из-за точного указания смещения в dx?
_mm_ при запуске она располагается по адресу psp+80h потом, после переустановки с помощью 1ah сразу по адресу в вашем случае с Finish
этот код вызывает у меня недоверие - я немогу утверждать глядя на ваш код что dta начинается с finish
В отладчике я вижу имя первого найденного файла по адресу Finish+1Eh. Проблема в том, что как только указываешь это смещение в dx, com-файл не создаётся. А укажешь +1Dh или 1Fh - создаётся. Но мне-то нужно +1Eh.
Вот последняя версия кода под masm. Код (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 ah,1Ah mov dx,offset Finish int 21h call Find_first ;Ищем первый файл. jc Error_file_metka ;Нет txt-файлов - на выход. goto_cikl: ;Начало цикла. mov ax,3D02h ;Загружаем в регистр ah число 3Dh (функция открытия ;файла с записью), а в al число 02h (пишем в конец). ;Можно было записать и так - mov ah,3Dh ;mov al,02h mov dx,offset Finish add dx,1Eh ;Указываем адрес файла в DTA (по умолчанию он 80h, ;+1Eh - имя файла. int 21h ;Выполняем функцию. mov Handle,ax ;При открытии файлу будет присвоен номер, его и ;сохраняем для дальнейших действий, mov bx,ax ;а заодно и сохраняем его в bx. mov ax,4202h ;Используем функцию установки указателя. ;al=02h - устанавливаем в конец. mov cx,0 ;Нам надо записать прямо в конец файла, поэтому mov dx,0 ;обнулим cx и dx (иначе будет писать далее на ;значение (CX * 65536) + DX int 21h ;Выполняем функцию. mov ah,40h ;Используем функцию записи в файл. mov dx,offset one ;В dx занесём адрес смещения к записываемому ;тексту. mov cx,1 ;Число записываемых байт - 1. int 21h ;Выполняем функцию. mov ah,3Eh ;Используем функцию закрытия файла. mov bx,Handle ;Для закрытия обязательно "вспоминаем" его номер, ;номер у нас был сохранён в Handle. int 21h ;Выполняем функцию. call Find_next ;Ищем следующий файл. jc goto_cikl ;Нашли ещё один файл; прыгаем на метку. mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset Vse_ok ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. mov ah,4Ch ;Используем для выхода из программы. int 21h Error_file_metka: ;Вывод сообщения об ошибке. mov ah,9 ;Загружаем в регистр ah число 9 (указываем функцию). mov dx,offset Error_file ;Указываем, что за фразу мы будем выводить. int 21h ;Выводим фразу. mov ah,4Ch ;Используем для выхода из программы. int 21h Find_first proc ;Подпрограмма поиска первого файла. mov ah,4Eh ;Ищем первый файл по маске (функция 4Eh). xor cx,cx ;Атрибуты обычные. Смотрим, что в CX. mov dx,offset File_name ;Адрес маски в DS:DX int 21h ;В DTA заносится имя найденного файла. ret Find_first endp ;Подпрограмма поиска следующего файла. Find_next proc xor dx,dx ;DS:DX указывают на DTA (DX=0). xor cx,cx ;CX=0. mov ah,4Fh ;4Fh - поиск следующего файла. int 21h ;В DTA заносится имя найденного файла. ret Find_next endp File_name db '*.txt',0 ;Маска файла. Handle dw 0FFFFh ;Определяем переменную Handle, которую используем для ;хранения номера файла. По умолчанию она равна 0FFFFh. one db '1' ;Определяем переменную one, содержащую символ "1", ;которую мы будем приписывать в конец файла. Vse_ok db 'Файлы найдены и обновлены. Всем спасибо.$';Успешное сообщение и сообщение об ошибке (ниже). Error_file db 'Файлы не найдены. Поместите файлы *.txt в каталог с программой.$' Finish equ $ ;Метка конца программы. CSEG ends end begin
Rockphorr результаты не всегда эквивалентны, конкретно тут без разницы, а вообще нужно семь раз подумать и один раз отрезать)
Great конкретно тут - это где ??? в фасме разницы нет, а в масме между двумя этими кусками разница принципиальная и в фасме разницы между lea и mov если смотреть на первый фрагмент не видно именно про это я и говорю
_mm_ я до компа дома не добрался - теща приехала - полный дом народу если есть объектник то почему не попробовать скормить его линкеру вручную ???
я скомпилил и отлинковал ваш исходник согласно #9 ком файл получился работает насколько может - в ней дефектный алгоритм - если текстовый файл один - он зацикливается на запись единиц в него - так как dta в случае ошибки не очищается другими словами после find_next должен быть jnc вместо jc упд: линковал с ключем /tiny если нужно могу выложить обрезок от пакета masm который будет собирать ком файл расскажите как вы компилите и линкуете поподробнее
Насчёт алгоритма - не беда, я же набросал примерный код, ещё не отлаживал по понятным причинам. Компилил так: ml lalala.asm /AT Линковщиком просто собирал без аргументов. Попробую завтра с /tiny. Интересно, почему же он не собрался сам? Может модель в самом коде прописать?
Всё заработало. И даже без .model tiny. И причина глупая - оказалось ESET NOD32 втихую удалял мой com-файл, принимая его за неизвестный вирус. Проблема выявилась при модификации кода (с моделью), когда информационное окно всё же всплыло. Чувствую себя весьма неловко. Первый класс, вторая четверть.