Вывод времени. Защита резидента от повторной загрузки - Assembler

Узнай цену своей работы

Формулировка задачи:

всем привет! снова имеется программа вывода времени, увы написанная не мной.. правда на сей раз занимает чуть больше ресурсов памяти..
RGB equ 1Fh         
VID EQU 0B800h
ROW EQU 1             
COL EQU 73          
SEP EQU 3Ah      
 
TIME SEGMENT
ORG 100h
ASSUME CS:TIME,DS:TIME
 
START:
JMP INIT
 
MOVEIT:            
PUSH DS
PUSH ES
PUSH SI
PUSH DI
 
MOV SI,CS
MOV DS,SI
MOV ES,SI
MOV SI,(OFFSET NewInt1C) + 2 + 5
XOR DI,DI
CLD
MOV CX,attente-(OFFSET NewInt1C)
REP MOVSB
 
MOV AX,251Ch
XOR DX,DX
INT 21h
 
POP DI
POP SI
POP ES
POP DS
 
NewInt1C PROC 
DEC BYTE PTR CS:attente
JZ MOVEIT
 
PUSH AX
PUSH BX
PUSH CX
PUSH DX 
PUSH ES
PUSH DI
 
CLD
 
MOV AX,VID
MOV ES,AX
MOV DI,(ROW-1)*160+(COL-1)*2 
 
MOV AH,2
INT 1Ah
 
MOV BX,CX   
 
MOV AL,BH   
MOV AH,RGB
MOV CL,4    
SHR AL,CL   
OR AL,30h
STOSW
MOV AL,BH
AND AL,0Fh
OR AL,30h
STOSW
 
MOV AL,SEP
STOSW
 
MOV AL,BL   
SHR AL,CL
OR AL,30h
STOSW 
MOV AL,BL
AND AL,0Fh
OR AL,30h
STOSW
 
MOV AL,SEP
STOSW
 
MOV AL,DH
SHR AL,CL
OR AL,30h
STOSW
MOV AL,DH
AND AL,0Fh
OR AL,30h
STOSW
 
POP DI
POP ES
POP DX
POP CX
POP BX
POP AX
 
         DB 0EAh 
Int1COfs DW ?
Int1CSeg DW ?
 
NewInt1C ENDP
 
attente DB 5
 
INIT:              
CLI
 
MOV AX,351Ch
INT 21h
MOV Int1COfs,BX
MOV Int1CSeg,ES
 
MOV AH,9
MOV DX,OFFSET copyright
INT 21h
 
MOV AX,251Ch
MOV DX,OFFSET NewInt1C
INT 21h
 
PUSH CS
POP ES
MOV ES,WORD PTR ES:2Ch
 
MOV AH,49h
INT 21h      
 
STI          
 
MOV AX,3100h
MOV DX,6     
INT 21h
 
copyright db 13,10,'Time! 3.4 - Coded By Sam In 1994 - 
          db The Flamoots Production - 96 Bytes In Memory!$'
TIME ENDS
END START
возникает вопрос по копированию резидентной части..
MOV SI,(OFFSET NewInt1C) + 2 + 5
XOR DI,DI
CLD
MOV CX,attente-(OFFSET NewInt1C)
REP MOVSB
резидентная часть вроде полностью не будет копироваться.. т.к. пропускаются команды сравнения 2+5=7 байт..
DEC BYTE PTR CS:attente     - 5 байт  
JZ MOVEIT     - 2 байта
почему тогда указана полная длина резидентной части для копирования, т.е. не отнимаются те самые 7 байт? ведь в этом случае скопируются в дополнение к резидентной части еще семь байтов расположенных за ней, а там уже по-сути мусор инициализационной части..

Решение задачи: «Вывод времени. Защита резидента от повторной загрузки»

textual
Листинг программы
.MODEL Tiny
.286
.CODE
.STARTUP
 
LOCALS
 
IntNo           =       08h             ; номер прерывания
HandlerOfs      =       30h;40h;80h     ; смещение, по которому будет копироваться обработчик (с отступом в 2-3 байта на инструкцию jmp), должно быть кратно 10h
HandlerShift    =       HandlerOfs-100h ; разница нового и исходного смещения обработчика
 
                jmp     InstallTSR
 
;-----------------------------------------------------------------------------------------------------------------------
 
HandlerStart:                           ; начало обработчика прерывания (между этой меткой и HandlerEntry могут храниться данные)
ORG     $-1
VentilOfs       DB      ?
VentilChars     DB      '\|/-'
HandlerEntry:                           ; точка входа обработчика прерывания
                push    ax
                push    bx
                push    ds
                
                push    cs
                pop     ds
                mov     al,VentilOfs
                inc     ax
                and     al,3
                mov     VentilOfs,al
                lea     bx,VentilChars
                xlat
                mov     ah,1Eh
                push    0B800h
                pop     ds
                mov     ds:[0],ax
 
                pop     ds
                pop     bx
                pop     ax
 
RealInt         DB      0EAh            ; возвращаем управление прерыванию (jmp far)
RealAddr        DW      ?,?
HandlerEnd:
ORG             $-4
 
;-----------------------------------------------------------------------------------------------------------------------
 
InstallTSR:
                mov     ah,9
                lea     dx,msgOk
                int     21h
 
                ; копируем наш код со смещением HandlerShift
                mov     si,offset HandlerStart
                mov     di,offset HandlerStart+HandlerShift
                mov     cx,(HandlerEnd-HandlerStart+1)/2
                rep movsw
 
                ; Освобождаем Environment
                mov     ah,49h
                mov     es,ds:[2Ch]
                int     21h
 
                ; Сдвигаем сегментный адрес
                mov     ax,cs
                add     ax,HandlerShift/16
                mov     ds,ax
 
                ; Получаем старый вектор прерывания
                mov     ax,3500h + IntNo
                int     21h
                mov     RealAddr[0],bx
                mov     RealAddr[2],es
 
                ; Перехватываем прерывание
                mov     ah,25h
                mov     dx,offset HandlerEntry
                int     21h
 
                ; Остаёмся резидентными
                mov     dx,offset HandlerEnd+HandlerShift
                int     27h
 
msgOk           DB      'TSR is installed!',13,10,'$'
 
END

Объяснение кода листинга программы

Вот что получилось:

  1. В коде есть следующие переменные:
    • IntNo — номер прерывания, равный 08h.
    • HandlerOfs — смещение, по которому будет копироваться обработчик, равное 30h, 40h или 80h (должно быть кратно 10h).
    • HandlerShift — разница нового и исходного смещения обработчика.
    • VentilOfs — DB-переменная, содержащая смещение вентиля (находится между метками HandlerStart и HandlerEntry).
    • VentilChars — DB-переменная, содержащая строку '|/-', которая будет выводиться на экран при каждом прерывании.
    • RealInt — DB-переменная, содержащая возвращаемое значение прерывания, равное 0EAh.
    • RealAddr — DW-переменная, содержащая адрес, на который будет возвращено управление при прерывании.
  2. Код выполняет следующие действия:
    • Выводит на экран сообщение «TSR is installed!», затем символы «|/-» (символы вентиля) и символ доллара.
    • Устанавливает обработчик прерывания на смещение HandlerStart с использованием регистра HandlerShift.
    • Освобождает Environment.
    • Сдвигает сегментный адрес на величину HandlerShift.
    • Получает старый вектор прерывания.
    • Перехватывает прерывание, проставляя в векторе прерывания адрес обработчика HandlerEntry.
    • Остаётся резидентными, сохраняя в памяти адрес HandlerEnd с использованием регистра HandlerShift.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 3.571 из 5
Похожие ответы