Цель работы:
Изучить возможности динамических библиотек.
Текст задания:
Разработать динамическую библиотеку, реализующую функции в соответствии с заданным вариантом, и программу для демонстрации ее возможностей. Использовать как явное, так и неявное связывание. Примечание: pchar – строка ascii-символов, заканчивающаяся нулем.
15.
function DeTab8(S: pchar): pchar .
Возвращает строку, в которой все вхождения кода горизонтальной табуляции Ht=9 расширены пробелами. Для этого строка просматривается слева направо и встречающиеся коды Ht заменяются на требуемое в данной позиции количество пробелов. Количество пробелов можно определить из формулы, связывающей индекс произвольной текущей позиции i c индексом следующей позиции табуляции j:
- 35 - j=(((i-1)/8)+1)*8+1 ,
ГСА процедуры:
Текст программы:
Файл «def32.inc»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
; файл с определениями констант и типов STD_OUTPUT_HANDLE equ -11 OPEN_EXISTING equ 3 CREATE_ALWAYS equ 2 GMEM_MOVEABLE equ 2 GMEM_ZEROINIT equ 40h RECT struc left dd ? top dd ? right dd ? bottom dd ? RECT ends NO_ERROR equ 0 ERROR_NO_MORE_ITEMS equ 259 RESOURCEUSAGE_CONNECTABLE equ 1 RESOURCETYPE_ANY equ 0 RESOURCE_CONNECTED equ 1 NTRESOURCE struc dwScope dd ? dwType dd ? dwDisplayType dd ? dwUsage dd ? lpLocalName dd ? lpRemoteName dd ? lpComment dd ? lpProvider dd ? NTRESOURCE ends GENERIC_READ equ 80000000h GENERIC_WRITE equ 40000000h FILE_SHARE_READ equ 1 FILE_SHARE_WRITE equ 2 FILE_ATTRIBUTE_ARCHIVE equ 20h MB_OK equ 0 MB_ICONINFORMATION equ 40h IDC_ARROW equ 32512 IDI_APPLICATION equ 32512 WS_OVERLAPPEDWINDOW equ 0CF0000h WM_DESTROY equ 2 WM_COMMAND equ 111h WM_INITDIALOG equ 110h WM_CLOSE equ 10h CS_HREDRAW equ 2 CS_VREDRAW equ 1 CW_USEDEFAULT equ 80000000h SW_SHOWNORMAL equ 1 COLOR_WINDOW equ 5 BN_CLICKED equ 0 WNDCLASSEX struc cbSize dd ? style dd ? lpfnWndProc dd ? cbClsExtra dd ? cbWndExtra dd ? hInstance dd ? hIcon dd ? hCursor dd ? hbrBackground dd ? lpszMenuName dd ? lpszClassName dd ? hIconSm dd ? WNDCLASSEX ends MSG struc hwnd dd ? message dd ? wParam dd ? lParam dd ? time dd ? pt dd ? MSG ends WM_CREATE equ 1 WM_ACTIVATE equ 6 WM_SETTEXT equ 0Ch WM_GETTEXT equ 0Dh WM_CUT equ 300h WM_COPY equ 301h WM_PASTE equ 302h WM_CLEAR equ 303h WM_UNDO equ 304h WM_SIZE equ 5 WS_VISIBLE equ 10000000h WS_CHILD equ 40000000h WS_EX_CLIENTEDGE equ 200h ES_LEFT equ 0 ES_MULTILINE equ 4 ES_AUTOHSCROLL equ 80h ES_AUTOVSCROLL equ 40h EM_GETHANDLE equ 0BDh EM_GETMODIFY equ 0B8h EM_SETMODIFY equ 0B9h EM_UNDO equ 0C7h EM_SETSEL equ 0B1h MB_YESNO equ 4 MB_ICONWARNING equ 30h IDOK equ 1 IDYES equ 6 OFN_PATHMUSTEXIST equ 800h OFN_FILEMUSTEXIST equ 1000h OFN_EXPLORER equ 80000h OFN_OVERWRITEPROMPT equ 2 OPENFILENAME struc lStructSize dd ? hwndOwner dd ? _hInstance dd ? lpstrFilter dd ? lpstrCustomFilter dd ? nMaxCustFilter dd ? nFilterIndex dd ? lpstrFile dd ? nMaxFile dd ? lpstrFileTitle dd ? nMaxFileTitle dd ? lpstrInitialDir dd ? lpstrTitle dd ? Flags dd ? nFileOffset dw ? nFileExtension dw ? lpstrDefExt dd ? lCustData dd ? lpfnHook dd ? lpTemplateName dd ? OPENFILENAME ends |
Файл «dlldemo.inc»:
1 2 3 4 5 6 7 8 9 |
includelib import32.lib extrn MessageBoxA:near extrn ExitProcess:near extrn LoadLibraryA:near extrn FreeLibrary:near extrn GetProcAddress:near MessageBox equ MessageBoxA LoadLibrary equ LoadLibraryA MB_OK equ 0000H |
Файл «dlldemo1.asm»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
; неявное подключение dllrus.dll ; выводит строку в KOI8 и затем в cp1251, ;перекодированную функцией koi2wins include dlldemo.inc includelib dllfile.lib extrn koi2win_asm:near extrn koi2win:near extrn koi2wins_asm:near extrn koi2wins:near extrn Change:near .386 .model FLAT,STDCALL .const title_string1 db 'koi2win demo: string in KOI8',0 title_string2 db 'koi2win demo: translate to cp1251',0 .data koi_string db 'єLT¦T+ ++ ыящ-8',0 instr db "11 1174657 3498573 348578 1",0 outstr db 100 dup(?),0 S dd ?; Ї а ¬Ґва S Res dd ?; .code _start: call Change,offset instr,offset outstr; call MessageBox,0,offset instr,\ offset title_string1, MB_OK ;call koi2wins,offset koi_string call MessageBox,0,offset outstr,\ offset title_string2,MB_OK call ExitProcess,0 ; конец программы end _start |
Файл «dllfile.asm»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
; DLL для win32 - перекодировщик из koi8 в cp1251 .386 .model flat ; функции, определяемые в этом DLL public koi2win_asm;koi2win_asm перекодирует символ в AL public koi2win; CHAR WINAPI koi2win(CHAR symbol) public koi2wins_asm;koi2wins_asm перекодирует строку в ;[EAX] public koi2wins ; VOID WINAPI koi2win(CHAR * string) public Change ;--------------------------------------------------------------- .const ; таблица для перевода символа из кодировки KOI8-r ;(RFC1489) в кодировку Windows (cp1251) ; для символов 80h – FFh (т.е. надо вычесть 80h из ;символа, преобразовать его и снова добавить 80h) k2w_tbl db 16 dup(0);символы, не существующие в cp1251, db 16 dup(0) ; перекодируются в 80h db 00h, 00h, 00h, 38h, 00h, 00h, 00h, 00h db 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h db 00h, 00h, 00h, 28h, 00h, 00h, 00h, 00h db 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h db 7Eh, 60h, 61h, 76h, 64h, 65h, 74h, 63h db 75h, 68h, 69h, 6Ah, 6Bh, 6Ch, 6Dh, 6Eh db 6Fh, 7Fh, 70h, 71h, 72h, 73h, 66h, 62h db 7Ch, 7Bh, 67h, 78h, 7Dh, 79h, 77h, 7Ah db 5Eh, 40h, 41h, 56h, 44h, 45h, 54h, 43h db 55h, 48h, 49h, 4Ah, 4Bh, 4Ch, 4Dh, 4Eh db 4Fh, 5Fh, 50h, 51h, 52h, 53h, 46h, 42h db 5Ch, 5Bh, 47h, 58h, 5Dh, 59h, 57h, 5Ah .code _start@12: ;процедура входа dll, в данном случае – ;пустая заглушка mov al,1 ; надо вернуть ненулевое число в EAX ret 12 ; перекодировка символа, передаче параметров через стек koi2win proc pop ecx ; обратный адрес в ECX pop eax;параметр в ECX (теперь стек очищен от ;параметров!) push ecx ; обратный адрес вернуть в стек для RET ; здесь нет команды RET - управление передается следующей процедуре koi2win endp ; перекодировка символа, ввод: AL - код символа в KOI, вывод: AL - код этого же символа в WIN koi2win_asm proc test al,80h ;если символ меньше 80h (старший бит 0), jz dont_decode ; не перекодировать, push ebx ; иначе - mov ebx,offset k2w_tbl sub al,80h ; вычесть 80h, xlat ; перекодировать add al,80h ; и прибавить 80h, pop ebx dont_decode: ret ; выйти koi2win_asm endp ; перекодировка строки, передача параметров через стек koi2wins proc pop ecx ; адрес возврата из стека pop eax ; параметр в EAX push ecx ; адрес возврата в стек koi2wins endp ; перекодировка строки, ввод: EAX - адрес строки, которую надо преобразовать из KOI в WIN koi2wins_asm proc push esi; сохранить регистры, которые нельзя изменять push edi push ebx mov esi,eax ; приемник строк mov edi,eax ; и источник совпадают mov ebx,offset k2w_tbl decode_string: lodsb ; прочитать байт, test al,80h ; если старший бит 0, jz dont_decode2 ; не перекодировать, sub al,80h ; иначе - вычесть 80h, xlat ; перекодировать add al,80h ; и добавить 80h dont_decode2: stosb ; вернуть байт на место, test al,al ; если байт - не ноль, jnz decode_string ; продолжить pop ebx pop edi pop esi ret koi2wins_asm endp ; function Change(S: string; Ch1, Ch2: char): string, ; ў®§ўа й Ґв бва®Єг, ў Є®в®а®© ўбҐ ўе®¦¤ҐЁп ‘h1 § ¬ҐҐл Ch2 ;--------------------------------------------------------------- Change proc ; ¤аҐб Ї а ¬Ґва®ў ў б⥪Ґ: pop eax; pop ecx; pop edx; push eax; ;S equ dword ptr [bp+6] ; Ї а ¬Ґва S ;Res equ dword ptr [bp+10] ; Ї а ¬Ґва Res (१г«мв в) push bp ; б®еа ҐЁҐ bp mov bp,sp ; бва®©Є bp ўҐаиЁг б⥪ push ds ; б®еа ҐЁҐ ds mov edi,edx ; es:di:= ¤аҐб १г«мв в mov esi,ecx ; ds:si:= ¤аҐб Ёб室®© бва®ЄЁ cld ; ®зЁбвЄ д« Ј Їа ў«ҐЁп (ЁЄаҐ¬Ґв) ;lodsb ; al:=(ds:[si]), si:=si+1 (al - ¤«Ё S) ; mov al,0ffh; ;stosb ; (es:[di]):=al, di:=di+1 (§ ЇЁбм ¤«Ёл) mov ecx,0 ; Ї®¤Ј®в®ўЄ бе ў Є зҐб⢥ бзҐвзЁЄ ;mov cl,255;al ; Є®«ЁзҐбвў бЁ¬ў®«®ў бва®ЄЁ S ;jcxz Exit ; ўл室, Ґб«Ё S - Їгбв п бва®Є (бе=0) ;push bx; ;C dw 00h; mov bx,00h; ;mov C,bx; ;pop bx; Repeat: ;pop bx; lodsb ; бзЁв вм ў al ®зҐаҐ¤®© бЁ¬ў®« S mov cl,al; inc cl; push ecx; ;push bx; ;push cx; ;mov bx,C; ;inc bx; mov cx,01h; cmp al,09h ; бЁ¬ў®« а ўҐ Tab? jne Save ; Ґв, б®еа Ёвм ЎҐ§ Ё§¬ҐҐЁ© mov cx,bx; sub cx,1; shr cx,3; ;shr cx,1; ;shr cx,1; add cx,1; shl cx,3; ;shl cx,1; ;shl cx,1; sub cx,bx; jnz Replace; mov cx,08h; Replace: mov al,20h ; ¤ , § ¬ҐЁвм Ch2 ;mov C,bx; Save: ;pop bx; inc bx; stosb ; § ЇЁб вм ®зҐаҐ¤®© бЁ¬ў®« १г«мв в Res ;push bx; loop Replace; pop ecx; loop Repeat ; Ї®ўв®апвм, Ї®Є Ґбвм бЁ¬ў®«л ў S (cx>0) Exit: ; mov edi,edx; ; mov bx, 0ffh; ; mov ax,bx; ; stosb; pop ds ; ў®ббв ®ўЁвм ds pop bp ; ў®ббв ®ўЁвм bp (sp Ё§¬ҐҐ Є®а४в®) ret ; ўл室 б г¤ «ҐЁҐ¬ Ї а ¬Ґва®ў Ch1, Ch2 Ё ; ¤аҐб S (Res г¤ «пвм Ґ«м§п!) Change endp end _start@12 |
Файл «dllfile.def»:
1 |
EXPORTS koi2win_asm koi2win koi2wins koi2wins_asm Change |
Результат работы программы:
№ Опыта | Вход | Выход |
1 | 111<Tab>111<Tab>1111 | 111<5 Пробелов>111<5 Пробелов>1111 |
2 | 11111111<Tab>1 | 11111111<8 Пробелов>1 |
3 | <Tab>1 | <8 Пробелов>1 |
Выводы:
Составленная процедура работает верно.