На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
Страницы: (3) 1 2 [3]  все  ( Перейти к последнему сообщению )  
> ASM DOS Создание TSR без PSP , Непонятки в использование INT 21H функции 55H и другие пояснения авторов на похожие темы.
    Цитата andr00 @
    Может кто посоветует, какой программой мне просмотреть память ?
    Есть peek.exe - резидент для просмотра памяти.
    Ну или да, TD...
    Прикреплённый файлПрикреплённый файлPEEK.7z (5,21 Кбайт, скачиваний: 105)
      Jin X, вообще моя задача полностью избавится от PSP. Т.к. есть довольно много маленьких TSR (даже всего 4 байта (ссылки на буфер в области памяти >1Мб)).
      Ваше предложение оставить всего 30H PSP не всегда проходит корректно. Некоторые конфигурации DOS, после установки TSR, портят исходные файлы (даже исходники *.asm).
      Я обнаружил, что после установки TSR (с остатком PSP в 30H байт) и после этого немедленного включения просмотра (по F3), практически все файлы с именем запускного
      файла портятся. Я не использую в TSR (пока) файловые операции. Все что я выяснил, это оставить остаток PSP = 40H, вроде не глючит. Но для большей уверенности,
      (если не использовать командную строку) это 80H.

      Добавлено
      Akina, TD при запуск программы исходника (в окне DOS под Windows-XP) работает отлично. Но если ей указать сегмент:смещение этой TSR (полученной с помощью MEM.EXE)- какой то мусор.
        Цитата andr00 @
        Некоторые конфигурации DOS, после установки TSR, портят исходные файлы (даже исходники *.asm).
        Это как?! :blink:
        Про 30h я же написал, что "по крайней мере,если не использовать int 21h внутри обработчика".

        Вообще, я бы следовал следующему алгоритму:

        0. Расположить обработчики в программе друг за другом, а первый из них выровнять по границе параграфа (16 байт).
        1. Удалить environment.
        2. Попытаться выделить блок памяти нужного размера (по размеру обработчиков).

        3а. Если блок выделился (это может бы только что освободившийся блок или дырка, оставленная кем-то ранее), то:
        3а.1. Подменяем служебную информацию (MCB) этого блока (чтобы при завершении программы он не освободился автоматически).
        3а.2. Копируем туда наш обработчик.
        3а.3. Перехватываем прерывания.
        3а.4. Выходим обычным образом (int 20h).

        3б. Если блок НЕ выделился, то:
        3б.1. Корректируем SS:SP (конец нашей программы + 100h).
        3б.2. Максимально уменьшаем размер памяти, выделенную под нашу программу (т.е. размер нашей программы + 100h под стек).
        3б.3. Выделяем новый блок такого же размера, как получился.
        3б.4. Копируем туда наш код, включая PSP.
        3б.5. Корректируем SS:SP.
        3б.6. Устанавливаем PSP на этот блок.
        3б.7. Прыгаем на то же место нашей программы, но в новом блоке.
        3б.8. Освобождаем область памяти, в которой была наша программа изначально.
        3б.9. Выделяем блок памяти нужного размера (по размеру обработчиков).
        3б.10а. Если блок выделился, goto 3а.1
        3б.10б. Если блок не выделился, значит мы где-то накосячили, можно вывести Error и помахать ручкой. Это крайне маловероятный сценарий в случае, если всё сделано правильно.
          Отъёлки...Program Segment Prefix.
            Интереса ради сделал то, что описал выше.
            Лови, andr00 ;)

            updated 31.07.2018:
            ExpandedWrap disabled
              ; TSR with no PSP (c) 2017 by Jin X
              ; Установка резидентных обработчиков прерываний, занимающих минимальное кол-во памяти (ровно столько, сколько требуется + 16 байт на MCB), без PSP !!!
               
              .MODEL Tiny
              .286
              .CODE
              .STARTUP
               
              IFDEF       ??Version           ; TASM
                LOCALS
              ENDIF
               
              ; Заполните эти константы любыми удобными вам значениями
              MuxFunc     =   0F1h            ; номер функции MUX Interrupt (Int 2Fh), должен быть в зиапазоне от 0C0h до 0FFh
              MuxAuthorID =   '7x'            ; идентификатор автора (BX)
              MuxProgID   =   'np'            ; идентификатор программы (DX)
              MuxAnswer   =   77FFh           ; ответ в AX, если программа установлена (любое значение)
               
              ProgStart   =   offset $        ; начало нашей программы
               
                      call    PreCheck        ; 3 байта - предварительная проверка (может, мы уже есть в памяти?)
                      
                      mov ah,49h          ; 2 байта
                      mov es,ds:[2Ch]     ; 4 байта
                      int 21h         ; 2 байта - освобождаем переменные окружения
               
                      ; Выделяем память для нашего резидента
                      mov ah,48h          ; 2 байта
               
                      jmp TSRInstall      ; 2-3 байта, итого 15-16 байт - прыгаем на продолжение установщика
               
              EVEN                        ; добиваем до 16 байт, если jmp оказался коротким (2-байтовым short)
               
              ;-- Начало резидентного кода обработчиков прерываний -------------------------------------------------------------------
              ; Эта метка должна быть выровнена по границе параграфа (16 байт) !!!
              TSRStart:
               
              ; Данные резидентного кода
              VentilChars DB  '|/-\'          ; таблица символов (вентилятора)
              VentilOfs   DB  -1          ; номер предыдущего символа (начиная с 0)
              VentilColor DB  1Eh         ; цвет вентилятора
               
              ; Обработчик прерывания 8 (системный таймер)
              HandlerInt8 PROC
                      push    ax
                      push    bx
                      push    ds
                      
                      push    cs
                      pop ds
                      mov al,[VentilOfs]
                      inc ax
                      and al,3
                      mov [VentilOfs],al      ; новое смещение
                      mov bx,offset VentilChars
                      xlat                ; AL = символ
                      mov ah,[VentilColor]    ; AH = цвет вентилятора
                      push    0B800h
                      pop ds
                      mov ds:[0],ax       ; выводим символ в левый верхний угол
               
                      pop ds
                      pop bx
                      pop ax
                OldInt8:
                      DB  0EAh            ; возвращаем управление прерыванию
                OldAddr8  DW  ?,?         ; адрес прерывания
              HandlerInt8 ENDP
               
              ; Обработчик прерывания 9 (клавиатура)
              HandlerInt9 PROC
                      push    ax
                      in  al,60h          ; читаем скан-код нажатой клавиши
                      cmp al,39h          ; пробел?
                      jne @@CheckEnter
               
                      ; Если пробел, меняем местами символы вентилятора (меняем направление вращения)
                      mov al,cs:[VentilChars+1]
                      xchg    al,cs:[VentilChars+3]
                      mov cs:[VentilChars+1],al
                      jmp @@exit
                  @@CheckEnter:
                      cmp al,1Ch          ; Enter?
                      jne @@exit
                      xor byte ptr cs:[VentilColor],(1Eh xor 21h) ; если Enter, меняем цвет
                  @@exit:
                      pop ax
                OldInt9:
                      DB  0EAh            ; возвращаем управление прерыванию
                OldAddr9  DW  ?,?         ; адрес прерывания
              HandlerInt9 ENDP
               
              ; Обработчик прерывания 2Fh (MUX Interrupt)
              HandlerInt2F    PROC
                      cmp ah,MuxFunc      ; проверяем номер функции
                      jne OldInt2F
                      cmp bx,MuxAuthorID      ; проверяем идентификатор автора
                      jne OldInt2F
                      cmp dx,MuxProgID        ; проверяем идентификатор программы
                      jne OldInt2F
               
                      test    al,al           ; проверяем номер подфункции
                      jne @@WrongFunc
               
                      mov ax,MuxAnswer        ; если AL=0, возвращаем наш ответ
                      iret
               
                  @@WrongFunc:
                      xor ax,ax           ; если номер подфункции неверный, возвращаем 0 в AX
                      iret
               
                OldInt2F:
                      DB  0EAh            ; возвращаем управление прерыванию
                OldAddr2F DW  ?,?         ; адрес прерывания
              HandlerInt2F    ENDP
               
              TSREnd      =   $           ; конец резидентного кода (вместе с его данными)
               
              ;-----------------------------------------------------------------------------------------------------------------------
               
              TSRSize     =   TSREnd-TSRStart     ; размер резидентного кода
              TSRParaSize =   (TSRSize+15)/16     ; размер резидентного кода в параграфах
               
              ; Структура данных о перехватываемом прерывании
              TSRItem     STRUC
                TSRIntNo  DB  ?           ; номер прерывания
                TSRAddrOfs    DW  ?           ; смещение переменной с адресом старого обработчика
                TSRHandlerOfs DW  ?           ; смещение нашего обработчика прерывания
              TSRItem     ENDS
               
              ; Таблица прерываний, адресов обработчиков и переменных для хранения старых адресов
              TSRTables   TSRItem <8,OldAddr8,HandlerInt8>, <9,OldAddr9,HandlerInt9>, <2Fh,OldAddr2F,HandlerInt2F>
              TSRIntCount =   ($-TSRTables)/(size TSRItem)
               
              ;-----------------------------------------------------------------------------------------------------------------------
               
              ; Проверка - есть ли уже наш код в памяти?
              ; Если есть, то выходим из программы (int 20h)
              PreCheck    PROC
                      mov ax,MuxFunc shl 8
                      mov bx,MuxAuthorID
                      mov dx,MuxProgID
                      int 2Fh         ; проверяем нашу программу
               
                      cmp ax,MuxAnswer
                      jne @@NotInstalled      ; прыгаем, если не установлена
               
                      mov ah,9
                      mov dx,offset MsgTSRAlrInst
                      int 21h         ; выводим сообщение
               
                      int 20h         ; выходим из программы
                  @@NotInstalled:
                      ret
              PreCheck    ENDP
               
              ; Установка резидентного кода и перехват прерываний
              TSRInstall  PROC
                      mov bx,TSRParaSize
                      int 21h         ; выделяем память нужного нам размера
                      jnc @@Allocated     ; если память выделилась, идём на перехват!
               
                      ; Переносим наш код выше, освобождая память текущего кода (чтобы выделить память по меньшему адресу для резидентного кода)
                      mov sp,offset @Startup+ProgParaSize*16+100h ; корректируем SP (оставляем под стек 256 байт)
                      
                      mov ah,4Ah
                      push    cs
                      pop es
                      mov bx,ProgParaSize+20h ; кол-во параграфов, включая PSP и стек
                      int 21h         ; сжимаем размер выделенной нашей программе области памяти
                      jc  @@Error         ; ошибка... что за бред?
               
                      mov ah,48h
                      int 21h         ; выделяем ещё один такой же блок
                      jc  @@Error         ; ошибка... неужели у нас всё так плохо с памятью?
               
                      cld             ; устанавливаем прямой порядок обработки строк
                      mov es,ax           ; ES = адрес нового блока
                      xor si,si
                      xor di,di
                      mov cx,(ProgEnd-@Startup+100h+1)/2
                      rep movsw           ; копируем наш код по новому адресу
               
                      push    es
                      pop ss          ; меняем SS на новый
               
                      push    es
                      push    offset @@Continue
                      retf                ; прыгаем по новому адресу :)
                  @@Continue:
                      mov ah,50h
                      mov bx,es
                      int 21h         ; устанавливаем новый PSP
               
                      mov ah,49h
                      push    ds
                      pop es          ; ES = старый PSP
                      int 21h         ; освобождаем память, которую мы занимали ранее
               
                      push    cs
                      pop ds          ; DS = наш новый (текущий) PSP
               
                      mov ah,48h
                      mov bx,TSRParaSize
                      int 21h         ; ещё раз пытаемся выделить память нужного нам размера
                      jc  @@Error         ; ошибка... что за бред?
               
                  @@Allocated:
                      ; Переносим наш код в выделенную память
                      sub ax,(TSRStart-@Startup+100h)/16
                      mov es,ax           ; ES = сегмент резидентного кода
                      mov word ptr es:[TSRStart-0Fh],40h  ; помечаем в MCB выделенный участок как принадлежащий сегменту 40h (этот сегмент принадлежит BIOS и никогда не будет освобождён)
               
                      mov si,offset TSRStart
                      mov di,si
                      mov cx,(TSRSize+1)/2
                      rep movsw           ; копируем наш резидентный код в выделенную память
               
               
                      ; Перехват прерываний
                      mov si,offset TSRTables
              IF  TSRIntCount gt 1
                      mov cx,TSRIntCount
                  @@SetTSRLoop:
              ENDIF
                      lodsb               ; читаем номер прерывания
                      push    ax
                      push    es
                      mov ah,35h
                      int 21h         ; получаем старый обработчик в ES:BX
                      mov dx,es           ; сохраняем сегмент в DX
                      pop es
                      lodsw
                      xchg    di,ax           ; DI = адрес переменной
                      xchg    ax,bx
                      stosw               ; записываем в неё смещение
                      xchg    ax,dx
                      stosw               ; и сегмент
               
                      lodsw
                      xchg    dx,ax           ; DX = адрес нашего обработчика
                      pop ax          ; восстанавливаем номер прерывания
                      mov ah,25h
                      push    ds
                      push    es
                      pop ds          ; DS = ES = сегмент резидентного кода
                      int 21h         ; устанавливаем наш обработчик
                      pop ds
               
              IF  TSRIntCount gt 1
                      loop    @@SetTSRLoop        ; повторяем цикл
              ENDIF
                      mov dx,offset MsgTSRInstOk  ; сообщение, что всё ok
                  @@Message:
                      mov ah,9
                      int 21h         ; выводим сообщение
               
                      int     20h         ; выходим из программы (int 27h нам тут не нужен, т.к. резидентный код находится в автономном блоке памяти, уже не связанном с текущей программой) :)
               
                  @@Error:
                      mov dx,offset MsgTSRInstErr ; сообщение об ошибке
                      jmp @@Message
               
              TSRInstall  ENDP
               
              ;-----------------------------------------------------------------------------------------------------------------------
               
              ; Сообщения
              MsgTSRInstOk    DB  'TSR is successfully installed !!!',13,10,'$'
              MsgTSRAlrInst   DB  'TSR is already installed !!!',13,10,'$'
              MsgTSRInstErr   DB  'TSR installation is failed :(',13,10,'$'
               
              ProgEnd     =   $           ; конец всей нашей программы
              ProgParaSize    =   (ProgEnd-@Startup+15)/16    ; размер всей нашей программы (без PSP) в параграфах
               
              END

            Прикреплённый файлПрикреплённый файлTsrNoPsp.zip (3,76 Кбайт, скачиваний: 71)

            Старый: Прикреплённый файлПрикреплённый файлTsrNoPsp.zip (3,78 Кбайт, скачиваний: 88)
            Сообщение отредактировано: Jin X -
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:
            Страницы: (3) 1 2 [3]  все


            Рейтинг@Mail.ru
            [ Script execution time: 0,0436 ]   [ 19 queries used ]   [ Generated: 16.04.24, 05:41 GMT ]