час
jc wait_time
; переконвертовуємо i записуємо
; у рядок годину, хвилину i секунду
xor ah,ah
mov al,ch
inc si
call Reg2Str
inc si
mov al,cl
call Reg2Str
inc si
mov al,dh
call Reg2Str
; виводимо час на екран
mov ah,13h ; виводимо рядок символів
mov al,0
mov cx,ln ; що саме будемо виводити
mov bx,000Fh
lea bp,td
xor dh,dh
mov dl,80
sub dl,cl
int 10h
pop es
pop ds
popa
iret
td db "xx.xx.xxxx xx:xx:xx" ; формат рядочка, який будемо виводити
ln=$-td
delta dw ?
cntr dw 0
old_1Ch dd ?
; ax - tone
; cx - delay
sound proc
push ax
; установим режим таймера
mov al,0B6h
out 43,al ; порт 43h - керуючий регістр першого таймера
; установим частоту канала
pop ax
out 42h,al ; канал 2 – керує динаміком
mov al,ah
out 42h,al
; включим динамiк i дозволимо таймер
in al,61h
or al,3
out 61h,al
; виконаємо затримку
call delay
; виключим динамiк i заборонемо таймер
and al,0FCh
out 61h,al
ret
delay proc
out_loop: ; цикл затримки
push cx
mov cx,0FFFFh
in_loop:
loop in_loop
pop cx
loop out_loop
ret
endp
; процедура переведення iз reg в ASCII
; ax - reg
; si – адреса, куди будем записувати переведенi
Reg2Str proc
push ax
push cx
or ah,ah
jz cx_is_2
; будемо конвертувати 16 бiт
mov cx,4
all4:
push cx
mov byte ptr ds:[si],0
mov cx,4
get44:
shl ax,1
rcl byte ptr ds:[si],1
loop get44
cmp byte ptr ds:[si],9
jbe be94
add byte ptr ds:[si],37h
jmp don4
be94:
add byte ptr ds:[si],30h
don4:
inc si
pop cx
loop all4
pop cx
pop ax
ret
push ax
push cx
; будемо конвертувати 8 бiт
cx_is_2:
mov cx,2
cx_is_:
push cx
mov byte ptr ds:[si],0
mov cx,4
get42:
shl al,1
rcl byte ptr ds:[si],1
loop get42
cmp byte ptr ds:[si],9
jbe be92
add byte ptr ds:[si],37h
jmp don2
be92:
add byte ptr ds:[si],30h
don2:
inc si
pop cx
loop cx_is_
pop cx
pop ax
ret
endp
endp
my_2Fh proc ; будемо посилати запит на наявність в пам’яті резидента
cmp ax,0AA55h
je my_quest
jmp cs:old_2Fh
my_quest:
xchg al,ah
iret
old_2Fh dd ?
endp
install_:
mov ax,0AA55h ; перевiряємо на наявнiсть
int 2Fh ; одного екземпляра у памятi
cmp ax,55AAh ; чи обмінялися регістри значеннями?
je do_not_install
call Parametr ; отримуємо "координати" параметрiв
call Str2Hex ; переводимо у 16-ву
xor dx,dx
mov bx,18
mul bl ; переводимо у секунди
mov word ptr cs:delta,ax
xor ax,ax
mov es,ax
call vector ; зберiгаємо i замiнюємо вектори
mov dx,(install_-begin_+10Fh)/16
mov ax,3100h ; залишаємо програму резидентною
int 21h
do_not_install:
mov ah,09h
lea dx,installed ; виводимо повідомлення про те, що резидент вже в пам’яті
int 21h
int 20h
installed db 'Programm is already installed!',10,13,'$'
vector proc
; зберiгаємо i замiнюємо вектор вiд таймера
mov ax,word ptr es:[1Ch*4+0]
mov word ptr cs:old_1Ch+0,ax
mov ax,word ptr es:[1Ch*4+2]
mov word ptr cs:old_1Ch+2,ax
mov ax,offset my_1Ch
mov word ptr es:[1Ch*4+0],ax
mov ax,cs
mov word ptr es:[1Ch*4+2],ax
; зберiгаємо i замiнюємо вектор переривання
mov ax,es:[2Fh*4]
mov word ptr cs:old_2Fh,ax
mov ax,es:[2Fh*4+2]
mov word ptr cs:old_2Fh+2,ax
mov ax,offset my_2Fh
mov word ptr es:[2Fh*4],ax
mov ax,cs
mov word ptr es:[2Fh*4+2],ax
ret
endp
; Конвертуємо iз 10-ої системи рядок
; si - адрес рядка
; cx - довжина
; ax - результат у 16-вiй системi
Str2Hex proc
push bx
push dx
push di
mov di,10
xor ax,ax
convert:
mov bl,[si]
and bx,000Fh
mul di
add ax,bx
inc si
loop convert
pop di
pop dx
pop bx
ret
endp
; Вихiд:
; si - адрес на початок
; cx - i довжина параметрiв
Parametr proc
push ax
mov si,81h
mov cl,byte ptr cs:[80h] ; довжина параметрiв
xor ch,ch
; шукаємо числовий початок параметрiв
space_is_still:
lodsb
dec cx
cmp al,' '
je space_is_still
dec si ; коректуємо адрес i
inc cx ; довжину параметрiв
pop ax
ret
endp
endp
end
ОПИС РОБОТИ
Програма складається з двох частин : резидентної, в якій виконуються безпосередньо завдання роботи і загрузчика, який заносить резидентну частину в пам’ять.
На початку програми вибирається тип процесора і вказується номер переривання, за яким слідкуватиме програма. Виконання програми починається із мітки begin_.
Резидентна частина починається із виклику оригінального вектора, визначення часу для подачі звукового сигналу.
Далі відбувається встановлення частоти і тривалості звукового сигналу. В процедурі Sound йде налаштування таймера, включення динаміка, подача звукового сигналу, виконання затримки та виключення динаміка. Також йде задання формату виводу на екран поточного часу та дати. В процедурі vector йде збереження і заміна старого вектора переривань на новий (install_).
Також в програмі передбачений захист від повторної загрузки резидентної програми в пам’ять комп’ютера. Посилаючи запит (AA55h) програма аналізує отриману відповідь. Якщо регістри обмінялися значеннями (55AAh), то резидент вже є в пам’яті, якщо ж ні – йде його загрузка в пам’ять.
Загрузчик починається від мітки install_.
Кількість раз повторення циклу затримки звукового динаміка встановлена на максимум, отже динамік буде спрацьовувати з заданим інтервалом багато разів до завершення користувачем програми.
ВИСНОВКИ
В результаті виконання курсового проектування було написано резидентну програму, що генерує звуковий сигнал через заданий інтервал та виводить поточний час та дату. Наведено блок-схему програми, подано її опис функціонування. Текст резидентної частини програми і загрузчика написано на мові Assembler, з докладним описом використаних функції та ремарками.
ПЕРЕЛІК ВИКОРИСТАНИХ ЛІТЕРАТУРНИХ ДЖЕРЕЛ
1. Зубков СВ. Assembler для DOS, Windows и UNIX -3-е изд., стер. -К Пресс; СПб.гПитер, 2005.-608с.
2. Фролов А.В, Фролов Г.В. Апаратное обеспечение IBM PC: В 2-х ч. Часть 1 - 2-е изд., стер. - М.: „ДИАЛОГ-МИФИ”, 1992.-208 с.
3. Юров В.И. Assembler. Учебник для