Задание:
Тестирование дискеты. По имени файла (в том числе и не в корневом каталоге) выводит номера кластеров, занятых им, и их состояние (плохой или нет) для дискеты. Задача состоит из двух частей. Первая — поиск файла обходом каталогов (возможно, рекурсивным). Вторая — просмотр и проверка кластеров, занятых этим файлом, по таблице размещения файлов (FAT).
Алгоритм:
Тексты программ:
Создать единую программу для поиска файла и проверки кластеров, в которых он находится не удалось, так как в документации по функциям Windows не удалось найти функции для работы с кластерами. Поэтому была создана отдельно программа для поиска файла и отдельно для проверки её размещения по таблице FAT. Причём вторая программа – программа DOS, так как под Windows не удалось вызвать ни одно прерывание.
Программа для поиска файла:
«console.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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
;Консольное приложение для win32, перечисляющее сетевые ресурсы include console.inc .386 .model FLAT,STDCALL .const greet_message db 'Example win32 console program' db 0Dh, 0Ah,0Dh,0Ah,0 error1_message db 0Dh,0Ah,'Couldnot get current user name',0Dh,0Ah,0 error2_message db 0Dh,0Ah,'Could not enumerate', 0Dh,0Ah,0 good_exit_msg db 0Dh,0Ah,0Dh,0Ah,'Normal termination', 0Dh,0Ah,0 enum_msg1 db 0Dh,0Ah,'Local ',0 enum_msg2 db ' remote - ',0 .data user_name db 'List of connected resources for user ' user_buff db 64 dup (?) ; буфер для WNetGetUser user_buff_l dd $-user_buff ;размер буфера для WNetGetUser enum_buf_l dd 1056 ; длина enum_buf в байтах enum_entries dd 1 ; число ресурсов, которые в нём помещаются msgstr1 db 10,13,'INT',10,13,0,'$' fff db 'STARTBUF' mybuf db 1000 dup(0); ggg db 'ENDBUF' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mytext db 500 dup(?); buff db 500 dup(?); nextfile db 13,10,"->",0 mytext2 db "Hello ",0; mytext3 db "Строка",0 vstrp db "strpath=",0 strpath db 500 dup(?); strdrive db "A:\*",0 strspace db " ",0 strfile db "filename.txt" strr db "\",0 strz db "*",0 strt db "..",0 datt dw 5; dt WIN32_FIND_DATA hFile dd; X dd 000000000h; n dw; LEBX dd ? FirstSearch db 0 .data? enum_buf NTRESOURCE <?,?,?,?,?,?,?,?>; буфер для WNetEnumResource dd 256 dup (?) ; 1024 байт для строк message_l dd ? ; переменная для WriteConsole enum_handle dd ? ; идентификатор для WNetEnumResource .code _start: ; получим от системы идентификатор буфера вывода stdout push STD_OUTPUT_HANDLE call GetStdHandle ;возвращает идентификатор STDOUT в eax mov ebx,eax ; а мы будем хранить его в EBX ; выведем строку greet_message на экран mov esi,offset greet_message call output_string ; определим имя пользователя, которому принадлежит наш процесс mov esi,offset user_buff push offset user_buff_l; адрес переменной с длиной буфера push esi ; адрес буфера push 0 ; NULL call WNetGetUser cmp eax,NO_ERROR ; если произошла ошибка jne error_exit1 ; выйти mov esi,offset user_name ; иначе - выведем строку на экран call output_string ; начнём перечисление сетевых ресурсов push offset enum_handle ; идентификатор для WNetEnumResource push 0 push RESOURCEUSAGE_CONNECTABLE ; все присоединяемые ресурсы push RESOURCETYPE_ANY ; ресурсы любого типа push RESOURCE_CONNECTED ; только присоединённые сейчас call WNetOpenEnum ; начать перечисление cmp eax,NO_ERROR ; если произошла ошибка jne error_exit2 ; выйти enumeration_loop: ; цикл перечисления ресурсов push offset enum_buf_l ; длина буфера в байтах push offset enum_buf ; адрес буфера push offset enum_entries ; число ресурсов push dword ptr enum_handle ; идентификатор от WNetOpenEnum call WNetEnumResource cmp eax,ERROR_NO_MORE_ITEMS ; если они закончились je end_enumeration ; завершить перечисление cmp eax,NO_ERROR ; если произошла ошибка jne error_exit2 ; выйти с сообщением об ошибке ; вывод информации ресурсе на экран mov esi,offset enum_msg1 ; первая часть строки call output_string ; на консоль mov esi,dword ptr enum_buf.lpLocalName ; ; локальное имя устройства call output_string ; на консоль mov esi,offset enum_msg2 ; вторая часть строки call output_string ; на консоль mov esi,dword ptr enum_buf.lpRemoteName ; удалённое имя устройства call output_string ; туда же jmp short enumeration_loop ; продолжим перечисление end_enumeration: push dword ptr enum_handle call WNetCloseEnum ; конец перечисления mov esi,offset good_exit_msg exit_program: call output_string ; выведем строку mov LEBX,ebx; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov edi,offset mytext; mov ebx,offset mytext3; mov esi,offset mytext2; call CopyStr; mov edi,offset mytext; mov ebx,offset mytext3; mov esi,offset mytext2; call AddStr; mov esi, offset strpath ;push esi; mov edi,offset strpath; mov esi,offset strdrive; call CopyStr; push ebx; call DrawFiles; pop ebx; mov esi,offset strfile mov edi, offset 12; push edi; сколько байт надо вывести на консоль push esi ; адрес строки для вывода на консоль push ebx ; идентификатор буфера вывода call WriteConsole ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push 0 ; код выхода call ExitProcess ; конец программы ; выходы после ошибок error_exit1: mov esi,offset error1_message jmp short exit_program error_exit2: mov esi,offset error2_message jmp short exit_program ; процедрура output_string выводит на экран строку ; ввод: esi - адрес строки, ebx - идентификатор stdout ; или другого консольного буфера output_string proc near cld ; определим длину строки xor eax,eax mov edi,esi repne scasb dec edi sub edi,esi push 0 ; пошлём её на консоль push offset message_l;сколько байт выведено на консоль push edi; сколько байт надо вывести на консоль push esi ; адрес строки для вывода на консоль push ebx ; идентификатор буфера вывода call WriteConsole ; WriteConsole(hConsoleOutput, lpvBuffer, cchToWrite, ;lpcchWritten, lpvReserved) ret output_string endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;процедура копирования строки ESI - адрес источника, EDI - адрес получателя CopyStr proc push esi; push edi; push eax; mcopyproc1: mov al,[esi]; mov [edi],al; inc esi; inc edi; cmp al,0; jne mcopyproc1; pop eax; pop edi; pop esi; ret CopyStr endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;процедура вычисления длины строки ESI - источник EAX - результат LenStr proc push ESI; push edx; mov eax,0; maddstr1: mov dl,[esi]; inc esi; inc eax; cmp dl,0; jne maddstr1; pop edx; pop ESI; ret LenStr endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;процедура добавления 1 строки в конец другой ESI - источник строка1, EBX - строка2, EDI - результат AddStr proc; push esi; push edi; push ebx; push eax; call CopyStr; call LenStr; add edi,eax; dec edi; mov esi,ebx; call CopyStr add eax,"0"; ;call MessageBox,0,offset edi,\ ;0,MB_OK ; и покажем его в MessageBox pop eax; pop ebx; pop edi; pop esi; ret AddStr endp; MyFunc proc sub datt,1; jz zero dec datt; mov edi,offset mytext; ;add dx,datt; ;mov [edi],'q'; ;mov [edi+1],'q'; ;mov [edi+2],0; call MyFunc; zero: MyFunc endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PrintFile proc mov edi,offset buff; mov esi,offset mytext; call CopyStr; mov esi, offset buff; mov ebx,offset dt.cFileName; mov edi,offset mytext; call AddStr mov edi,offset buff; mov esi,offset mytext; call CopyStr; mov edi,offset mytext; mov ebx, offset nextfile; mov esi, offset buff; call AddStr ;mov ecx,X; ;mprintfile1: ; mov edi,offset buff; ; mov esi,offset mytext; ; call CopyStr; ; ; ; mov edi,offset mytext; ; mov ebx, offset strspace; ; mov esi, offset buff; ; call AddStr ; loop mprintfile1; ret PrintFile endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Процедура заполнения Mytext ESI - каталог для поиска DrawFiles proc ;pop esi; ;push hFile; ;push n; push ebp mov ebp,esp push eax; push ebx; push ecx; push edx; call MessageBox,0,offset vstrp,\ 0,MB_OK ; и покажем его в MessageBox call MessageBox,0,offset strpath,\ 0,MB_OK ; и покажем его в MessageBox call FindFirstFile,offset strpath, offset dt mov hFile,eax; call GetLastError cmp eax,0 je FirstFileFound pop edx; pop ecx; pop ebx; pop eax; pop ebp ret FirstFileFound: ;call PrintFile ;mov edi,offset dt.cFileName; ;mov [edi],0; mov ecx,40; mov esi,offset strpath ;call LenStr ;cmp eax,5 ;je NextFileFound metkaloop: push ecx; call FindNextFile,hFile, offset dt call GetLastError cmp eax,0; jne NO_MORE_FILES ;NextFileFound: mov esi,offset dt.cFileName; mov edi,offset strt; mov cx,word ptr [esi]; cmp cx,word ptr [edi]; jne ddalee pop ecx; jmp metkaloop; ddalee: mov edi, offset strfile mov ecx,12 msrvn: mov al,[edi]; cmp al,[esi]; jne ddalee2; inc edi inc esi; loop msrvn call MessageBox,0,offset strpath,\ 0,MB_OK ; и покажем его в MessageBox mov esi, offset strpath; mov ebx,LEBX call output_string; ddalee2: ;call PrintFile; ;pop hFile; ;;;; ;рекурсивный вызов push eax; mov esi,offset strpath; mov edi,offset strpath; call LenStr sub eax,2; ;mov ecx,eax; add edi,eax; ;mm1: ;mov [edi],"0"; ;inc edi; ;loop mm1; mov [edi],0; mov edx,eax; pop eax; push edx; jmp mmmm1; metkaloop1: jmp metkaloop; mmmm1: mov edi, offset strpath mov esi, offset strpath; mov ebx,offset dt.cFileName; call AddStr mov ebx, offset strr; call AddStr mov ebx, offset strz; call AddStr ;mov esi, offset strr ;call AddStr push hFile; ;add X,2; call DrawFiles; pop hFile; call MessageBox,0,offset strpath,\ 0,MB_OK ; и покажем его в MessageBox pop edx; mov edi,offset strpath; add edi,edx; mov [edi],'*' inc edi mov [edi],0; call MessageBox,0,offset strpath,\ 0,MB_OK ; и покажем его в MessageBox ;sub X,2; pop ecx; LOOP metkaloop1 NO_MORE_FILES: ;call AddStr ;;mov ebx,offset enter; ;call AddStr; ;pop n; ;pop hFile; pop edx; pop ecx; pop ebx; pop eax; leave ret DrawFiles endp end _start |
Файл «console.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 |
includelib import32.lib ; имена используемых функций из kernel32.dll extrn ExitProcess:near extrn WriteConsoleA:near extrn GetStdHandle:near ; присваивания для облегчения читаемости кода WriteConsole equ WriteConsoleA ; имена используемых функций из mpr.dll extrn WNetGetUserA:near extrn WNetOpenEnumA:near extrn WNetEnumResourceA:near extrn WNetCloseEnum:near ; присваивания для облегчения читаемости кода WNetGetUser equ WNetGetUserA WNetOpenEnum equ WNetOpenEnumA WNetEnumResource equ WNetEnumResourceA ; определения констант и типов NO_ERROR equ 0 ERROR_NO_MORE_ITEMS equ 259 RESOURCEUSAGE_CONNECTABLE equ 1 RESOURCETYPE_ANY equ 0 RESOURCE_CONNECTED equ 1 STD_OUTPUT_HANDLE equ -11 NTRESOURCE struc dwScope dd ? dwType dd ? dwDisplayType dd ? dwUsage dd ? lpLocalName dd ? lpRemoteName dd ? lpComment dd ? lpProvider dd ? NTRESOURCE ends ; имена используемых функций из user32.dll extrn MessageBoxA:near extrn DialogBoxParamA:near extrn GetDlgItem:near extrn GetDlgItemTextA:near extrn SetDlgItemTextA:near extrn EndDialog:near extrn SetFocus:near extrn FindFirstFileA:near; extrn FindNextFileA:near; extrn GetLastError:near; ; присваивания для облегчения читаемости кода MessageBox equ MessageBoxA DialogBoxParam equ DialogBoxParamA GetDlgItemText equ GetDlgItemTextA SetDlgItemText equ SetDlgItemTextA FindFirstFile equ FindFirstFileA FindNextFile equ FindNextFileA WIN32_FIND_DATA struc ; { // wfd dwFileAttributes DD ; ftCreationTime DQ ; ftLastAccessTime DQ; ftLastWriteTime DQ; nFileSizeHigh DD ; nFileSizeLow DD ; dwReserved0 DD ; dwReserved1 DD ; cFileName DB 260 dup(0); cAlternateFileName DB 14 dup(?); WIN32_FIND_DATA ends; ; определения констант и типов WM_COMMAND equ 111h WM_INITDIALOG equ 110h WM_CLOSE equ 10h BN_CLICKED equ 0 MB_OK equ 0 |
Программа для определения в каких кластерах находится данный файл:
Файл «lab6.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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
FCB struc; Structura dla raboti s failom drv db ? FILENAME db 8 dup(?) ; EXT db 3 dup(?) ; CurBlk dw 0 ; RecSize dw 0 ; filesize dd 0 ; date dw 0 ; reserved db 10 dup(0) ; CurRec dw 0 ; RandomRec dd 0 ; FCB ends; KORNSECT struc JMP1 db 3 dup(?); ff db 8 dup(?) SectSize dw ?; ClustSize db ?; ResSecs dw ?; FatCnt db ?; RootSiz dw ?; TotSecs dw ?; Media db ?; FatSize dw ?; TrkSecs dw ?; HeadCnt dw ?; RidnSec dw ?; KORNSECT ends data segment NCl dw ?; NC dw ?; msg1 db 10,13, 'Program started...','$' msgstr1 db 10,13, 'First str:',10,13,'$' msgstr2 db 10,13, 'Second str:',10,13,'$' msgstr3 db 10,13, 'Third str:',10,13,'$' msgafter db 10,13,'After MyProc:',10,13,'$' file1 db 'filenametxt' per1 db 0 ggg db 'STARTOFDATA' myfcb FCB ?; xxx db 'ENDOFDATA' mydta db 33 dup(0);; gggg db 'STARTKORNSEC' ks KORNSECT ?; xxxx db 'ENDKORNSEC' qqq db 'STARTFAT' FAT dw 1000 dup(?); WWW db 'ENDFAT' data ends; code segment assume cs:code,ds:code,es:data; start: mov ax,data; настроить сегментный mov ds,ax; регистр ds на данные mov es,ax; lea dx,msg1; call print_msg MOV AX,01H; mov bx,offset per1; mov [bx], AL; mov ax,offset myfcb.FILENAME; mov di,ax; dword ptr myfcb.FILENAME; mov ax,offset file1 mov si,ax; dword ptr file1; cld; mov cx,11; m1: lodsb; stosb; loop m1; mov ah,1ah; mov dx, offset mydta int 21h; mov di,offset mydta; inc di; add di,01ah; mov di, offset myfcb mov ah,01h; mov [di],ah; mov ah,11h; mov dx,offset myfcb; int 21h; mov al,0; mov cx,1; mov dx,1; mov bx, offset FAT; int 25h; mov si,offset mydta; ; inc si; add si,01ah; mov ax,[si] mov NC,1; push ax; shr ax,4 call print_cluster pop ax; mov cx,ax; mov bl,03h; mul bl mov dx,0; mov bx,0002h; div bx; ;add ax,6 shr ax,4; jmp m2; mov dx,ax; mov si,offset FAT; add si,ax; inc si; mov ah,[si]; inc si; mov al,[si]; mov cx,ax; mov bl,03h; push dx; mul bl mov dx,0; mov bx,0002h; div bx; pop dx; cmp dx,2; jne not3 mov ah,0; not3: ;mov bl,03h; ;mul bl ;mov dx,0; ;mov bx,0002h; ;div bx; jmp ifend m2: mov si,offset FAT; add si,ax; mov al,[si]; inc si; mov ah,[si] mov bx,NC; mov NCl,bx mov NC,ax; call print_cluster ;cmp ah, FF sp1: ;mov dx,ax; ;mov ax,NC; push NCl shl NCl,15; jnz ifz; pop NCl; ;mov ax,dx; and ax,0FFFh; jmp ifend jumper1: jmp m2; ifz: pop NCl; ;mov ax,dx; shr NC,4; shr ax,4; and ax,0FFFh; ifend: and NCl,0FFFh; ;and cx,0FF0h; ;cmp cx,0FF0h; cmp NCl,0FFFh; mov cx,ax; mov bx,0003h; mul bx mov dx,0; mov bx,0002h; div bx; jne jumper1; mov ax,dx; shr ax,4; mov si,offset FAT; add si,ax; mov ax,[si]; mov dx,ax; mov ah, 01h; int 21h; mov ah,4ch; завершить int 21h; программу print_msg proc push ax; mov ah,09h; int 21h; pop ax; ret print_msg endp print_number proc push ax push bx push cx push dx; mov bx,ax; mov cx,bx; mov bx,0; return_position: mov dl,016; mov ax,cx; div dl; mov cl,al; mov ch,0; mov dl,ah; mov dh,0; mov ah,02h; cmp dx,10; jge great; add dx,'0'; Jmp viv; great: add dx,'A'; sub dx,10; viv: ;mov ah,02h; ;int 21h; push dx; inc bx; cmp cx , 0h;; jg return_position mov cx,bx; mov ah,02h; Write: pop dx; int 21h; LOOP Write; mov dx,13; int 21h; mov dx, 10; int 21h; pop dx pop cx pop bx pop ax; ret; print_number endp print_cluster proc push ax ;and ah,0Fh;; mov ah,0; push NC shl NC,12; jnz dddd; shr ax,4 dddd: pop NC call print_number pop ax; ret; print_cluster endp; ends end start |
Вывод:
Была составлена программа проверяющая в каких кластерах находится данный файл.