Консультация № 178548
21.05.2010, 17:54
42.52 руб.
0 1 1
Здравствуйте уважаемые эксперты! Недавно нашел в сети код будильника, работает прекрасно. Чисто для себя хочу разобраться как он работает. Если есть возможность прокомментируйте пожалуйста, т.к не все понятно(что не ясно отметил знаками вопроса). Здесь готовый файл .com.

Код:

.286
.model tiny

BEEP_DUR_INNER = 5000 ;???
BEEP_DUR_OUTTER = 0D000h ;???

BEEP_TONE = 5 ;???

MAX_HR = 24 ;максимально часов
MAX_MS = 60 ;максимально минут
.code
org 100h
begin:
jmp start

old_int_2fh dd ?

hrs dB ? ;часы
min dB ? ;минуты
sec dB ? ;секунды

int_4a_code:
in al,61h ;???
push ax
or al,03h ;???
out 61h,al ;???


mov cx,BEEP_DUR_OUTTER ;???
mov al,BEEP_TONE ;???
.lo:
out 42h,al ;???

push cx
mov cx,BEEP_DUR_INNER ;???
.li: loop .li
pop cx
loop .lo

pop ax ;???
and al,11111100b ;???
out 61h,al ;???

iret ;возврат изь прерывания

int_2f_code:
;???
cmp ah,0ffh
jne .int_2f_exit
mov al,ah
iret
.int_2f_exit:
;???
jmp cs:old_int_2fh

;===================================================================================
;менюшка
prog_data:
;Строки
m_usage dB 0ah,0dh
dB '=============Usage:=============',0ah,0dh
dB '[alarm -c] - check current state',0ah,0dh
dB '[alarm -HH:MM:SS] - set alarm',0ah,0dh
dB '[alarm -x] - turn the alarm off',0ah,0dh,24h

m_not_active dB 'Alarm is not active',0ah,0dh,24h
m_state dB 'Alarm is set to '
m_hhmmss dB '00:00:00',0ah,0dh,24h
m_off dB 'Alarm has been turned off',0ah,0dh,24h
m_off_already dB 'Alarm has already been turned off',0ah,0dh,24h
m_set dB 'Alarm has been successfully set!',0ah,0dh,24h
m_set_error dB 'Alarm set error!',0ah,0dh,24h



start:

mov si,80h ;???

xor cx,cx ;обнуляем cx
mov cl,[si] ;???
add si,2 ;???

.arg_shrch:
jcxz .arg_out ;???
mov al,[si] ;???
cmp al,'-' ;???
jz .arg_found
inc si ;зачем?
dec cx ;зачем?
jmp .arg_shrch

;вывод
.arg_out:
mov ah,09h
mov dx,offset m_usage
int 21h

;Выход
mov ax,4c01h
int 21h


.arg_found:

inc si
mov al,[si]

;Преобразуем в строчные буквы
or al,20h

;Если с
cmp al,'c'
jne .chk_off


;==========Проверка==================
;Установлен ли?
call check_install
jc .installed
;Сообщение, если нет
mov ah,09h
mov dx,offset m_not_active
int 21h

;Выход
.exit_inst:
mov ax,4c00h
int 21h

.installed:
;Если да

mov ax,354ah ;???
int 21h

mov di,bx ;???

mov al,es:[di-3] ;???
call make_ascii ;преобразование в АSCII

mov word ptr m_hhmmss,ax ;???

mov al,es:[di-2] ;???
call make_ascii ;преобразование в АSCII
mov word ptr m_hhmmss+3,ax ;???

mov al,es:[di-1] ;???
call make_ascii ;преобразование в АSCII
mov word ptr m_hhmmss+6,ax ;???

;Вывод на экран
mov ah,09h
mov dx,offset m_state
int 21h

jmp .exit_inst
;====================================

.chk_off:
;Если -х
cmp al,'x'
jne .chk_set

;==========Выключение================
call check_install
jc .inst_off

mov ah,09h
mov dx,offset m_off_already
int 21h

jmp .exit_inst
.inst_off:
mov ah,07h ;???
int 1ah ;???

mov ax,354ah ;???
int 21h
mov di,bx ;???

mov ah,35h ;???
mov al,2fh ;???
push ds
lds dx,[di-7] ;???
int 21h

pop ds

mov ah,49h ;освобождение резидента
int 21h

;сообщение об успехе операции
mov ah,09h
mov dx,offset m_off
int 21h

;====================================
jmp .exit_inst
.chk_set:

call make_bcd ;???
mov hrs,al ;???

add si,2
cmp byte ptr [si],':' ;???
je .cont

mov ah,09h
mov dx,offset m_usage
int 21h

mov ax,4c01h
int 21h
.cont:

inc si ;???
call make_bcd ;???
mov min,al ;???

add si,2 ;???
cmp byte ptr [si],':' ;???
je .proceed ;???

mov ah,09h
mov dx,offset m_usage
int 21h

mov ax,4c01h
int 21h

.proceed:
inc si
call make_bcd
mov sec,al
;==========Установка=================

;Проверка
call check_install
jc .no_install_on


;Запрет прерываний
cli

;Получаем адрес 2fh(почему)
mov ah,35h
mov al,2fh
int 21h

mov word ptr old_int_2fh,bx ;???
mov word ptr old_int_2fh+2,es ;???

mov ah,25h ;???
mov al,2fh ;???
mov dx,offset int_2f_code ;???
int 21h

mov ah,25h ;???
mov al,4ah ;???
mov dx,offset int_4a_code ;???
int 21h
;Разрешение прерываний
sti


;???
mov ah,06h
mov ch,hrs
mov cl,min
mov dh,sec
int 1ah

;Сообщение об успехе
mov ah,09h
mov dx,offset m_set
int 21h

;???
mov ah,31h
mov dx,offset prog_data
int 21h
.no_install_on:
;???
mov ah,07h
int 1ah

;???
mov ah,06h
mov ch,hrs
mov cl,min
mov dh,sec

int 1ah ;???
jnc .install_ok ;???

;Вывод собщения об ошибке
mov ah,09h
mov dx,offset m_set_error
int 21h

jmp .set_exit

.install_ok:
;====================================

;Успешная установка
mov ah,09h
mov dx,offset m_set
int 21h
.set_exit:
mov ax,4c00h
int 21h

;???
check_install proc
push ax
mov ah,0ffh ;???
xor al,al ;???
int 2fh ;???
add al,1 ;???
pop ax ;???
;Если ah == 0ffh, CF=1
;CF == 0 в противном случае
ret
check_install endp

;перевод в BCD
make_bcd proc
mov ax,[si]
and ax,0f0fh
shl al,4
or al,ah
ret
make_bcd endp

;перевод в ASCII
make_ascii proc
mov ah,al
and ah,0fh
shr al,4
or ax,3030h
ret
make_ascii endp

end begin


Спасибо большое

Обсуждение

давно
Старший Модератор
31795
6196
21.05.2010, 20:43
общий
это ответ
Здравствуйте, Мироненко Николай Николаевич.

Код с комментариями в приложении. Общий принцип работы. При запуске программы Вы должны использовать ключи: , и -новое время. Последний ключ ещё и запускает сам будильник.
В программе используются прерывание , функции: 06-установить будильник и 07. При установке будильника в КМОП-микросхему записывается значение: часов:минут:секунд. На аппаратном уровне проиисходит проверка текущего времени, и если совпадает, то вызывается программное прерывание , обработчик которого есть в коде(int_4a_code:). Это простейший биппер. Включает динамик и системный таймер(бит 0 - динамик, бит 1 - таймер).
Код:
in     al,61h
or al,03h
out 61h,al

Аналoгичный код, но с уже сброшеными битами служит для выключения таймера и динамика.
Команда out 42h,al - включает и выключает питание на динамик, а т.к. она расположена в цикле вместе с пустым циклом задержки .li: loop .li, то в динамике слышен звук .

Для контроля своего присутсвия в системе используется прерывание 2F, функция 0F, именно её перехватывает обработчик int_2f_code:, и если нашего резидента нет в памяти, то функцию 0F будет обрабатывать старый обработчик, который установила система или другая программа, до этого и соответсвенно будет установлен флаг СF.
Вроде всё. Вопросы задавайте в мини-форум.
Удачи!

Приложение:
.286
.model tiny

BEEP_DUR_INNER = 5000 ;интервалы для цыклов
BEEP_DUR_OUTTER = 0D000h ;

BEEP_TONE = 5 ;тон звука

MAX_HR = 24 ;максимально часов
MAX_MS = 60 ;максимально минут
.code
org 100h
begin:
jmp start

old_int_2fh dd ?

hrs dB ? ;часы
min dB ? ;минуты
sec dB ? ;секунды

int_4a_code:
in al,61h ;получаем регистр состояния контролера клавиатуры
push ax
or al,03h ;включаем динамик и таймер
out 61h,al ;записываем новое значение состояния


mov cx,BEEP_DUR_OUTTER ;внешний цикл
mov al,BEEP_TONE ;тональность звука
.lo:
out 42h,al ;бикаем - не бикаем

push cx
mov cx,BEEP_DUR_INNER ;цикл задержки
.li: loop .li
pop cx
loop .lo

pop ax ;востанавливаем старое значение состояния контролера клавиатуры
and al,11111100b ;выключаем таймер и динамик
out 61h,al ;устанавливаем старое значение

iret ;возврат изь прерывания

int_2f_code:
;контрольный код
cmp ah,0ffh
jne .int_2f_exit
mov al,ah
iret
.int_2f_exit:
;запускаем старый обработчик
jmp cs:old_int_2fh

;===================================================================================
;менюшка
prog_data:
;Строки
m_usage dB 0ah,0dh
dB '=============Usage:=============',0ah,0dh
dB '[alarm -c] - check current state',0ah,0dh
dB '[alarm -HH:MM:SS] - set alarm',0ah,0dh
dB '[alarm -x] - turn the alarm off',0ah,0dh,24h

m_not_active dB 'Alarm is not active',0ah,0dh,24h
m_state dB 'Alarm is set to '
m_hhmmss dB '00:00:00',0ah,0dh,24h
m_off dB 'Alarm has been turned off',0ah,0dh,24h
m_off_already dB 'Alarm has already been turned off',0ah,0dh,24h
m_set dB 'Alarm has been successfully set!',0ah,0dh,24h
m_set_error dB 'Alarm set error!',0ah,0dh,24h



start:

mov si,80h ;адрес командной строки передаваемой при старте программы

xor cx,cx ;обнуляем cx
mov cl,[si] ;длин ком.строки
add si,2 ;устанавливаем указатель на начало ком.строки

.arg_shrch:
jcxz .arg_out ;ноль выходим
mov al,[si] ;считываем символ
cmp al,'-' ;и сравниваем его с признаком ключа
jz .arg_found
inc si ;следующий символ
dec cx ;на один символ меньше
jmp .arg_shrch

;вывод
.arg_out:
mov ah,09h
mov dx,offset m_usage
int 21h

;Выход
mov ax,4c01h
int 21h


.arg_found:

inc si
mov al,[si]

;Преобразуем в строчные буквы
or al,20h

;Если с
cmp al,'c'
jne .chk_off


;==========Проверка==================
;Установлен ли?
call check_install
jc .installed
;Сообщение, если нет
mov ah,09h
mov dx,offset m_not_active
int 21h

;Выход
.exit_inst:
mov ax,4c00h
int 21h

.installed:
;Если да

mov ax,354ah ;получаем адрес обработчика
int 21h

mov di,bx ;дальнейшая работа будет с индексным регистром

mov al,es:[di-3] ;получаем часы
call make_ascii ;преобразование в АSCII

mov word ptr m_hhmmss,ax ;записываем в строку вывода

mov al,es:[di-2] ;минуты
call make_ascii ;преобразование в АSCII
mov word ptr m_hhmmss+3,ax ;см. выше

mov al,es:[di-1] ;секунды
call make_ascii ;преобразование в АSCII
mov word ptr m_hhmmss+6,ax ;см.выше

;Вывод на экран
mov ah,09h
mov dx,offset m_state
int 21h

jmp .exit_inst
;====================================

.chk_off:
;Если -х
cmp al,'x'
jne .chk_set

;==========Выключение================
call check_install
jc .inst_off

mov ah,09h
mov dx,offset m_off_already
int 21h

jmp .exit_inst
.inst_off:
mov ah,07h ;сбрасываем будильник
int 1ah ;

mov ax,354ah ;получить адрес обработчика
int 21h
mov di,bx ;запомнить в другом регистре

mov ah,35h ;получить адрес обработчика,
mov al,2fh ;должно быть 252fh
push ds
lds dx,[di-7] ;
int 21h

pop ds

mov ah,49h ;освобождение блока памяти
int 21h

;сообщение об успехе операции
mov ah,09h
mov dx,offset m_off
int 21h

;====================================
jmp .exit_inst
.chk_set:

call make_bcd ;переводим в другую систему
mov hrs,al ;устанавливаем время

add si,2
cmp byte ptr [si],':' ;должно быть " : "
je .cont; да, продолжаем
;нет выходим с ошибкой
mov ah,09h
mov dx,offset m_usage
int 21h

mov ax,4c01h
int 21h
.cont:

inc si ;тоже с минутами
call make_bcd ;
mov min,al ;

add si,2 ;
cmp byte ptr [si],':' ;
je .proceed ;

mov ah,09h
mov dx,offset m_usage
int 21h

mov ax,4c01h
int 21h

.proceed:
inc si;тоже с секундами
call make_bcd
mov sec,al
;==========Установка=================

;Проверка
call check_install
jc .no_install_on


;Запрет прерываний
cli

;Получаем адрес 2fh(почему)
mov ah,35h
mov al,2fh
int 21h

mov word ptr old_int_2fh,bx ;запоминаем старый обработчик
mov word ptr old_int_2fh+2,es ;

mov ah,25h ;ставим свой присутсвия в системе
mov al,2fh ;
mov dx,offset int_2f_code ;
int 21h

mov ah,25h ;ставим свой на таймер
mov al,4ah ;
mov dx,offset int_4a_code ;
int 21h
;Разрешение прерываний
sti

;устанавливаем будильник
mov ah,06h
mov ch,hrs
mov cl,min
mov dh,sec
int 1ah

;Сообщение об успехе
mov ah,09h
mov dx,offset m_set
int 21h

;запускаем резидент
mov ah,31h
mov dx,offset prog_data
int 21h
.no_install_on:
;сбрасываем будильник
mov ah,07h
int 1ah

;устанавливаем свой
mov ah,06h
mov ch,hrs
mov cl,min
mov dh,sec

int 1ah ;
jnc .install_ok ; СF=0 все нормально переходим

;Вывод собщения об ошибке
mov ah,09h
mov dx,offset m_set_error
int 21h

jmp .set_exit

.install_ok:
;====================================

;Успешная установка
mov ah,09h
mov dx,offset m_set
int 21h
.set_exit:
mov ax,4c00h
int 21h

;запускаем код контрольной проверки
check_install proc
push ax
mov ah,0ffh ;см. int_2f_code:
xor al,al
int 2fh
add al,1
pop ax
;Если ah == 0ffh, CF=1
;CF == 0 в противном случае
ret
check_install endp

;перевод в BCD
make_bcd proc
mov ax,[si]
and ax,0f0fh
shl al,4
or al,ah
ret
make_bcd endp

;перевод в ASCII
make_ascii proc
mov ah,al
and ah,0fh
shr al,4
or ax,3030h
ret
make_ascii endp

end begin
5
Спасибо Вам большое!!! Пока вопросов нет :)
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа