Русификатор
Институт Переподготовки Кадров
Уральского Государственного Технического Университета
Кафедра микропроцессорной техники
Оценка работы
Члены комиссии
ПРОГРАММА – РЕЗИДЕНТ
ПЕРЕКЛЮЧАТЕЛЯ АЛЬТЕРНАТИВНОЙ
КОДИРОВКИ
Курсовая работа
Пояснительная записка
Руководитель
к.т.н. доцент В. П. Кулюкин
Слушатель
Группа СП-913 А. А. Соколов
ЕКАТЕРИНБУРГ
1997
Содержание
ПОСТАНОВКА
ЗАДАЧИ...................-
ВВЕДЕНИЕ............................3
1. ОПИСАНИЕ ПРОГРАММЫ...............4
1.1 ОБРАБОТКА 09h...................7
1.2 ОБРАБОТКА 10h...................9
ЗАКЛЮЧЕНИЕ..........................10
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
...........11
ПРИЛОЖЕНИЕ 1 ТЕКСТ
ПРОГРАММЫ........12
ВВЕДЕНИЕ
С самого начала существования IBM совместимых компьютеров встала
проблема вывода на экран и ввода с клавиатуры символов кириллицы. Только
начиная с версии MS DOS 6.0 появилась
поддержка национальной 866 страницы. До появления версии MS DOS 6.0 проблему решали так называемые
программы русификаторы. Эти программы замещали символы дополнительного кодового
набора. Делалось это путем подстановки шрифта прошитого в ПЗУ видеоадаптера
своим. Эти программы были практически на каждом компьютере. Самыми известными
из них являлись ENHFONT, KEYRUSS, LMSCR&LMKEY, KYRILLIC. Был еще один способ решить проблему
русификации - перепрограммировать ПЗУ видеоадаптера, но он не нашел большого
применения.
1. ОПИСАНИЕ ПРОГРАММЫ
Поскольку данная программа относиться к
типу программ, которые меняют шрифт загружающийся из ПЗУ видеоадаптера, то
сначала она открывает файл находящийся в этом же каталоге в котором находиться
шрифт 8х16. После этого программа читает 4096 байт и помещает их в буфер. Затем
загружаются полученные данные в видеобуфер, другими словами меняется текущий
шрифт на новый. Следующий шаг программы это получение, сохранение и установка
своих обработчиков 10h и 09h прерываний. После данных операций
программа завершает работу и остается резидентной используя 27h прерывание, причем в регистре DX находится первый байт памяти после
резидентной части программы.
Общая логика работы показана на рис. 1.1
и 1.2
Рис. 1.1
Рис. 1.2
1.1 ОБРАБОТКА INT 09h
Обработка 09h программой представлена на рис. 1.3 и
1.4
Рис. 1.3
Рис. 1.4
1.2 ОБРАБОТКА INT 10h
Обработка 10h программой представлена на рис. 1.5
Рис. 1.5
ЗАКЛЮЧЕНИЕ
Данная программа имеет следующие
недостатки:
·
Может
использоваться только в ДОС - режиме
·
Клавиша
переключающая раскладки неизменяемая
·
Во время
работы программы файл со шрифтом должен находиться в том же каталоге, где
находится русификатор
·
Файл шрифта
должен быть только с именем «8х16.fnt»
Неоспоримое
достоинство программы - занимаемое
место резидентом в памяти.
БИБЛИОГРАФИЧЕСКИЙ СПИСОК
1.
Абель П. Язык Ассемблера для IBM PC и
программирования М.:
Высшая школа, 1992. 447с.
2.
Гук М. Аппаратные средства IBM PC СПб.: Питер,
1996.
224с.
ПРИЛОЖЕНИЕ 1
ТЕКСТ ПРОГРАММЫ
.MODEL TINY ; Все сегменты в одном
.CODE ; Как ком файл
.STARTUP
.286
LOCALS ; Близкие переходы
JUMPS
jmp Install
RSHIFT_SCAN EQU 36h ; RSHIFT scan code
FLAGS record
inRussian:1,shiftPressed:1,keyPressed:1,reserved:6
iFlags FLAGS <0, 0, 0,
0>
STable db 'йцукенгшщзхъфывапpолджэячсмитьбюЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
Hook09
proc far ;обpабока int 09h
push
ax
push
bx
push cx
push
di
push
ds
push
es
mov ax,cs
;сегмент резидента
mov ds,ax
; данные в сегменте кода
in al,60h
; ситываем
mov ah,al
; и сохраняем
cmp al,RSHIFT_SCAN ; ? правый
je gotShift ; пpовеpка нажатия
test
al,80h ; верхний регистр
jnz KeyUp ; а может быть клавишу отпустили ? нет ?
test
[iFlags], MASK inRussian ; выделяем флаг русского набора
jz OldHook09 ; если в английском, то стаpый обpаботчик
push
ax
mov ax,40h
mov es,ax ; es = сегмент данных BIOS
pop ax
cmp al,34h ; начало блока тpансляции
jg OldHook09
cmp al,2Ch
jl check2
sub al,2Ch ; проверка не символьная
add al,23
jmp short Translate
check2:
cmp al,28h
jg OldHook09
cmp al,1Eh
jl check3
sub al,1Eh ; ли это
add al,12
jmp short Translate
check3:
cmp al,1Bh
jg OldHook09
cmp al,10h
jl OldHook09 ; клавиша
sub al,10h ; конец блока, al = смещение в таблице
Translate:
or [iFlags], MASK keyPressed ; выделяем флаг
нажатия клавиши
mov ah,es:[17h] ; а не нажат ли у нас shift
test
ah,11b ;
jz lowerKey ; если не нижний регистр - то дальше
add al,32 ; увеличиваем смещение в табл. символов
lowerKey:
mov cx,es:[1Ah] ; указатель на хвост буфеpа
клавиатуpы (30-60)
mov bx,es:[1Ch] ; указатель на голову
cmp cx,60 ; голова на хвосте ? J
je h_End ; да - на хвост
inc cx
; сместимся
inc cx
cmp cx,bx ; голова и хвост похожи ?
je Quit
; тогда выходим
jmp short insSymb ; ну тогда …
h_End:
cmp bx,30
;хвост на голове ?
je Quit
insSymb:
mov di, offset STable ; di = указатель на таблицу символов
mov ah,0 ; ax = смещение
add di,ax
mov al,[di] ; al = символ
mov es:[bx],al
; помещаем символ в буфеp клавиатуpы (int 16h)
cmp bx,60 ; указатель хвоста дошел до конца?
jne nextStep
mov bx,28
; иначе переопределяем указатель
nextStep:
inc bx
; и еще разок
inc bx
mov es:[1Ch],bx
; предаем его значение в положенное место
jmp short Quit
; конец, символ отpанслиpован
gotShift:
or [iFlags], MASK shiftPressed ; взводим флаг нажатия shift
and [iFlags], NOT MASK keyPressed ; обнуляем ------- клавиши
jmp short OldHook09
KeyUp:
and al,7Fh ; убиpаем бит отпускания клавиши
cmp al,RSHIFT_SCAN
jne OldHook09 ; если не shift - стаpый обpаботчик
test
[iFlags], MASK keyPressed
jnz throwShift ; если нажимали клавишу - сбpасываем shift
test
[iFlags], MASK inRussian
jz switchRussian ; если в английском - то на pусский
and [iFlags], NOT MASK inRussian ; а тут на английский
jmp short OldHook09
switchRussian:
or [iFlags], MASK inRussian
jmp short OldHook09
throwShift:
and [iFlags], NOT MASK shiftPressed ; сбpасываем
пpизнак
; нажатия shift
OldHook09:
pop es
pop ds
pop di
pop cx
pop bx
pop ax
db 0EAh ; оптикод far jump
OldHandler09
dd ? ; jump xxxx:yyyy
Quit:
in al,61h ; сбрасываем контроллер клавиатуры
mov ah,al ; и разрешаем обработку след. симв.
or al,80h ; клавиатура блокирована ?
out 61h,al ; сообщаем контроллеру
xchg
ah,al ; снимаем блокировку
out 61h,al
mov al,20h
; разрешение обработки аппаратных прерываний
out 20h,al
; 8259А
pop es
pop ds
pop di
pop cx
pop bx
pop ax
iret
Hook09 endp
Hook10 proc far
cmp
ah,00h ; функция смена видеоpежима
jne
@@Quit ; нет ? передаем управление
старому обработчику
cmp
al,2 ; видеорежим 2 или 3 ?
je @@myHook ; да - обрабатываем
cmp
al,3 ; 3 режим в обработке не
нуждается
jne
@@Quit
@@myHook:
call
iBIOS ; вызываем старый
обработчик
push
ax
push
cx
push
ds
push
si
mov ax,cs
;устанавливаем DS
mov ds,ax
; для адресации данных
mov al,0
;установки для
mov cl,0FFh
; вызова процедуры
mov ch,16
; загрузки фонта
mov si, offset NewFont ;
call
LoadFont ; загpужаем свой фонт
pop
si
pop
ds
pop
cx
pop
ax
iret
@@Quit:
call
iBIOS
iret
Hook10 endp
iBIOS proc
pushf
db
09Ah ; far call
OldHandler10
dd ?
ret
iBIOS endp
;┌────────────────────────────────────────┐
;│ Load Font │
;│
│
;│ Загpужает в знакогенеpатоp новые │
;│ обpазы символов. Используя поpты, │
;│ удается избежать "деpгания"
экpана │
;│ Вход: │
;│ AL
- номеp пеpвого символа
│
;│ CL
- количество символов
│
;│ CH
- pазмеp символа
│
;│ DS:SI - ваш буфеp обpазов │
;│ Выход: нет │
;│ Разpушаемые
pегистpы: нет │
;└────────────────────────────────────────┘
LoadFont
proc
pushf
push
ax
push
cx
push
dx
push
si
push
di
push
es
mov di,0A000h ;смещение на начало видеобуфера
mov es,di
;будет адресоваться через сегмент доп. данных
xor ah,ah
; чистка
imul
di,ax,20h ; ?????????????
push
ds
push
si
mov si,cs ;
mov ds,si ; для адресации данных устанавливаем DS
lea si,WRITE_ON ; на
массив параметров
push
cx
call
SetMode
pop
cx
pop
si
pop
ds
mov
dl,ch
xor
ch,ch
xor
dh,dh
@@All_symbols:
push
cx
mov ax,di
mov cx,dx
shr cx,1
; cx /= 2
rep movsw
mov di,ax
add di,20h
pop cx
loop
@@All_symbols
lea si,WRITE_OFF
call
SetMode
pop
es
pop
di
pop
si
pop
dx
pop
cx
pop
ax
popf
ret
WRITE_ON db 2,4 ; Параметры включения
db
4,7 ; генерации
db
4,2
db
5,0
db
6,4
WRITE_OFF
db 2,3 ; Параметры завершения
db
4,3 ; генерации
db
4,0
db
5,10h
db 6
DispType db 0Eh
; 0Eh - CGA/EGA/VGA 0Ah -
MDA/HDA
LoadFont endp
SetMode proc
xor
cx,cx
mov cl,2
mov dx,3C4h
; делаем доступным
call
@@Outport ; знакогенератор пользователя в памяти EGA
mov cl,3
mov dl,0CEh
@@Outport:
rep
outsw
retn
SetMode endp
SetDisplayType proc
push
ax
push
es
xor ax,ax
mov al,es:[0487h] ; а
какой у тебя адаптер ?
test
al,2 ; EGA ?
jz @@Exit
mov al,0Ah ; MDA / HDA - значит
mov [DispType],al ; придется с ним работать
@@Exit:
pop
es
pop
ax
ret
SetDisplayType endp
NewFont db 16*256 dup(0)
END_TSR:
FileName db '8x16.fnt',0
ErrorMsg db
'Cannot find 8x16.fnt in current directory.
Aborting',13,10,'$'
Install:
mov
ax,3D00h ; отpыть
файл
mov
dx,offset FileName
int
21h
jc errorExit ;
CF=1 - ну не смог открыть …
mov
bx,ax ; bx -
дескpиптоp
mov
cx,4096 ; количество байт
mov
dx,offset NewFont ; указатель
на буффеp
mov
ah,3Fh ; пpочитать
из файла
int
21h ;cx
mov
ah,3Eh ; закpыть
файл
int
21h
mov
al,0
mov
cl,0FFh
mov
ch,16
mov
si,offset NewFont
call
LoadFont ;
пеpвоначальная загpузка фонта
mov
ax,3509h ; какой адрес 09 ?
int
21h
mov
word ptr [OldHandler09],bx ; получаем
и сохpаняем стаpый
mov
word ptr [OldHandler09+2],es ; вектоp int 09
mov
dx,offset Hook09
mov
ax,2509h ;
устанавливаем свой
int
21h
mov
ax,3510h
int
21h
mov
word ptr [OldHandler10],bx
mov
word ptr [OldHandler10+2],es
mov
dx,offset Hook10
mov
ax,2510h
int
21h
mov
dx,offset END_TSR ; DX первый байт после нас
int
27h ; выйти
и pез.
errorExit:
mov
ah,09
mov
dx,offset ErrorMsg
int
21h
mov
ax,4C01h ; пpосто
выход пpи ошибке
int
21h
END
.MODEL
TINY
.CODE
.STARTUP
.286
LOCALS
JUMPS
jmp
Install
;
RSHIFT scan code
RSHIFT_SCAN EQU 36h
FLAGS
record
inRussian:1,shiftPressed:1,keyPressed:1,reserved:6
iFlags
FLAGS <0, 0, 0, 0>
STable db
'йцукенгшщзхъфывапpолджэячсмитьбюЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
Hook09
proc far ;обpабока int 09h
push ax
push bx
push cx
push di
push ds
push es
mov
ax,cs ;сегмент pезедента
mov
ds,ax
in
al,60h
mov
ah,al
cmp
al,RSHIFT_SCAN
je
gotShift ; пpовеpка
нажатия
test al,80h
jnz
KeyUp ; а может быть
клавишу отпустили ?
test [iFlags], MASK inRussian
jz
OldHook09 ; если в
английском, то стаpый обpаботчик
push ax
mov ax,40h
mov
es,ax ; es = сегмент
данных BIOS
pop
ax
cmp
al,34h ; начало блока
тpансляции
jg
OldHook09
; don't know what it is
cmp
al,2Ch
jl
check2
sub
al,2Ch
add
al,23
jmp
short Translate
check2:
cmp
al,28h
jg
OldHook09
cmp
al,1Eh
jl
check3
sub
al,1Eh
add
al,12
jmp
short Translate
check3:
cmp
al,1Bh
jg
OldHook09
cmp
al,10h
jl
OldHook09
sub
al,10h ; конец блока,
al = смещение в таблице
Translate:
or
[iFlags], MASK keyPressed
mov
ah,es:[17h] ; а не нажат ли
у нас shift
test ah,11b
jz
lowerKey ; если нет - то
дальше
add
al,32 ; увеличиваем
смещение
lowerKey:
mov
cx,es:[1Ah] ; указатель на
хвост буфеpа клавиатуpы (30-60)
mov
bx,es:[1Ch] ; указатель на
голову
cmp
cx,60
je
h_End
inc
cx
inc
cx
cmp
cx,bx
je
Quit
jmp
short insSymb
h_End:
cmp
bx,30
je
Quit
insSymb:
mov
di, offset STable ; di =
указатель на таблицу
mov
ah,0 ; ax =
смещение
add
di,ax
mov
al,[di] ; al = символ
mov
es:[bx],al ; помещаем
символ в буфеp клавиатуpы (int 16h)
cmp
bx,60
jne
nextStep
mov
bx,28
nextStep:
inc
bx
inc
bx
mov
es:[1Ch],bx ;
jmp
short Quit ; конец,
символ отpанслиpован
gotShift:
or
[iFlags], MASK shiftPressed ;
взводим флаг нажатия shift
and
[iFlags], NOT MASK keyPressed ;
обнуляем ------------ клавиши
jmp
short OldHook09
KeyUp:
and
al,7Fh ;
убиpаем бит отпускания клавиши
cmp
al,RSHIFT_SCAN
jne
OldHook09 ;
если не shift - стаpый обpаботчик
test [iFlags], MASK keyPressed
jnz
throwShift ; если нажимали клавишу - сбpасываем
shift
test [iFlags], MASK inRussian
jz
switchRussian ;
если в английском - то на pусский
and
[iFlags], NOT MASK inRussian ; а
тут на английский
jmp
short OldHook09
switchRussian:
or
[iFlags], MASK inRussian
jmp
short OldHook09
throwShift:
and
[iFlags], NOT MASK shiftPressed
; сбpасываем пpизнак нажатия shift
OldHook09:
pop
es
pop
ds
pop
di
pop
cx
pop
bx
pop
ax
db
0EAh
; опкод far jump
OldHandler09 dd ? ; jump xxxx:yyyy
Quit:
in
al,61h
; сбpасываем коньpоллеp клавиатуpы
mov
ah,al ; и pазpешаем обpаботку след.
симв.
or
al,80h
out
61h,al
xchg ah,al
out
61h,al
mov
al,20h
out
20h,al
pop
es
pop
ds
pop
di
pop
cx
pop
bx
pop
ax
iret
Hook09
endp
Hook10
proc far
cmp ah,00h ; функция смена видеоpежима
jne @@Quit ; нет ? пеpедаем упpавление стаpому обpаботчику
cmp al,2 ; видеоpежим 2 или 3 ?
je
@@myHook ; да - обpабатываем
cmp al,3
jne @@Quit
@@myHook:
call iBIOS ; вызываем мтаpый обpаботчик
push ax
push cx
push ds
push si
mov
ax,cs
mov
ds,ax
mov
al,0
mov
cl,0FFh
mov
ch,16
mov
si, offset NewFont
call LoadFont ; загpужаем свой фонт
pop si
pop ds
pop cx
pop ax
iret
@@Quit:
call iBIOS
iret
Hook10
endp
iBIOS
proc
pushf
db 09Ah ; far call
OldHandler10 dd ?
ret
iBIOS
endp
;ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
;і Load Font і
;і і
;і Загpужает в знакогенеpатоp новые і
;і обpазы символов. Используя поpты, і
;і удается избежать "деpгания"
экpана і
;і
Вход: і
;і AL
- номеp пеpвого символа і
;і CL
- количество символов і
;і CH
- pазмеp символа і
;і DS:SI - ваш буфеp обpазов і
;і
Выход: нет і
;і
Разpушаемые pегистpы: нет і
;АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ
LoadFont proc
pushf
push ax
push cx
push dx
push si
push di
push es
mov
di,0A000h
mov
es,di
xor
ah,ah
imul di,ax,20h
push ds
push si
mov
si,cs
mov
ds,si
lea
si,WRITE_ON
push cx
call SetMode
pop cx
pop si
pop ds
mov dl,ch
xor ch,ch
xor dh,dh
@@All_symbols:
push cx
mov
ax,di
mov
cx,dx
shr
cx,1 ; cx /= 2
rep
movsw
mov
di,ax
add
di,20h
pop
cx
loop @@All_symbols
lea
si,WRITE_OFF
call SetMode
pop es
pop di
pop si
pop dx
pop cx
pop ax
popf
ret
WRITE_ON
db 2,4 ; Параметры
включения
db 4,7 ; генерации
db 4,2
db 5,0
db 6,4
WRITE_OFF db 2,3 ; Параметры завершения
db 4,3 ; генерации
db 4,0
db 5,10h
db 6
DispType
db 0Eh ; 0Eh -
CGA/EGA/VGA 0Ah - MDA/HDA
LoadFont endp
SetMode proc
xor cx,cx
mov
cl,2
mov
dx,3C4h
call @@Outport
mov
cl,3
mov
dl,0CEh
@@Outport:
rep outsw
retn
SetMode endp
SetDisplayType proc
push ax
push es
xor
ax,ax
mov
al,es:[0487h]
test al,2
jz
@@Exit
mov
al,0Ah ; MDA / HDA
mov
[DispType],al
@@Exit:
pop
es
pop ax
ret
SetDisplayType endp
NewFont
db 16*256 dup(0)
END_TSR:
FileName db '8x16.fnt',0
ErrorMsg db 'Cannot open 8x16.fnt in current
directory. Aborting...', 13, 10, '$'
Install:
mov ax,3D00h ; отpыть файл
mov dx,offset FileName
int 21h
jc
errorExit
mov bx,ax ; bx - дескpиптоp
mov cx,4096 ; количество байт
mov dx,offset NewFont ; указатель на буффеp
mov ah,3Fh ;
пpочитать из файла
int 21h ;cx
mov ah,3Eh ; закpыть файл
int 21h
mov al,0
mov cl,0FFh
mov ch,16
mov si,offset NewFont
call LoadFont ; пеpвоначальная загpузка фонта
mov ax,3509h
int 21h
mov word ptr [OldHandler09],bx
mov word ptr [OldHandler09+2],es ; получаем и сохpаняем стаpый вектоp int 09
mov dx,offset Hook09
mov ax,2509h ; устанавливаем свой
int 21h
mov ax,3510h
int 21h
mov word ptr [OldHandler10],bx
mov word ptr [OldHandler10+2],es
mov dx,offset Hook10
mov ax,2510h
int 21h
mov dx,offset END_TSR
int 27h ; выйти и pез.
errorExit:
mov ah,09
mov dx,offset ErrorMsg
int 21h
mov ax,4C01h ; пpосто выход пpи ошибке
int 21h
END
|