1. Заголовок или название темы должно быть информативным 2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE] 3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали! 4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора. 5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM! 6. Проверяйте программы перед тем, как выложить их на форум!!
Мелодия системного динамика, Все о системном динамике
Написать программу исполняющую на системном динамике песню про веселых гусей.
К сожалению, я пока не обладаю соответствующими навыками в программировании на ассемблере, но был бы очень признателен людям, которые откликнулись бы на эту тему и написали все что знаю о системном динамике, как к нему обращаться и работать. Как завершение этой темы, общими усилиями, хотелось бы написать процедуру биликанья динамика, т. е. в соответствии от введенной цифры он биликал бы соответствующую ноту. Вот.
; Таблица соответствия номеров полутонов обозначениям нот ; (в буквенной нотации), S - диез C equ 0 ;"до" D equ 2 ;"ре" E equ 4 ;"ми" F equ 5 ;"фа" G equ 7 ;"соль" A equ 9 ;"ля" B equ 11 ;"си" S equ 1 ;#
;--------------------------------------------------------------- ; play - воспроизведение ноты ; note = номер полутона ; octave = номер октавы ; len = длительность для размера 4/4 и заданного темпа
.code .startup ;воспроизведение ноты "ля" первой октавы play A,3,4
;выход mov ax,4C00h int 21h
;--------------------------------------------------------------- ; play_note - начинает воспроизведение ноты ; вход: ; al = номер полутона внутри октавы (0..11) ; ah = номер октавы (3 = первая фортепианная) ; выход: ; нет
play_note proc mov cl,ah ;cl = номер октавы cbw ;ax = номер полутона * 2 shl ax,1 lea bx,notes ;bx = @notes[номер полутона] add bx,ax mov al,0B6h ;загрузка упраляющего слова таймера out 43h,al ;(меандер на 3-м канале) mov ax,[bx] ;ax = notes[номер полутона] * 2^номер октавы shr ax,cl out 42h,al ;загрузка коэффициента деления в 3-й канал таймера mov al,ah out 42h,al in al,61h ;включение динамика or al,3 out 61h,al ret endp
;--------------------------------------------------------------- ; stop_note - выключает динамик ; вход: ; нет ; выход: ; нет
stop_note proc in al,61h and al,not 1 out 61h,al ret endp
;--------------------------------------------------------------- ; delay - задержка ; вход: ; cx = длительность задержки в 1/18 с (точнее - в 65536/1193180 с) ; выход: ; нет
delay proc xor ax,ax mov es,ax @@1: mov ax,es:[46Ch] @@2: hlt cmp ax,es:[46Ch] je @@2 loop @@1 ret endp
.const
; notes - таблица коэффициентов деления для октавы 0 (контроктавы) ; Коэффициенты деления для более высоких октав получаются ; путём умножения значений из таблицы на 2^(номер октавы)
КМА, следи за тем, что печатаешь. Я исправил.. Лопарь
Я тута помучился чуть-чуть, и вообщем сделал такую прикольную вещь. По возможности оставил комментарии, мало ли кому понадобиться. Только она играет "Веселую овечку Мери".
TITLE mary ;================= ;= сегмент стека = ;================= mary_stack SEGMENT PARA STACK 'stack' db 64 dup('stack') mary_stack ENDS ;================== ;= сегмент данных = ;================== mary_data SEGMENT PARA PUBLIC 'data' ; время задержки mary_time dw 6 dup (25), 50 dw 2 dup (25, 25), 50, 25, 25, 50 dw 12 dup (25), 100 ; цельная нота, это 100 (1 сек), половинная 50, 25 это четверть, и т. д. ;++++++++++++++++++++++ ; мелодия мери mary_freq dw 330, 294, 262, 293, 3 dup(330) ; 1-2 такт dw 3 dup(294), 330, 2 dup(392) ; 3-4 такт dw 330, 294, 262, 294, 4 dup (330) ; 5-6 такт dw 2 dup (294), 330, 294, 262, 0FFFFh ; 7-8 такт ; нота соответствуют частотам ; до 130,8 ; диез 138,6 ; ре 146,8 ; ми 164,8 ; диез 155,6 ; фа 174,8 ; соль 196 ; диез 185 ; ля 220 ; диез 207,7 ; си 246,9 ; ---------- ; до 261 ; диез 277,2 ; ре 293,7 ; диез 311,1 ; ми 329,6 ; фа 349,2 ; диез 370 ; соль 392 ; диез 415 ; ля 440 ; диез 464,2 ; cи 493,9 mary_data ENDS ;================ ;= сегмент кода = ;================ mary_code SEGMENT PARA PUBLIC 'code'
mary proc far assume CS: mary_code, DS: mary_data, SS: mary_stack push DS xor ax, ax ; обнуляем ax push ax ; DS:0000 по нему будем выходить в ОС
mov ax, mary_data ; явно определим сегмент данных mov DS, ax ; подготовим все для проигрыша звука, т. е. lea si, mary_freq ; загрузим в si массив мелодии call play ; запускаем процедуру play ret mary endp
; Процедра play проигрывает мелодию ; в регистре si должен находиться адрес массива мелодии play proc near push ax ; cохраняем регистры push di push si push bp @freq: mov di, [si] ; загружаем в di следующую ноту cmp di, 0FFFFh ; сравниваем, не конец ли? (0FFFFh признак окончания) je @end_play ; если конец, то заканчиваем проигрывать ; если нет, то воспроизведем звук mov bx, mary_time+bp call sound ; вызвав процедуру sound add si, 2 ; ставим указатель на следующую ноту add bp, 2 ; и соответственно на следующий такт jmp @freq ; прыгаем на следующий проигрыш ноты
@end_play: pop bp ; восстанавливаем регистры pop si pop di pop ax ret play endp
; процедура sound проигрывает звук ; в di соответствущая нота ; в bx задержка sound proc near push ax ; сохраним регистры push bx push cs push dx push di
mov al, 0BCh out 43h, al ; запишем в al значение таймера mov dx, 14h ; делитель времени mov ax, 4F33h ; 1331000 делить на частоту div di out 42h, al ; младший байт счетчика таймера mov al, ah out 42h, al in al, 61h mov ah, al or al, 3 ; включаем динамики out 61h, al @waits: ; делаем задержку mov cx, 10000 ; в 10 милисекунд loop $ dec bx ; пока не кончиться bx jnz @waits ; будем выводить звук mov al, ah out 61h, al ; восстанавливаем порт в начальное состояник
pop di ; восстановим регистры pop dx pop cx pop bx pop ax ret sound endp mary_code ENDS END mary