Некорректная работа процедуры, реализованной как часть обработчика int09 - Assembler
Формулировка задачи:
Здравствуйте, хочу спросить. Написал TSR прогу в формате СОМ, которая должна выводить на экран скэн-коды
нажатых клавиш. Формат вывода: 2-ух символьный код в 16-теричной системе плюс символ "h".
При активации вместо кодов выводится только "h", а перед ним двойное пустое поле. Если, однако,
запустить какую-либо программу после моей, то в поле для скэн-кодов отобразится мусор.
Те же процедуры,
не выполненные как часть резидентного обработчика, работают правильно, более того,
при просмотре дампа памяти при активном TSR, 2-ух байтовое поле "string" содержит код нажатой клавиши.
Запускаю под Вин-7 из DosBox.
В чем проблема?
Для краткости привожу только код обработчика, остальные процедуры нареканий не вызывают.
scan2hex directout
old_int9 dd ? old_int2f dd ? string db '??' flag db 0 khold db ? int9_handler proc pushf push ax bx es di si in al,60h mov khold,al cmp al,0 je outme mov bx,40h mov es,bx cmp byte ptr es:[17h],2 ;bit 1 set ? (LShift DOWN) je nxt jmp same nxt: cmp al,0fh ;TAB DOWN je toggl jmp same toggl: mov bl,flag not bl mov flag,bl same: cmp flag,0 je outme call scan2hex call directout outme: pop si di es bx ax popf jmp cs:[old_int9] ;------------------subroutines for main handler---------------------- _rout_intern: cmp al,0ah jae add_37 add al,30h jmp nxt1 add_37: add al,37h nxt1: mov byte ptr cs:[si], al inc si retn scan2hex: mov si,offset string mov al,khold push ax shr al,4 call _rout_intern pop ax and al,0fh call _rout_intern retn directout: mov ax,0b800h ;segment start mov es,ax mov di,072dh ;offset start+1 mov byte ptr es:[di],0ch ;pink color attribute for pos. +1 add di,2 ;+3.... mov byte ptr es:[di],0ch add di,2 ;+5... mov byte ptr es:[di],0ch mov si,offset string ;back to string offset+0 mov di,072ch ;now symbol at pos. 0 mov al, byte ptr [si] ;the symbol at pos. 0 mov byte ptr es:[di],al add di,2 inc si mov al, byte ptr [si] ;the symbol at pos. 2 mov byte ptr es:[di],al add di,2 mov byte ptr es:[di],'h' ;the symbol at pos. 4, i.e., 'h' retn int9_handler endp
Решение задачи: «Некорректная работа процедуры, реализованной как часть обработчика int09»
textual
Листинг программы
.286 text segment 'code' assume cs:text, ds:text org 100h main proc jmp init old_int9 dd ? old_int2f dd ? string db '??' flag db 0 khold db ? int9_handler proc pushf push ax bx es di si in al,60h mov khold,al cmp al,0 je outme mov bx,40h mov es,bx cmp byte ptr es:[17h],2 ;bit 1 set ? (LShift DOWN) je nxt jmp same nxt: cmp al,0fh ;TAB DOWN je toggl jmp same toggl: mov bl,flag not bl mov flag,bl same: cmp flag,0 je outme call scan2hex call directout outme: pop si di es bx ax popf jmp cs:[old_int9] ;------------------subroutines for main handler---------------------- _rout_intern: cmp al,0ah jae add_37 add al,30h jmp nxt1 add_37: add al,37h nxt1: mov byte ptr cs:[si], al inc si retn scan2hex: mov si,offset string mov al,khold push ax shr al,4 call _rout_intern pop ax and al,0fh call _rout_intern retn directout: mov ax,0b800h ;segment start mov es,ax mov di,072dh ;offset start+1 mov byte ptr es:[di],0ch ;pink color attribute for pos. +1 add di,2 ;+3.... mov byte ptr es:[di],0ch add di,2 ;+5... mov byte ptr es:[di],0ch mov si,offset string ;back to string offset+0 mov di,072ch ;now symbol at pos. 0 mov al, byte ptr [si] ;the symbol at pos. 0 mov byte ptr es:[di],al add di,2 inc si mov al, byte ptr [si] ;the symbol at pos. 2 mov byte ptr es:[di],al add di,2 mov byte ptr es:[di],'h' ;the symbol at pos. 4, i.e., 'h' retn int9_handler endp ;------------------------------------------------------------------------------------------------- int2f_handler proc pushf cmp ax,0fafbh jne outhand mov ax,0fcfdh popf iret outhand: popf ;DO NOT COMMENT OUT - any other executable will stall the system! jmp cs:[old_int2f] int2f_handler endp end_ISR label byte info db 'TSR scan codes viewer - holding LShift, press & release Tab to toggle',10,13,'$' info1 db 'Occupying: $+ bytes after install$' norun db 13,10,'!TSR is already installed!$' wrd2char proc mov cx, 0 mov bx, 10 loop12: mov dx,0 div bx push ax add dl,'0' pop ax push dx inc cx cmp ax, 0 jnz loop12 mov ah, 2 loop13: pop dx int 21h loop loop13 ret wrd2char endp init: mov ah,9 mov dx,offset info int 21h mov ax,0fafbh int 2fh cmp ax,0fcfdh jne canrun mov ah,9 mov dx,offset norun int 21h mov ax,4c01h int 21h canrun: mov ax,3509h int 21h mov word ptr [old_int9],bx mov word ptr [old_int9+2],es mov ax,2509h mov dx,offset int9_handler int 21h mov ax,352fh int 21h mov word ptr [old_int2f],bx mov word ptr [old_int2f+2],es mov ax,252fh mov dx,offset int2f_handler int 21h mov ah,9 mov dx,offset info1 int 21h mov dx,offset end_ISR add dx,16 mov ax,dx call wrd2char mov ah,9 mov dx,offset info1+12 int 21h mov dx,offset end_ISR mov ax,3100h shr dx,4 inc dx int 21h main endp text ends end main
Объяснение кода листинга программы
- Процедура
int9_handler
обрабатывает прерывание от нажатия клавиш на клавиатуре. - При поступлении прерывания сначала сохраняются регистры, затем из регистра AL считывается скан-код клавиши.
- Если бит 1 регистра AL (LShift) установлен, то выполняется подпрограмма
toggl
, которая меняет значение флагаflag
. - В подпрограмме
scan2hex
сначала определяется начальный сегмент для вывода (0b800h), затем в регистре SI сохраняется смещение начала строки символов, а в регистре DI - смещение начала символа. - Далее в цикле происходит вывод символов, при этом каждый символ выводится на экран в сегменте 0b800h.
- После обработки прерывания выполняется возврат в основную программу, при этом регистры SI и DI содержат смещения следующего символа.
- В подпрограмме
directout
сначала определяется начальный сегмент для вывода (0b800h), затем в регистре SI сохраняется смещение начала строки символов, а в регистре DI - смещение начала символа. - Далее в цикле происходит вывод символов, при этом каждый символ выводится на экран в сегменте 0b800h.
- После обработки прерывания выполняется возврат в основную программу, при этом регистры SI и DI содержат смещения следующего символа.
- В подпрограмме
wrd2char
происходит преобразование числового значения в строку символов. - В начале программы выполняется инициализация: в регистре AX устанавливается значение 0fafbh, которое затем передается в обработчик прерывания int2f_handler.
- Если в обработчике прерывания int2f_handler значение регистра AX не равно 0fcfdh, то выводится сообщение об уже установленном TSR.
- Если в обработчике прерывания int2f_handler значение регистра AX равно 0fcfdh, то выполняется установка TSR.
- После установки TSR выполняется обработка прерывания int9_handler.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д