Форум программистов, компьютерный форум, киберфорум
Assembler: DOS/Real Mode/16-bits
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.53/64: Рейтинг темы: голосов - 64, средняя оценка - 4.53
28 / 20 / 6
Регистрация: 19.11.2017
Сообщений: 91
TASM

Написание музыки на ассемблере и паузы между нотами

29.11.2019, 00:23. Показов 14110. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Есть такое задание: написать музыку на ассемблере. Но для того, чтобы звучало все адекватно, как песня, нужно расставить паузы между нотами. Длительность нот настроили, а паузы между нотами не знаем. Может есть какие-то частоты тишины там, я не знаю, которые не будут воспроизводиться. Вот код:
Assembler
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
DSEG SEGMENT
BEAT DB 8,4,4,10,4,4,8,4,4,4,4,4,4,4,4,8,4,4,4,4,8,4,4,4,4,4,4,4 ;длительность нот
FREQUENCY DW 2316,3091,3091,1000,2316,3895,2316,2316,3091,3091,2599,2063,3470,3470,2063,2316
DW 3091,3091,2316,3895,2918,2918,3895,3895,2599,2063,3470,3470,2063 ;длительность частот
MELODY DB 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, 0FFH; номер частоты нот
DSEG ENDS
 
SSEG SEGMENT STACK
db 256 dup(0)
SSEG ENDS
 
CSEG SEGMENT
assume cs:CSEG,ds:DSEG
start: mov ax,DSEG
mov ds,ax
 
;---инициализация
PORT_B EQU 61H
COMMAND_REG EQU 43H
LATCH2 EQU 42H
IN AL,PORT_B ;получаем текущий статус
OR AL,00000011B ;разрешаем динамик и таймер
OUT PORT_B,AL ;заменяем байт
MOV SI,0 ;инициализируем указатель
MOV AL,0B6H ;установка для канала 2
OUT COMMAND_REG,AL ;посылаем в командный регистр
;---смотрим ноту, получаем ее частоту и помещаем в канал 2
NEXT_NOTE:
LEA BX,MELODY ;берем смещение для мелодии
MOV AL,[BX][SI] ;берем код n-ой ноты строки
CMP AL,0FFH ;проверка на конец строки
JE NO_MORE ;если конец то на выход
CBW ;переводим в слово
;---получение частоты
MOV BX,OFFSET FREQUENCY ;смещение таблицы частот
DEC AX ;начинаем отсчет с 0
SHL AX,1 ;умножаем на 2, т.к. слова
MOV DI,AX ;адресуем через DI
MOV DX,[BX][DI] ;получаем частоту из таблицы
;начинаем исполнение ноты
MOV AL,DL ;готовим младший байт частоты
OUT LATCH2,AL ;посылаем его
MOV AL,DH ;готовим старший байт частоты
OUT LATCH2,AL ;посылаем его
;---создание цикла задержки
MOV AH,0 ;номер функции чтения счетчика
INT 1AH ;получаем значение счетчика
MOV BX,OFFSET BEAT ;смещение таблицы длин
MOV CL,[BX][SI] ;берем длину очередной ноты
MOV CH,0
MOV BX,DX ;берем младшее слово счетчика
ADD BX,CX ;определяем момент окончания
STILL_SOUND:
INT 1AH ;берем значение счетчика
CMP DX,BX ;сравниваем с окончанием
JNE STILL_SOUND ;неравны-продолжаем звук
INC SI ;переходим к следующей ноте
JMP NEXT_NOTE ;
;---завершение
NO_MORE:
IN AL,PORT_B ;полчаем статус порта В
AND AL,0FCH ;выключаем динамик
OUT 61H,AL ;заменяем байт
 
MOV AX,4C00H
INT 21H
CSEG ENDS
END START
Заранее благодарю за ответы!
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.11.2019, 00:23
Ответы с готовыми решениями:

Интервал между нотами.
Составить программу которая бы реализовала следующий алгоритм: по введённым названиям двух нот (до ре ми фа соль ля си) определить...

25к - написание музыки
Здравствуйте! Помогите подобрать ПК. Сам в железе понимаю немного, поэтому решил обратиться к компетентным людям :) Занимаюсь написанием...

Создание паузы между циклом
всем привет, необходима небольшая помощь. Нужно сделать так, чтобы цикл выполнялся каждые 5 секунд, а сама программа работала. Пробовал...

6
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8655 / 4491 / 1669
Регистрация: 01.02.2015
Сообщений: 13,899
Записей в блоге: 12
29.11.2019, 00:28
Лучший ответ Сообщение было отмечено Andymit как решение

Решение

Отключать динамик на время паузы кодом из строк 61-63, а потом обратно включать.
1
28 / 20 / 6
Регистрация: 19.11.2017
Сообщений: 91
29.11.2019, 01:23  [ТС]
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
Отключать динамик на время паузы кодом из строк 61-63, а потом обратно включать.
Спасибо!
0
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
29.11.2019, 18:51
Вот так выглядит Ваша программа после небольшой редакции.
Звуки издаёт, правда, непонятные

Assembler
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
DSEG SEGMENT
BEAT DB 8,4,4,10,4,4,8,4,4,4,4,4,4,4,4,8,4,4,4,4,8,4,4,4,4,4,4,4 ;длительность нот
FREQUENCY DW 2316,3091,3091,1000,2316,3895,2316,2316,3091,3091,2599,2063,3470,3470,2063,2316
          DW 3091,3091,2316,3895,2918,2918,3895,3895,2599,2063,3470,3470,2063,-1 ;длительность частот, -1 - конец данных
PORT61DATA DB 0
DSEG ENDS
 
SSEG SEGMENT STACK
    db 256 dup(0)
SSEG ENDS
 
PORT_B EQU 61H
COMMAND_REG EQU 43H
LATCH2 EQU 42H
 
    CSEG SEGMENT
    assume cs:CSEG,ds:DSEG
 
 
PLAYNOTE: 
    CMP  AX,0
    JZ   PLAYPAUSE
    PUSH AX
    MOV AL,0B6H
    OUT COMMAND_REG,AX
    POP AX
    OUT LATCH2,AL
    MOV AL,AH
    OUT LATCH2,AL
    IN  AL,PORT_B
    OR  AL,3
    OUT PORT_B,AL
PLAYPAUSE:
    PUSH ES
    MOV AX,0
    MOV ES,AX
    JCXZ WT2
wt0:    mov  ax,es:[46Ch]
wt1:    push ax
    mov  ah,1
    int 16h
    jnz EXITPROG2
    pop  ax
    cmp  ax,es:[46Ch]
    jz   wt1
    loop wt0
WT2:    POP  ES
    in   al,port_b
    and  al,0FCh
    out  port_b,al
    RET
 
start:  mov ax,DSEG
    mov ds,ax
    IN AL,PORT_B ;получаем текущий статус
    MOV PORT61DATA,AL
    MOV SI,OFFSET FREQUENCY ;инициализируем указатель
    MOV BP,OFFSET BEAT
;---смотрим ноту, получаем ее частоту
NEXT_NOTE:
;---получение частоты
    LODSW
    CMP AX,-1
        JZ  EXITPROG
;---ПОЛУЧАЕМ ДЛИТЕЛЬНОСТЬ НОТЫ
        MOV CH,0  
        MOV CL,DS:[BP]
        INC BP
    add cx,cx
    add cx,cx
        CALL PLAYNOTE
    JMP  NEXT_NOTE
EXITPROG:   
    MOV AX,4C00H
    INT 21H
 
EXITPROG2:
    mov al,PORT61DATA
    out PORT_B,al ; speaker off
    mov ah,0 ; чтение кода нажатой клавиши
    int 16h
    jmp EXITPROG
 
CSEG ENDS
END START
Добавлено через 5 минут
Вот пример работающей программы с мелодией
Обратите внимание, что здесь закодированы частоты нот,
а не значения таймера

Assembler
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
; Программа из книги Leo Scanlon Лео Скэнлон
; персональные ЭВМ IBM PC XT программирование на языке ассемблера
;
; Индюк в соломе ...
 
 
    .286
    .model small
    .code
    assume ds: _text
    org 100h
start:  jmp beg
port61  db 0
;ПРИМЕР 8.4. ТАБЛИЦЫ ДАННЫХ ДЛЯ МЕЛОДИИ "ИНДЮК В СОЛОМЕ".
freq    DW 294,262,233,233,262,233,175,147,156 ;Линейка 1
    DW 175,196,175,147,175,233,262,294,294 ;Линейка 2
    DW 294,262,233,262
    DW 294,262,262,294,262,233,233,262 ;Линейка 3
    DW 233,175,147,156
    DW 175, 196,175,147,175,233,262,294,349 ;Линейка 4
    DW 349,294,233,262
    DW 294,262,233,294,349,294,349,349 ;Линейка 5
    DW 294,349,294,349,311,392,311,392,392 ;Линейка 6
    DW 311,392,311,392,466,466,349,349 ;Линейка 7
    DW 294,294,262,233,262,294,349,392 ;Линейка 8 
    DW 349,294,233,262,294,262,233,-1
 
delay   Db 2 DUP(12),25,6 DUP(12)
    Db 4 DUP(12),25,2 DUP(12),2 DUP(25)
    Db 4 DUP(12)
    Db 3 DUP(25),2 DUP(12),25,6 DUP(12)
    Db 4 DUP(12),25,2 DUP(12),2 DUP(25)
    Db 4 DUP(12)
    Db 2 DUP(25),50,12,25,12,2 DUP(25)
    Db 12,25,12,50,2 DUP(12,25),25
    Db 12,25,12,50,4 DUP(25)
    Db 3 DUP(25),3 DUP(12),25,5 DUP(12)
    Db 3 DUP(25)
 
; Эта процедура заставляет динамик издать тон заданной частоты и заданной длительности
; Перед вызовом загрузите частоту в регистр DI и длительность в регистр CX
; Значения всех регистров сохраняются
 
sound:  pusha
    mov al,0B6h
    out 43h,al
    mov dx, 14h   ; freq=1331000 Hz
    mov ax, 4f38h
    div di
    out 42h,al
    mov al,ah
    out 42h,al
    in al,61h
    mov ah,al
    mov port61,al
    or al,3  ; speaker on
    out 61h,al
    push es
    push ax
    mov  ax,0
    mov  es,ax
wt0:    mov  ax,es:[46Ch]
wt1:    push ax
    mov  ah,1
    int 16h
    jnz ex
    pop  ax
    cmp  ax,es:[46Ch]
    jz   wt1
    loop wt0
    pop  ax
    pop  es
    mov al,ah
    out 61h,al ; speaker off
    popa
    ret
 
beg:    push cs
    pop ds
    mov si,offset freq
    mov bp,offset delay
nextnote:
    lodsw
    cmp ax,-1
    jz dosexit
    add ax,ax ; freq=freq*2
    mov di,ax
    mov al,ds:[bp]
    mov ah,0
    shr ax,2  ; delay=delay/4
    mov cx,ax
    call sound
    inc bp
    jmp nextnote
dosexit:mov ax,4C00h
    int 21h
ex: mov al,port61
    out 61h,al ; speaker off
    mov ah,0
    int 16h
    jmp dosexit
    end start
Добавлено через 2 часа 12 минут
Извините - поторопился. Вот рабочий вариант Вашей программы

Assembler
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
    DSEG SEGMENT
BEAT DB 8,4,4,10,4,4,8,4,4,4,4,4,4,4,4,8,4,4,4,4,8,4,4,4,4,4,4,4 ;длительность нот
FREQUENCY DW 2316,3091,3091,1000,2316,3895,2316,2316,3091,3091,2599,2063,3470,3470,2063,2316
    DW 3091,3091,2316,3895,2918,2918,3895,3895,2599,2063,3470,3470,2063,-1 ;длительность частот
    DSEG ENDS
 
    SSEG SEGMENT STACK
    db 256 dup(0)
    SSEG ENDS
 
    CSEG SEGMENT
    assume cs:CSEG,ds:DSEG
start: mov ax,DSEG
    mov ds,ax
 
;---инициализация
PORT_B EQU 61H
COMMAND_REG EQU 43H
LATCH2 EQU 42H
    MOV BP,offset beat ;инициализируем указатель
    mov SI,offset frequency
    MOV AL,0B6H ;установка для канала 2
    OUT COMMAND_REG,AL ;посылаем в командный регистр
;---смотрим ноту, получаем ее частоту и помещаем в канал 2
NEXT_NOTE:
    lodsw
    CMP AX,-1 ;проверка на конец строки
    JE NO_MORE ;если конец то на выход
    MOV DX,AX ;
    cmp ax,0  ; если AX=0, то сделать паузу
    jz playpause
;начинаем исполнение ноты
    push ax
    mov al,0B6h
    out command_reg,al
        pop ax
    MOV AL,DL ;готовим младший байт частоты
    OUT LATCH2,AL ;посылаем его
    MOV AL,DH ;готовим старший байт частоты
    OUT LATCH2,AL ;посылаем его
    in al,port_b ; включить динамик
    or al,3
    out port_b,al
;---создание цикла задержки
playpause:
    MOV AH,0 ;номер функции чтения счетчика
    INT 1AH ;получаем значение счетчика
    MOV CL,ds:[bp] ;берем длину очередной ноты
    MOV CH,0
    inc bp
    MOV BX,DX ;берем младшее слово счетчика
    ADD BX,CX ;определяем момент окончания
STILL_SOUND:
    push ax
    mov ah,1 ; опрос состояния клавиатуры
    int 16h
    jnz stopexec
    pop ax
    INT 1AH ;берем значение счетчика
    CMP DX,BX ;сравниваем с окончанием
    JNE STILL_SOUND ;неравны-продолжаем звук
        in al,port_b ; выключить динамик
    and al,0FCh
    out port_b,al   
    JMP NEXT_NOTE ;
;---завершение
NO_MORE:
    MOV AX,4C00H
    INT 21H
stopexec:
        in al,port_b ; выключить динамик
    and al,0FCh
    out port_b,al   
    mov ah,0     ; получить код клавиши
    int 16h
    jmp no_more
    CSEG ENDS
END START
2
28 / 20 / 6
Регистрация: 19.11.2017
Сообщений: 91
01.12.2019, 19:20  [ТС]
qbfan, Спасибо
0
0 / 0 / 0
Регистрация: 07.12.2021
Сообщений: 1
07.12.2021, 19:54
Andymit, Здравствуйте! Помогите, пожалуйста с одним вопросом. У меня лаб.работа горит и не могли бы объяснить как запустить программу, которые вы обсуждали в 2017г? Написание музыки на ассемблере и паузы между нотами
0
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
08.12.2021, 13:36
Не ставится DosBox или в чём проблема ?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
08.12.2021, 13:36
Помогаю со студенческими работами здесь

Паузы между проигрыванием wav файлов
Добрый день ,есть загвоздка с воспроизведением звуковых файлов ,воспроизводя поочередно их ,образуется довольно заметная пауза : ...

создать паузы между запросами в AnyEvent::HTTP
Здравствуйте! Есть следующий псевдокод (выкачиваются страницы): for my $url (@urls) { http_get $url, $headers, sub { ... } } ...

Как делать паузы между запросами в cURL PHP?
Подскажите, как делать паузы между запросами в cURL? Немного поясню: у меня есть код, который парсит дату регистрации пользователя...

Добавление паузы между вызовами метода (с помощью класса Timer)
Есть кнопка private void StartPause_btn_Click(object sender, EventArgs e) { } Которая должна...

Написание сервиса для фоновой музыки в приложении под Android(Java)
Товарищи, в данный момент столкнулся с одной из многих проблем на моём жизненном пути. Хотелось бы подробно узнать о секретах работы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru