Поскольку тема про секс-символы закрыта придется мериться программами на ассемблере.
Вот исходник программы, написанной мной году в 1999-ом (и за нее я получил небольшие деньги).
Резидентный драйвер под DOS для перекодировки интерфейсов (ИРПР в ИРПР-М).
Предназначен был для подключения к PC принтера CM6315
Скрытый текст
TITLE CM6315
P286
Text SEGMENT PARA
ASSUME CS: Text
ORG 100h
;------------- начало резидентной части программы -------------------
; Old_2Fh_Vector dd 0
Old_2Fh_Vector:
Entry:
jmp near ptr Begin ; эта команда занимает три байта
fourthbyte db 0
Old_17h_Vector dd 0
OUR_2Fh_MUX_ID EQU 0C7h
Koi7Rus db 97, 98, 119, 103, 100, 101, 118, 122, 105, 106, 107, 108, 109, 110, 111
db 112, 114, 115, 116, 117, 102, 104, 99, 126, 123, 125, 120, 121, 120, 124
db 96, 113, 97, 98, 119, 103, 100, 101, 118, 122, 105, 106, 107, 108, 109
db 110, 111, 112, 32, 32, 32, 255, 255, 255, 255, 43, 43, 255, 255, 43, 43
db 43, 43, 43, 43, 45, 45, 255, 45, 43, 255, 255, 43, 43, 45, 45, 255, 45
db 43, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 255, 255, 32
db 114, 115, 116, 117, 102, 104, 99, 126, 123, 125, 120, 121, 120, 124, 96
db 113, 101, 101
lptStrobe EQU 01h
lptNoAutoLF EQU 02h
lptInit EQU 04h
lptSelect EQU 08h
lptIRQEnb EQU 10h
WRITE_LPT_CONTROL_PORT MACRO Value ; запись в порт управления LPT1
pusha
mov DX, 37Ah
mov AL, Value
out DX, AL
popa
ENDM
WaitWhileAcknowledgeZero PROC NEAR
push AX
mov DX, 379h
iszero:
in AL, DX
test AL, 40h
jz iszero
pop AX
retn
WaitWhileAcknowledgeZero ENDP
WaitWhileAcknowledgeNotZero PROC NEAR
push AX
mov DX, 379h
notzero:
in AL, DX
test AL, 40h
jnz notzero
pop AX
retn
WaitWhileAcknowledgeNotZero ENDP
; если в AL - символ Ch1, заменить его на Ch2 и пеpеход на RecodedLabel
REPLACE_CHAR MACRO Ch1, Ch2, RecodedLabel
LOCAL noexchange;
cmp AL, Ch1
jne noexchange
mov AL, Ch2
jmp near ptr RecodedLabel
noexchange:
ENDM
; процедура вывода символа на СМ6315 с ожиданием в конце строки
PrintKOI7H2Char PROC NEAR ; в AL - код символа
cmp AL, 32
jae printable_char
cmp AL, 10
je recoded
cmp AL, 13
je recoded
jmp near ptr endprint
printable_char:
REPLACE_CHAR '|', 255, recoded
REPLACE_CHAR '~', '^', recoded
REPLACE_CHAR '`', 39, recoded
REPLACE_CHAR '}', ']', recoded
REPLACE_CHAR '{', '[', recoded
cmp AL, 'a'
jb recoded
cmp AL, 'z'
ja rus
sub AL, 32
jmp short recoded
rus:
REPLACE_CHAR 'Ё', 'Е', dorec
REPLACE_CHAR 'ё', 'е', dorec
cmp AL, 241
ja endprint
cmp AL, 128
jae dorec
dorec:
sub AL, 128
xor AH, AH
mov BX, OFFSET Koi7Rus
add BX, AX
mov AL, BYTE PTR CS:[BX]
recoded:
; инвертируем код символа
not AL
; ждем сигнала готовности получить символ
call WaitWhileAcknowledgeNotZero
; вывод символа в LPT - порт
mov DX, 378h
out DX, AL
; выставляем сигнал подтверждения передачи символа
WRITE_LPT_CONTROL_PORT lptSelect+lptStrobe
; ждем сигнала "неготовности" получить другой символ
call WaitWhileAcknowledgeZero
; сбрасываем сигнал подтверждения передачи символа
WRITE_LPT_CONTROL_PORT lptSelect
; ждем сигнала готовности получить символ
call WaitWhileAcknowledgeNotZero
endprint:
retn
PrintKOI7H2Char ENDP
; функция (прерывания BIOS) печати на принтере символа
New_17h PROC FAR
push DX
push AX
WRITE_LPT_CONTROL_PORT lptSelect
cmp AH, 00h
jne retstatus
call PrintKOI7H2Char ; в AL - код символа
retstatus:
; получим статус порта принтера
mov DX, 379h
in AL, DX
; сформируем значение PrinterStatusRec
mov AH, AL
and AH, 10111000b
xor AH, 08h
mov DH, AH
pop AX
mov AH, DH
pop DX
iret
New_17h ENDP
; Entry: AH = OUR_2Fh_MUX_ID; AL = 0; DX = 0FFFFh;
; Exit (if Ok): AL = 0FFh; DX = CS
New_2Fh PROC FAR
cmp AH, OUR_2Fh_MUX_ID
jne old2Fh
cmp AL, 0
jne old2Fh
cmp DX, 0FFFFh
jne old2Fh
mov AL, 0FFh
mov DX, CS
jmp short end2Fh
old2Fh:
jmp DWORD PTR Old_2Fh_Vector
end2Fh:
iret
New_2Fh ENDP
ResidentSectionEndLabel LABEL WORD
;------------- конец резидентной части программы --------------------
;------------- нерезидентная часть программы ------------------------
SET_VECTOR MACRO IntNumber, NewHandle, OldVector
mov AL, IntNumber
mov AH, 35h
int 21h
mov Word Ptr OldVector, BX
mov Word Ptr OldVector+2, ES
mov AH, 25h
mov DX, OFFSET NewHandle
int 21h
ENDM
RESTORE_VECTOR MACRO IntNumber, OldVector
mov AL, IntNumber
mov AH, 25h
mov DX, Word Ptr OldVector
mov DS, Word Ptr OldVector+2
int 21h
ENDM
AboutStr db 33, 44, 43, 1, 1, 66, 76, 23, 18, 16, 20, 1, 87, 15, 16, 15, 16, 44, 43, 33
WhatIsStr db 99, 67, 67, 236, 131, 205, 192, 131, 195, 207, 207, 195, 67, 204, 198, 131, 198, 201, 205, 199, 203, 131, 205, 193, 201
db 203, 67, 130, 203, 207, 193, 205, 200, 205, 193, 67, 199, 200, 140, 67, 227, 245, 236, 240, 67, 242, 239, 85, 80, 82, 86, 110, 105, 99
AuthorStr db 33, 1, 1, 9, 66, 8, 1, 161, 140, 133, 193, 132, 136, 1, 184, 137, 193, 202, 136, 1, 19, 17, 17, 17, 12, 19, 17, 17, 16, 44, 43, 33
UsageStr db 51, 62, 57, 19, 19, 180, 147, 144, 211, 208, 148, 153, 147, 9, 19, 19, 19, 80, 94, 5, 0, 2, 6, 29, 80, 92, 94, 62, 57, 19, 19, 177, 216
db 144, 211, 208, 148, 153, 147, 9, 19, 19, 19, 80, 94, 5, 0, 2, 6, 29, 80, 92, 94, 19, 28, 70, 62, 57, 51
LoadedStr db 11, 6, 1, 43, 43, 132, 174, 235, 174, 161, 165, 175, 163, 235, 165, 169, 226, 163, 161, 43, 232, 173, 174, 43, 172, 171, 168, 235, 232, 173, 174, 166, 6, 1, 6, 1, 11
MemErrStr db 79, 66, 69, 111, 111, 193, 167, 231, 238, 229, 239, 111, 225, 174, 237, 225, 238, 225, 233, 235, 234, 226, 231, 160, 111, 224, 239, 227, 160, 173, 231, 66, 69, 79
UnloadStr db 34, 47, 40, 2, 2, 173, 135, 194, 135, 136, 140, 134, 138, 194, 140, 128, 203, 138, 136, 2, 128, 201, 129, 194, 193, 132, 135, 143, 47, 40, 34
BadPrmStr db 99, 110, 105, 67, 67, 238, 198, 193, 198, 131, 206, 136, 202, 67, 204, 195, 131, 195, 207, 198, 129, 131, 110, 105, 99
UnloadMe db 0
; процедура расшифровки и вывода на экран строки
WriteString PROC NEAR
mov AH, 02h
mov DH, [SI]
nextchar:
inc SI
mov DL, [SI]
xor DL, DH
jz nullchar
int 21h
jmp short nextchar
nullchar:
retn
WriteString ENDP
WRITE MACRO String
mov SI, OFFSET String
call WriteString
ENDM
Begin:
; найти параметр [/u|/U|-u|-U] в командной строке
mov CL, BYTE PTR ES:[80h]
or CL, CL
jz NoParam
mov AL, 32
mov DI, 81h
xor CH, CH
cld
repe scasb ; пропускаем пробелы
mov AX, WORD PTR ES:[DI-1]
cmp AL, 2Dh
je Check2
cmp AL, 2Fh
jne BadParam
Check2:
cmp AH, 55h
je IsUnloadParam
cmp AH, 75h
je IsUnloadParam
BadParam:
WRITE BadPrmStr
jmp near ptr Exit
IsUnloadParam:
mov UnloadMe, 1
jmp short LoadIFNess
NoParam:
mov UnloadMe, 0
LoadIFNess:
mov AH, 4Ah
mov BX, 00
int 21h
jc MemFreeErr
; освободить блок окружения
mov AX, WORD PTR ES:[2ch]
mov ES, AX
mov AH, 49h
int 21h
jc MemFreeErr
mov AX, CS
mov DS, AX
WRITE_LPT_CONTROL_PORT lptSelect
mov AH, OUR_2Fh_MUX_ID
mov AL, 0
mov DX, 0FFFFh
int 2Fh
cmp AL, 0 ; если не загружен
je Load
cmp UnloadMe, 1
je UnLoad
jmp near ptr Loaded
Load:
WRITE AboutStr
WRITE WhatIsStr
WRITE AuthorStr
WRITE UsageStr
SET_VECTOR 17h, New_17h, Old_17h_Vector
SET_VECTOR 2Fh, New_2Fh, Old_2Fh_Vector
; завершиться но остаться резидентным
mov DX, OFFSET ResidentSectionEndLabel ; Установка окончания резидентной части
int 27h
MemFreeErr:
WRITE MemErrStr
jmp near ptr Exit
Loaded:
WRITE LoadedStr
jmp near ptr Exit
Unload:
; в DX мультиплексное прерывание возвращает CS резидента
mov ES, DX
RESTORE_VECTOR 17h, ES:Old_17h_Vector
RESTORE_VECTOR 2Fh, ES:Old_2Fh_Vector
mov AH, 49h
int 21h
jc MemFreeErr
mov AX, CS
mov DS, AX
WRITE UnloadStr
jmp near ptr Exit
Exit:
mov AX, 4C00h
int 21h
Text ENDS
END Entry