текст программы (1071547), страница 2
Текст из файла (страница 2)
1 263 ;записываем в строку минуты
1 264 01D6 2E: 89 1E 010Ar mov [ WORD PTR cs:Time_String + 3 ], bx
1 265 ;записываем в строку секунды
1 266 01DB 2E: 89 0E 010Dr mov [ WORD PTR cs:Time_String + 6], cx
1 267
1 268 ;проверяем: а не перерисовывался экран в том месте, где у нас показываются
1 269 ;часы ( это нужно чтобы не восстановить на экране не то, что нужно )
1 270 ;проверка проводится по символам ':' ( я надеюсь этого будет достаточно )
1 271 ;часы всегда находятся в левом верхнем углу
1 272 01E0 68 B800 push 0B800h ; адрес сегмента начала видеопамяти VGA
1 273 01E3 07 pop es
1 274 01E4 26: 80 3E 0004 3A cmp [ BYTE PTR es:0004h ], ':' ; B800:0004h - адрес первого символа ':'
1 275 ; ( вернее там он должен быть )
1 276 01EA 75 0A jne @@Store_New_Screen ; если его там нет => экран перерисовывался => надо
1 277 ; запомнить новый перерисованный экран
1 278 01EC 26: 80 3E 000A 3A cmp [ BYTE PTR es:000Ah ], ':' ; B800:000Ah - адрес второго символа ':'
1 279 ; ( вернее там он должен быть )
1 280 01F2 75 02 jne @@Store_New_Screen ; если его там нет => экран перерисовывался => надо
1 281 ; запомнить новый перерисованный экран
1 282 ;если мы здесь => наши часы перерисованы не были => ничего делать не надо
1 283 01F4 EB 0F jmp @@Show_Current_Time ; переходим к показу текущего времени
1 284 01F6 @@Store_New_Screen:
1 285 ;экран был перерисован => мы запоминаем новый экран
1 286 01F6 2E: C5 36 0103r lds si, [ DWORD PTR cs:Video_Memory_Start ] ; адрес начала запоминаемой области
1 287 01FB 0E push cs ; указываем адрес строки, где будет хранится
1 288 01FC 07 pop es ; запоминаемая часть экрана
1 289 01FD BF 0110r mov di, OFFSET Temp_String
1 290 0200 B9 0008 mov cx, 08h ;копироваться будет восемь слов ( символ + его аттрибут )
1 291 0203 F3> A5 rep movsw ;собственно копируем
1 292 0205 @@Show_Current_Time:
1 293 ;Печатаем строку со временем
1 294 0205 2E: C4 3E 0103r les di, [ DWORD PTR cs:Video_Memory_Start ]
1 295 020A 0E push cs
1 296 020B 1F pop ds
1 297 020C BE 0107r mov si, OFFSET Time_String
1 298
1 299 020F B4 0E mov ah, 0Eh ; цвет будет желтый на черном
1 300
1 301 ;собственно выводим на экран строку
1 302 0211 B9 0008 mov cx, 08h
1 303 0214 @@Next_Char:
1 304 0214 AC lodsb
1 305 0215 AB stosw
1 306 0216 E2 FC loop @@Next_Char
1 307
1 308 0218 @@Exit_Procedure:
1 309 ;разрешаем аппаратные прерывания
1 310 0218 FB sti
1 311 ;восстанавливаем использовавшиеся регистры
1 312 0219 07 pop es
1 313 021A 1F pop ds
1 314 021B 61 popa
1 315 ;возвращаемся из процедуры обработки прерывания
1 316 021C CF iret
1 317 021D ENDP New_1C_Vector
1 318
1 319 ;------------------------------------------------------------------------------
1 320
1 321 ;процедура обработки прерывания 2Fh
1 322 021D PROC New_2F_Vector FAR
1 323 021D CC int 03h
1 324 ;проверяем, а нас ли требует вызывающая программа
1 325 021E 80 FC BD cmp ah, 0BDh
1 326 0221 75 10 jne @@Finish_Procedure ;нет не нас
1 327 ;да - нас
1 328 ;какую функцию от нас требуют ?
1 329 ;подтвердить присутствие ?
1 330 0223 3C 00 cmp al, 00h
1 331 0225 74 06 je @@We_Are_Here
1 332 ;вернуть адрес начала нашего PSP ?
1 333 0227 3C 01 cmp al, 01h
1 334 0229 74 05 je @@Return_PSP_Segment_Address
1 335 ;от нас требуют не предусмотренную функцию
1 336 022B EB 06 jmp @@Finish_Procedure
1 337 022D @@We_Are_Here:
1 338 ;устанавливаем признак того, что мы здесь
1 339 022D B0 FF mov al, 0FFh
1 340 ;возвращаемся из процедуры
1 341 022F CF iret
1 342 0230 @@Return_PSP_Segment_Address:
1 343 ;устанавливаем выходные параметры
1 344 0230 8C CD mov bp, cs
1 345 ;возвращаемся из процедуры
1 346 0232 CF iret
1 347 0233 @@Finish_Procedure:
1 348 ;вызываем старый обработчик прерываний
1 349 0233 2E: FF 2E 0129r jmp [ DWORD PTR cs:Old_2F_Vector ]
1 350 0238 ENDP New_2F_Vector
1 351
1 352 ;------------------------------------------------------------------------------
1 353
1 354
355
356 ;указатель на окончание резидентной части
357 0238 LABEL Last_Byte_Of_TSR_Part BYTE
358
359 ;процедура инициализации
360 0238 PROC Initialize
361 ;Проверяем, а не требует ли пользователь от нас помощи по использованию
362 ;программы ( параметр /? в командной строке )
363 0238 0E push cs ;передаем адрес
364 0239 1F pop ds ;строки с
365 023A BA 07FAr mov dx, OFFSET HelpParameter ;требуемым параметром
366 023D B0 00 mov al, 00h ;указываем, что нужно игнорировать
367 ;регистр символов
368 023F E8 005E call IsParameter ;если CF = 1, то указанный параметр найден в командной строке
369 0242 73 0B jnc @@Proceed ; если параметр не найден, то продолжаем
370 ;да - параметр /? есть в командной строке
371 ;показываем строку помощи
372 0244 BA 06D0r mov dx, OFFSET HelpString
373 0247 B8 0900 mov ax, PRINT_STRING
374 024A CD 21 int DOS_INT
375 ;завершаем программу
376 024C E8 0283 call FinishProgram
377 024F @@Proceed:
378 ;Проверяем, а не загружена ли уже программа в память
379 024F B8 BD00 mov ax, 0BD00h ; а это для 2Fh - варианта
380 0252 CD 2F int MUX_INT
381 0254 3C FF cmp al, 0FFh ;наша программа в памяти ?
382 0256 75 1F jne @@Not_In_Memory ;нет - ее в памяти нет
383 ;Проверяем командную строку на наличие параметра /U - unload
384 0258 0E push cs ; передаем адрес
385 0259 1F pop ds ; строки
386 025A BA 07F7r mov dx, OFFSET UnloadParameter ; с требуемым параметром
387 025D B0 00 mov al, 00h ; указываем, что нужно игнорировать
388 ; регистр символов
389 025F E8 003E call IsParameter ;если CF = 1, то указанный параметр найден в командной строке
390 0262 73 06 jnc @@Do_Not_Unload
391 ;выгружаем программу из памяти
392 0264 E8 01D5 call UnloadProgramFromMemory
393 ;завершаем программу
394 0267 E8 0268 call FinishProgram
395 026A @@Do_Not_Unload:
396 ;печатаем сообщение о присутствии программы в памяти
397 026A 0E push cs
398 026B 1F pop ds
399 026C BA 0534r mov dx, OFFSET ProgramAlreadyLoadedMessage
400 026F B8 0900 mov ax, PRINT_STRING
401 0272 CD 21 int DOS_INT
402 ;завершаем программу
403 0274 E8 025B call FinishProgram
404 0277 @@Not_In_Memory:
405 ;Оставляем программу резидентной в памяти
406 ;устанавливаем новый обработчик 09h прерывания
407 0277 E8 0286 call Install_New_09_Handler
408 ;устанавливаем новый обработчик 1Ch прерывания
409 027A E8 0269 call Install_New_1C_Handler
410 ;устанавливаем новый обработчик 2Fh прерывания
411 027D E8 029A call Install_New_2F_Handler
412 ;высвобождаем память, занятую копией переменных среды, созданной для
413 ;нашей программы
414 0280 B8 4900 mov ax, FREE_MEMORY
415 0283 2E: 8E 06 002Cr mov es, [ Env_Seg ]
416 0288 CD 21 int DOS_INT
417 ;печатаем сообщение об оставлении программы в памяти
418 028A 0E push cs
419 028B 1F pop ds
420 028C BA 0581r mov dx, OFFSET ProgramLoadedMessage
421 028F B8 0900 mov ax, PRINT_STRING
422 0292 CD 21 int DOS_INT
423 ;вычисляем размер резидентной части
424 0294 BA 0024 mov dx, ( Last_Byte_Of_TSR_Part - First_Byte_Of_TSR_Part + 15 )/16
425 ;оставляем программу в памяти
426 0297 2E: C6 06 012Dr 00 mov [BYTE PTR Exit_Code], 0
427 029D E8 023C call KeepProgram
428 02A0 ENDP Initialize
429
430
431 ;включаем файлы с используемыми процедурами
432 INCLUDE "clk_unit.asm"
1 433
1 434 ;------------------------------------------------------------------------------
1 435
1 436 ;процедура проверки загруженности программы в память
1 437 02A0 PROC IsParameter
1 438 ;Передаваемые параметры
1 439 ; DS:DX - адрес ASCIIZ строки с параметром, который нужно искать в командной
1 440 ; строке
1 441 ; AL = 0 если нужно игнорировать регистр символов
1 442 ; AL = другое значение, если надо учитывать регистр символов
1 443 ;Возвращаемые параметры
1 444 ; CF = 0 если указанный параметр НЕ НАЙДЕН в командной строке
1 445 ; CF = 1 если указанный параметр НАЙДЕН в командной строке
1 446 ;Разрушаемые регистры
1 447 ; нет
1 448 ;запоминаем флаг преобразования регистра
1 449 02A0 2E: A2 02A7r mov [ Register_Flag ], al
1 450 ;перескакиваем данные
1 451 02A4 E9 0105 jmp @@Code_Start
1 452 ;данные
1 453 02A7 00 Register_Flag DB 0
1 454 02A8 82*(00) Parameter_Copy DB 130 DUP(0) ;копия строки с параметром, который
1 455 ;мы ищем
1 456 032A 82*(00) Command_Line_Copy DB 130 DUP(0) ;копия командной строки
1 457 ;код
1 458 03AC @@Code_Start:
1 459 ;сохраняем все регистры
1 460 03AC 60 pusha
1 461 03AD 1E push ds
1 462 03AE 06 push es
1 463
1 464 ;Делаем копию ASCIIZ строки с параметром
1 465 03AF 8B F2 mov si, dx
1 466 03B1 0E push cs
1 467 03B2 07 pop es
1 468 03B3 BF 02A8r mov di, OFFSET Parameter_Copy
1 469 03B6 @@Copy_1:
1 470 03B6 80 3C 00 cmp [ BYTE PTR ds:si ], 00h
1 471 03B9 A4 movsb
1 472 03BA E0 FA loopne @@Copy_1
1 473 ;Делаем копию командной строки
1 474 03BC 0E push cs
1 475 03BD 1F pop ds
1 476 03BE BE 0081 mov si, COMMAND_LINE_START
1 477 03C1 0E push cs
1 478 03C2 07 pop es
1 479 03C3 BF 032Ar mov di, OFFSET Command_Line_Copy
1 480 03C6 @@Copy_2:
1 481 03C6 80 3C 0D cmp [ BYTE PTR ds:si ], 0Dh ;т.к. коммандная строка заканчивается байтом 0Dh
1 482 03C9 A4 movsb
1 483 03CA E0 FA loopne @@Copy_2
1 484 03CC 4F dec di ; заменяем в конце строки
1 485 03CD 32 C0 xor al, al ; байт 0Dh
1 486 03CF AA stosb ; на 00h
1 487
1 488 ;Если надо - преобразовываем обе строки к верхнему регистру
1 489 03D0 2E: 80 3E 02A7r 00 cmp [ Register_Flag ], 00h ; если совпадает => нужно игнорировать регистр
1 490 03D6 75 10 jne @@Find_Parameter ; не совпадает => никаких преобразований регистра мы
1 491 ; производить не будем
1 492 ;Нужно игнорировать регистр => преобразуем к верхнему регистру строку с
1 493 ;параметром и командную строку ( вернее их копии, т.к. именно с копиями мы
1 494 ;производим все манипуляции )
1 495 ;Преобразуем строку с параметром
1 496 03D8 BA 02A8r mov dx, OFFSET Parameter_Copy
1 497 03DB B8 6522 mov ax, UPSHIFT_ASCIIZ_STRING
1 498 03DE CD 21 int DOS_INT
1 499 ;Преобразуем командную строку
1 500 03E0 BA 032Ar mov dx, OFFSET Command_Line_Copy
1 501 03E3 B8 6522 mov ax, UPSHIFT_ASCIIZ_STRING
1 502 03E6 CD 21 int DOS_INT
1 503
1 504 03E8 @@Find_Parameter:
1 505 ;Ищем указанный параметр
1 506 ;устанавливаем DS:SI на начало строки с параметром
1 507 03E8 0E push cs
1 508 03E9 1F pop ds
1 509 03EA BE 02A8r mov si, OFFSET Parameter_Copy
1 510 ;устанавливаем ES:DI на начало командной строки
1 511 03ED 0E push cs
1 512 03EE 07 pop es
1 513 03EF BF 032Ar mov di, OFFSET Command_Line_Copy
1 514 ;будем сравнивать в нормальном порядке ( слева направо )
1 515 03F2 FC cld
1 516 ;а вдруг параметр нулевой длины ? ( проверяем )
1 517 03F3 80 3C 00 cmp [ BYTE PTR ds:si ], 00h
1 518 03F6 74 3C je @@Parameter_Not_Found ; так оно и есть => выходим
1 519 ;а вдруг командная строка нулевой длины ? ( проверяем )
1 520 03F8 26: 80 3D 00 cmp [ BYTE PTR es:di ], 00h
1 521 03FC 74 36 je @@Parameter_Not_Found ; так оно и есть => выходим
1 522 ;Начинаем сравнение
1 523 03FE @@Compare_Again:
1 524 03FE A6 cmpsb ;проверяем символы на совпадение
1 525 03FF 74 09 je @@Match_Found
1 526
1 527 ;Если текущие символы в сравниваемых строках не совпадают
1 528 ;проверяем, а не кончилась ли командная строка
1 529 0401 26: 80 3D 00 cmp [ BYTE PTR es:di ], 00h
1 530 0405 74 2D je @@Parameter_Not_Found ; так оно и есть => выходим
1 531 ;ни одна строка не кончилась => переходим к сравнению следующего символа