Сделать приведенную программу резидентной (FASM) - Assembler
Формулировка задачи:
Всем доброго времени суток! Нужно сделать программу резидентной. Помогите кто чем сможет.
коменты могут быть не совсем корректными
use16 ; генерация 16-битного кода org 100h ; отступаем 256 байт от начала памяти char db 65 ; аски код начального символа т.е. А kpos dw 0 ; переменная для сохранения позиции курсора (изначальная позиция курсора (т.е. левый верхний угол) jmp start install: pushf ; перед выполнением процедуры сохранение флаги push ds es ax di bx cx ; сохранение регистров в стек mov ax,0B800h ; загружаем в 16-битный регистр данных, 0b800h соответствует сегменту дисплея в тестовом режиме mov es,ax ;т.к. загрузка числа напрямую в сегментный регистр запрещена mov di,[kpos] ; смещение относительно сегмента 0b800h (т.е. позиция курсора на экране) mov cx,1 ; в сх длина сообщения т.е. количество выводимых символов mov al,[char] ; в al заносится аски код символа m1: mov ah,00001111b ;заносим цвет символа и фона в двоичном коде ; где 7 бит- мерцание символа, 6-4 - цвет фона, 3-яркость символа,2-0-цвет символа mov [es:di],ax ;заносим по адресу 0b800h:0000h атрибут символа и ASCII-код символа add di,2 ; смещаемся на 2 байта чтобы переместить курсор на след. позицию на экране inc al ; увеличиваем аски-код символа на 1, чтобы перейти к след. символу по алфавиту cmp al,91 ; сравнение аски кода полученного символа с аски кодом символа не нужного для вывода на экран (т.е. с аски кодом знака а не буквы) jnz m3 ; пока al не равно 91 то переход на метку m3 mov al,97 ; в al заносится аски код маленькую буквы а m3: cmp al,123 ; проверка совпадает ли аски код с аски кодом маленькой буквы z (т.е. последний символ английского алфавита) jnz m2 ; пока al не равно 123 то переход на метку m2 mov al,65 ; если в al аски код маленькой буквы z то заносим в al аски код буквы A m2: cmp di,320 ; проверка находится ли курсор в конце второй строки jnz m4 ; если di не равно 320 то переход на метку m4 mov di,0 ; так как di равно 320 то в di заносится 0 (чтобы перейти на начало первой строки) m4: mov [kpos],di ; сохранение позиции курсора mov [char],al ; сохранение аски кода символа loop m1 ;цикл метки m1 pop cx bx di ax es ds ; выносим из стека значения сохраненных ранее регистров popf ; востанавливаем значения флагов db 0eah ;переход на старый обработчик old08 dw ? ;переменная для старого вектор прерывания old_seg dw ? ; переменная старого сегмента прерывания start: mov ax,03h ;функция установки текстового видеорежима int 10h mov ax, 3508h ; заносим в ax функцию получения вектора прерывания (адреса подпрограммы) int 21h ; получаем вектор 09h(нажатие на клавиатуру), после выполнения прерывания в bx заносится вектор , а в es сегмент вектора mov [cs:old08], bx ; сохраняем вектор mov [cs:old_seg], es ; сохраняем сегмент вектора mov ax, 2508h ; устанавливаем свой ветор mov dx, install ;указываем адрес процедуры которая будет выполнятся вместо подпрограммы прерывания 1Ch push cs ;заносим в стек сегмент кода pop ds ; выносим из стека сегмент кода в сегмент данных int 21h ; выполняем установку ветора с новой процедурой key: xor ax, ax ; обнуляем ах int 16h ; прерывание сервиса клавиатуры после которого в al заносится аски код нажатой клавиши cmp al, 27 ; проверка нажата ли кнопка ESC jne key ; пока не нажата клавиша ESC переход на метку getkey mov ax, 2508h ; восстанавливаем старый вектор, для этого mov dx, [cs:old08] ; в dx заносится адрес подпрограммы старого (сохраненного) вектора mov ds, [cs:old_seg] ; в ds заносится старый сегмент вектора int 21h ; выполняем установку ветора со старой процедурой mov ax, 4C00h ; передача управления операционной системе int 21h
Решение задачи: «Сделать приведенную программу резидентной (FASM)»
textual
Листинг программы
use16 ;16-битный режим org 100h ;смещение програмы в памяти (com-файл) Begin: jmp InstallTSR ;Загрузка резидента в память Old08 dd ? ;резервируем место для адреса оригинального обработчика прерывания 08h cnt db 90 col db 0 New08Obrab: ;новый обработчик прерывания int08h jmp short cont dw 0fffeh ;метка присутствия резидента в памяти cont: pushf ;заносим флаги в стек, поскольку iret в конце оригинального обработчика заберет один экземпляр флагов из стека call dword [CS:Old08] ;вызов оригинального обработчика cli ;запретить прерывания push ax ;сохранить регистры общего назначения push bx push es mov ax,0b800h ;еs настраивается на видеопамять mov es,ax cmp [cs:cnt],0 ;если счетчик не равен 0 jnz fin08 ;то закончить прерывание mov [cs:cnt],90 ;если 0, занести в счетчик значение эквивалентное 5 сек m1: add [cs:col],10h ;изменить цвет н а следующий cmp [cs:col],80h ;если не 80h jnz m2 ;то пропустить mov [cs:col],0 ;сбросить цвет фона m2: mov al,[es:1] ;взять цвет символа в верхнем левом углу shl al,4 ;сдвинуть его в фон cmp [cs:col],al ;если текущий цвет фона будет сливаться с символами jz m1 ;то изменить цвет xor bx,bx ;начало верхней строки видеопамяти lp: and [es:bx+1],byte 0fh ;сбросить фон символа на экране mov al,[cs:col] ;взять цвет фона or [es:bx+1],al ;записать в видеопамять add bx,2 ;перейти к следующему символу cmp bx,160 ;пока не закончится строка экрана jb lp ;продолжать fin08: dec [cs:cnt] ;уменьшить счетчик pop es ;восстанавливаем регистры pop bx pop ax sti ;разрешить прерывания iret ;выход из прерывания InstallTSR: ;загрузка резидента mov ax, 3508h int 21h ;получить адрес обработчика mov dx, word [es:bx+2] ;взять сигнатуру cmp dx, 0fffeh ;если не загружен jnz not_loaded ;то продолжаем call isunload ;проверить нет ли ключа выгрузки test al,al ;если есть jnz unload ;то выгружаем ;иначе выводим сообщение, что загружен mov dx,already ;адрес строки mov ah,09h ;функция вывода строки на экран int 21h ;выводим на экран ex: mov ah,4ch ; стандартный выход из программы int 21h not_loaded: call isunload ;проверить нет ли ключа выгрузки test al,al ;если есть jnz ex ;то не загружаем cli mov word [Old08],BX ;сохранить вектор прерывания mov word [Old08+2],ES mov ax,2508h ; SetVector mov dx,New08Obrab int 21h ;установить новый обработчик прерывания sti ; сообщение об успехе mov dx,Success ;адрес строки mov ah,09h ;функция вывода строки на экран int 21h ;выводим на экран mov ax,3100h ; KeepProc mov dx,(InstallTSR-Begin+10Fh)/16; указываем системе сколько памяти в параграфах занимает наш резидент int 21h ; закончить, но остаться в памяти unload: ;выгрузка cli mov ax,2508h ; функция установки вектора 08h lds dx,[es:Old08] ;в ds:dx адрес старого обработчика (Из копии в памяти!!!) int 21h ;возврашаем старый обработчик sti push es mov es,[es:2ch] ;сегмент окружения из PSP mov ah,49h ;функция освобождения блока памяти int 21h ;освободить сегмент окружения pop es ;es указывет на начало программы в памяти mov ah,49h ;функция освобождения блока памяти int 21h ;выгрузить программу push cs pop ds ;ds=cs mov dx,un ;адрес строки mov ah,09h ;функция вывода строки на экран int 21h ;выводим на экран jmp ex isunload: ;проверка ключа выгрузки mov si,81h ;начало командной строки l1: mov al,[si] ;взять очередной символ cmp al,13 ;если конец командной строки jz no ;то нет ключа выгрузки cmp al,' ' ;если не пробел jnz l2 ;то есть параметр командной строки inc si ;следующий символ jmp l1 ;продолжить поиск l2: cmp [si],byte '/' ;если первый символ ключа не / jnz no ;то нет ключа выгрузки cmp [si+1],byte 'U' ;если первый / jz yes ;и второй U или u cmp [si+1],byte 'u' jz yes ;то есть ключ no: mov al,0 ;нет ключа ret yes: mov al,1 ;есть ключ ret Success db 10,13,'Program loaded',10,13,'$' already db 10,13,'Already loaded',10,13,'$' un db 10,13,'Program unloaded',10,13,'$'
Объяснение кода листинга программы
- Резидентная программа написана на ассемблере.
- Программа использует 16-битный режим.
- Смещение программы в памяти 100h.
- В начале программы есть инструкция jmp InstallTSR, которая загружает программу в память.
- В Old08h хранится резервированный адрес оригинального обработчика прерывания 08h.
- В счетчике cnt хранится количество итераций, которые должны быть выполнены.
- Переменная col используется для хранения текущего цвета фона.
- Новый обработчик прерывания int08h находится в New08Obrab.
- Если счетчик cnt не равен 0, то выполняется цикл m1, который изменяет цвет фона.
- Если цвет фона не равен 0, то выполняется цикл m2, который изменяет цвет символов на экране.
- В начале каждой строки видеопамяти находится адрес начального символа в верхнем левом углу.
- Адрес обработчика прерывания 08h сохраняется в регистрах BX и ES.
- Если ключ выгрузки не найден, то выводится сообщение
Program loaded
. - Если ключ выгрузки найден, то выводится сообщение
Program unloaded
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д