Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Советник
Рейтинг: 10854
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Советник
Рейтинг: 4002
∙ повысить рейтинг »
Куликов Роман Евгеньевич
Статус: 1-й класс
Рейтинг: 0
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1564
Дата выхода:22.09.2015, 14:21
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:13 / 5
Вопросов / ответов:1 / 1

Консультация # 188037: Разбираю код программы из учебника, программа формирует log-файл(report.txt) действий пользователя. В самом log-файле будут записи, такого формата: "Launch file ---> C:\AFDPRO\RESID19.COM". Все понятно, кроме одного: откуда в регистре DX в строке Move_string proc ... mov si,dx ... Move_strin...


Консультация # 188037:

Разбираю код программы из учебника, программа формирует log-файл(report.txt) действий пользователя. В самом log-файле будут записи, такого формата: "Launch file ---> C:\AFDPRO\RESID19.COM".
Все понятно, кроме одного: откуда в регистре DX в строке

Move_string proc
...
mov si,dx
...
Move_string endp

берется смещение имени файла "C:\AFDPRO\RESID19.COM"

Вот сам код:

Код :
;            RESID19.ASM - программа к Главе № 19
 
; (С) Авторские права на файлы-приложения принадлежат автору книги
; "Ассемблер? Это просто! Учимся программировать под MS-DOS"
; Автор: Калашников Олег Александрович (e-mail: Assembler@Kalashnikoff.ru)
;    http://www.Kalashnikoff.ru
 
; --- Ассемблирование (получение *.com файла) ---
;При использовании MASM 6.11 - 6.13:
;ML.EXE resid19.asm /AT
 
;При использовании TASM:
;TASM.EXE resid19.asm
;TLINK.EXE resid19.obj /t/x
 
 
;   === Начало программы: ===
286
CSEG segment
assume cs:CSEG, ds:CSEG, ss:CSEG, es:CSEG
org 100h
 
Begin:
       jmp Init     ;На метку инициализации 
 
; === Обработчик 21h-ого прерывания ===
Int_21h_proc proc
     cmp ax,9889h
     jne Next_step
 
     xchg ah,al
     iret
 
Next_step:
     pusha      ;Сохраним регистры...
     push ds
     push es
 
     mov bx,ds      ;BX=DS
 
     push cs        ;Настроим сегментные регистры
     push cs
     pop es
     pop ds
     
     ;cmp ax, 0998h ; MY CODE!!! - wrong way!
     ;je Start_f     
 
     cmp ax,4B00h   ;Это запуск файла на выполнение?
     je Start_f
 
     cmp ah,39h     ;Это создание каталога?
     je Create_dir
 
     cmp ah,3Ah     ;Это удаление каталога?
     je Delete_dir
 
     cmp ah,3Bh     ;Это смена каталога?
     je Change_dir
 
     cmp ah,3Ch     ;Это создание файла?
     je Create_file
 
     cmp ax,3D02h   ;Это открытие файла для чтения/записи?
     je Open_fl
 
     cmp ah,41h     ;Это удаление файла?
     je Delete_file
 
     jmp short Go_21h   ;Если другое, то передадим управление 21h-ому... 
 
Start_f:
     mov si,offset Start_filemess ;Строка для записи в наш log-файл.
     call Move_string   ;Готовим строку и записываем ее в файл...
     jmp short Go_21h   ;Передадим управление 21h-ому прерыванию...
 
Create_dir:
     mov si,offset Create_dirmess
     call Move_string
     jmp short Go_21h
 
Delete_dir:
     mov si,offset Delete_dirmess
     call Move_string
     jmp short Go_21h
 
Change_dir:
     mov si,offset Change_dirmess
     call Move_string
     jmp short Go_21h
 
Create_file:
     mov si,offset Create_filemess
     call Move_string
     jmp short Go_21h
 
Open_fl:
     mov si,offset Open_filemess
     call Move_string
     jmp short Go_21h
 
Delete_file:
     mov si,offset Delete_filemess
     call Move_string
 
 
Go_21h:
     pop es     ;Восстановим регистры...
     pop ds
     popa
 
  jmp dword ptr cs:[0FCh] ;Передаем управление прежнему 21h-ому
Int_21h_proc endp
 
;=== Переносим строку и пишем информацию в файл ===
Move_string proc
    mov di,2    ;DS:SI указывают на строку
        ;ES:DI - на место в памяти, где будет формироваться строка...
    lodsw   ;Получим длину строки (первый байт строки)
    mov cx,ax   ;Длину строки в CX
    rep movsb   ;Переместили строку по адресу ES:DI (Текущий сегмент:0002h)
 
    push ds
    mov ds,bx   ;DS указывает на сегмент, где находится имя файла
    mov si,dx   ;SI - на смещение
 
Next_char:
    lodsb   ;Получаем очередной символ
    or al,al    ;Это конец строки с именем файла? Проверка на 0...
    jz Zero_found
    stosb   ;Если еще не конец - заносим его в нашу формирующуюся строку
    jmp short Next_char ;Следующий символ...
 
Zero_found:
    pop ds  ;Имя файла перенесли! Восстановим DS.
 
    mov ax,0A0Dh ;Добавим возврат каретки/перевод строки.
    stosw
 
    dec di
    dec di
    mov word ptr cs:[0],di ;Занесем по 0-ому смещению длину готовой строки
 
    call Save_file  ;Запишем готовую строку в наш log-файл...
 
    ret
Move_string endp
 
 
;=== Пишем в файл ===
Save_file proc
     call Check_file    ;Проверим, существует ли наш log-файл или нет...
 
     mov al,02h     ;Открываем файл для чтения/записи
     call Open_file
 
     mov ax,4202h   ;Устанавливаем указатель на конец файла
     xor cx,cx
     xor dx,dx
     int 3
 
     mov ah,40h     ;Функция записи в файл
     mov cx,cs:[0]  ;Количество записываемых байт
     mov dx,2       ;Откуда будем писать (DS:DX)
     int 3
 
     call Close_file    ;Закрываем файл...
 
     ret
Save_file endp
 
;=== Проверяем: существует ли нужный файл ===
Check_file proc
     xor al,al      ;Пробуем открыть наш log-файл
     call Open_file
     jnc File_exists    ;Если файл существует, то на метку File_exists
 
; === Атрибуты файла ===
;00001 - только чтение
;00010 - спрятанный
;00100 - системный
;01000 - метка тома
;010000 - подкаталог
;100000 - архивный
     mov ah,3Ch     ;Если файл не существует, то создадим его.
     mov cx,100010b ;Атрибут: архивный, спрятанный
     mov dx,offset File_name ;DS:DX указывают на имя файла
     int 3
     jc Error_create    ;Ошибка?.. 
     mov Handle,ax  ;Если успешно создали, то запомним номер файла
 
File_exists:
     call Close_file    ;Закрываем файл...
 
Error_create:
     ret
 
File_name db 'C:\report.txt',0  ;Наш log-файл
Check_file endp
 
;=== Открытие файла ===
Open_file proc
     mov dx,offset File_name
     mov ah,3Dh
     int 3
     jc Error_open
 
     mov bx,ax
     mov Handle,ax
 
Error_open:
     ret
Handle dw 0FFFFh
Open_file endp
 
;=== Закрытие файла ===
Close_file proc
     pusha
     pushf
     cmp Handle,0FFFFh  ;Нечего закрывать?.. 
     je No_close
 
     mov ah,3Eh
     mov bx,Handle
     int 3
     mov Handle,0FFFFh  ;Закрываем и отмечаем, что нет открытых файлов...
 
No_close:
     popa
     popf
     ret
Close_file endp
 
;--- Сообщения резидента ---
Start_filemess dw Start_filemessl
               db 'Launch file      ---> '        ;db 'Запуск файла      ---> '
Start_filemessl equ $-Start_filemess-2
 
Create_dirmess dw Create_dirmessl
               db 'Create folder ---> '          ;db 'Создание каталога ---> '
Create_dirmessl equ $-Create_dirmess-2
 
Delete_dirmess dw Delete_dirmessl
               db 'Delete folder ---> '          ;db 'Удаление каталога ---> '
Delete_dirmessl equ $-Delete_dirmess-2
 
Change_dirmess dw Change_dirmessl
               db 'Change folder to ---> '     ;db 'Смена каталога на ---> '
Change_dirmessl equ $-Change_dirmess-2
 
Create_filemess dw Create_filemessl
                db 'Create file    ---> '            ;db 'Создание файла    ---> '
Create_filemessl equ $-Create_filemess-2
 
Open_filemess dw Open_filemessl
              db 'Open file for read/write    ---> '       ;db 'Открытие файла для чтения/записи ---> '
Open_filemessl equ $-Open_filemess-2
 
Delete_filemess dw Delete_filemessl
                db 'Deleta file    ---> '              ;db 'Удаление файла    ---> '
Delete_filemessl equ $-Delete_filemess-2
 
 
 
 
;   === Инициализация (подготовка и настройка резидента) ===
Init:
       mov ax,9889h ;Проверим, в памяти ли мы уже или еще нет
       int 21h
       cmp ax,8998h
       jne Set_resident
 
       mov ah,9     ;Если в памяти, то выведем соответствующее сообщение
       mov dx,offset In_memory
       int 21h
 
       ret      ;...И вернемся в DOS
 
Set_resident:       ;Если нас в памяти нет, то установим резидент
; 21h-ое...
       mov ax,3521h
       int 21h      ;Получим и сохраним адрес (вектор) 21h прерывания
       mov word ptr cs:[0FCh],bx
       mov word ptr cs:[0FEh],es
 
       mov ax,es    ;Установим старый вектор 21h-прерывания на 3...
       push 0       ;(вырубим отладчик)
       pop es
       mov es:[3*4],bx
       mov es:[3*4+2],ax
 
       mov ax,2521h
       mov dx,offset Int_21h_proc
       int 3        ;"Повесим" нашу процедуру на 21h прерывание
 
       call Check_file  ;А есть ли наш log-файл?
 
       mov ah,9
       mov dx,offset Mess_hello
       int 21h
 
       mov dx,offset Init
       int 27h      ;Оставим программу резидентной в памяти.
 
In_memory db 'Программа уже загружена в память!!!',0Ah,0Dh,0Ah
 
Mess_hello db 'Резидент к книге "Ассемблер? Это просто! Учимся программировать", Глава № 19.',0Ah,0Dh,0Ah
           db 'Автор: Калашников Олег Александрович (Assembler@Kalashnikoff.ru),',0Ah,0Dh
           db 'http://www.Kalashnikoff.ru, Россия, Москва, 2000 год.',0Ah,0Dh,'$'
 
CSEG ends
end Begin

Дата отправки: 19.09.2015, 13:44
Вопрос задал: Посетитель - 398958 (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Коцюрбенко Алексей aka Жерар (Советник):

Здравствуйте, Посетитель - 398958!

Для тех функций прерывания 21h, которые используют имя файла (39h, 3Ah, 3Bh, 3Ch, 3Dh, 41h, 43h, 4Bh, 4Eh, 56h и некоторые другие) адрес строки с именем файла передаётся через DS:DX. В данном обработчике DS сразу сохраняется в BX, а DX не изменяется, после чего для всех перехватываемых функций вызывается процедура Move_string, которая использует пару регистров BX и DX для получения сегмента и смещения строки с именем файла. Для функции 4Bh это будет имя запускаемой программы, для функций 39h, 3Ah, 3Bh - имя каталога, для остальных - имя файла.

Консультировал: Коцюрбенко Алексей aka Жерар (Советник)
Дата отправки: 20.09.2015, 15:28
Рейтинг ответа:

НЕ одобряю +1 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!


© 2001-2015, Портал RFPRO.RU, Россия
Авторское право: ООО "Мастер-Эксперт Про"
Калашников О.А. | Гладенюк А.Г.
Версия системы: 2015.6.38 от 22.09.2015

В избранное