如何在ASM 8086中演奏和弦?

时间:2015-03-20 14:31:29

标签: audio assembly timer x86-16 sound-synthesis

我想知道在装配时播放超过1个音符的最佳方法是什么。 如果可以,请添加一个解释您的答案的程序。 谢谢!

1 个答案:

答案 0 :(得分:2)

橙色,下一个代码是很久以前在EMU8086和Windows XP(它当时运行)的程序。现在我有Windows 8 64位,它不再运行。我会给你代码,因为它可以帮助你。所有的名称和评论都是西班牙语,因为我是costarrican,但汇编程序代码是通用的(谷歌翻译将帮助你):

.model small
.stack 100h
.data

;----------------------------------------------------------------------------

MENSAJEPLAY    DB '                       PROYECTO ® PIANO ¯',13,10
               DB 13,10
               DB '            LAS TECLAS DE LAS NOTAS VAN EN EL ORDEN SIGUIENTE:',13,10
               DB 13,10
               DB '                        2  3     5  6  7' ,13,10
               DB '                      q  w  e  r  t  y  u',13,10,13,10
               DB 13,10
               DB '                        s  d     g  h  j' ,13,10
               DB '                      z  x  c  v  b  n  m',13,10,13,10
               DB '                       PARA TERMINAR PRESIONE ESC','$'

;----------------------------------------------------------------------------

.code

TONO MACRO NUMERO               ;Esta macro recibe el tono
        MOV     BX,NUMERO       ;y manda a llamar a los procedimientos
        CALL    BOCINA
ENDM

;----------------------------------------------------------------------------

CLRSCR PROC
;Limpia la pantalla
        MOV     AH,6
        XOR     AL,AL
        XOR     CX,CX
        MOV     DX,184FH
        MOV     BH,13
        INT     10H
        RET
ENDP

;----------------------------------------------------------------------------

BocinaOn  PROC                  ;Activa la bocina
        IN      AL, 61h
        OR      AL, 11B
        OUT     61h, AL
        RET
BocinaOn  ENDP

;----------------------------------------------------------------------------

BocinaOff  PROC                 ;Desactiva la bocina
        IN      AL, 61h
        AND     AL, 11111100b
        OUT     61h, AL
        RET
BocinaOff  ENDP

;----------------------------------------------------------------------------

Ajustar  PROC                  ;Ajusta la bocina con la frecuencia dada
        PUSH    BP
        MOV     BP, SP
        MOV     DX, 18      
        MOV     AX, 13353   
        MOV     BX, [BP + 4]
        DIV     BX
        MOV     BX, AX  
        MOV     AL, 0B6h
        OUT     43h, AL
;ENVIAR AL PUERTO LA FRECUENCIA EN DOS BYTES POR SEPARADO.
        MOV     AX, BX
        OUT     42h, AL ;ENVIA PRIMER BYTE. (PUERTO PARALELO = 378H)
        MOV     AL, AH
        OUT     42h, AL ;ENVIA SEGUNDO BYTE. (PUERTO SERIAL = 3F8H)
        POP     BP
        RET
Ajustar  ENDP

;----------------------------------------------------------------------------

Suena proc                      ;Activa la bocina y coloca el nombre de
        CALL bocinaON           ;la tecla.
        MOV     AX,40H
        MOV     ES,AX
        MOV     DX,ES:[006EH]
        MOV     AX,ES:[006CH]
        ADD     AX,7
        ADC     DX,0            ;Se le suma 7 unidades a ese valor
CLIC:
        CMP     DX,ES:[006EH]   ;Y se compara hasta que sean iguales
        JB      FINI            ;Pasando por un ciclo, cuando llegen
        JA      CLIC            ;a ser iguales se sale del ciclo y
        CMP     AX,ES:[006CH]
        JA      CLIC
FINI:
        CALL    BocinaOff       ;Se desconecta la bocina y regresa.
        RET
Suena endp

;----------------------------------------------------------------------------

Bocina proc                     ;Este procedimiento guarda AX y BX en
        PUSH    BX              ;la pila para no perder su valor, con
        MOV     AX, BX          ;esto llama a ajusta y a suena
        PUSH    AX
        CALL    Ajustar         ;Pone la frecuencia en el puerto.
        POP     AX
        POP     BX
        CALL    SUENA           ;Activa el speaker y lo desactiva.
        ret
Bocina endp

;----------------------------------------------------------------------------
;CONVERTIR A MINUSCULA SI ERA MAYUSCULA

MINUSCULA PROC
        CMP AL, 65    ;'A'
        JB  CONTINUAR ;SI LA TECLA ES MENOR QUE LA 'A' NO HACE NADA
        CMP AL, 90    ;'Z'
        JA  CONTINUAR ;SI LA TECLA ES MAYOR QUE LA 'Z' NO HACE NADA
        ADD AL, 32    ;Convierte may£scula en min£scula.
     CONTINUAR:
        RET
MINUSCULA ENDP

;----------------------------------------------------------------------------
;CAPTURA LA TECLA CON LA NOTA QUE EL USUARIO DESEA.

TECLA PROC
        MOV     AH,8            ;Si la hay, obtiene la nota
        INT     21H
        CALL    MINUSCULA
        RET
TECLA ENDP
;----------------------------------------------------------------------------
;Cicla el programa hasta que el usuario presione la tecla ESC.
;El procedimiento reacciona a las teclas indicadas en el segmento de datos.
;Cualquier otra tecla es ignorada.
;La tecla presionada es convertida a min£scula, ya que la tabla ASCII
;trata distinto unas de otras.
;Despu‚s de que cada tecla es presionada, el ciclo vuelve al inicio y
;se repite.
;Si la tecla presionada corresponde a una nota musical, el c¢digo
;correspondiente es enviado al parlante.

SPEAKER PROC
COMIENZA:
        CALL    TECLA
        CMP     AL,'q'   ;DO alto
        JNE     S1       ;SI NO ES LA TECLA ESPERADA, SALTA PARA VERIFICAR LA SIGUIENTE.
        TONO    523      ;SI ES LA TECLA ESPERADA, GENERA EL SONIDO CORRESPONDIENTE
        JMP     COMIENZA ;DESPUES DEL SONIDO REINICIA PARA ESPERAR OTRO SONIDO.
S1:     CMP     AL,'w'   ;RE alto
        JNE     S2
        TONO    587
        JMP     COMIENZA
S2:     CMP     AL,'e'   ;MI alto
        JNE     S3
        TONO    659
        JMP     COMIENZA
S3:     CMP     AL,'r'   ;FA alto
        JNE     S4
        TONO    698
        JMP     COMIENZA
S4:     CMP     AL,'t'   ;SOL alto
        JNE     S5
        TONO    784
        JMP     COMIENZA
S5:     CMP     AL,'y'   ;LA alto
        JNE     S6
        TONO    880
        JMP     COMIENZA
S6:     CMP     AL,'u'   ;SI alto
        JNE     S8
        TONO    988
        JMP     NOSALTO1
SALTO1:
   JMP COMIENZA
NOSALTO1:
        JMP     COMIENZA
S8:     CMP     AL,'2'   ;DO# alto
        JNE     S9
        TONO    554
        JMP     COMIENZA
S9:     CMP     AL,'3'   ;RE# alto
        JNE     S10
        TONO    622
        JMP     COMIENZA
S10:    CMP     AL,'5'   ;FA# alto
        JNE     S11
        TONO    740
        JMP     COMIENZA
S11:    CMP     AL,'6'   ;SOL# alto
        JNE     S12
        TONO    830
        JMP     COMIENZA
S12:    CMP     AL,'7'   ;SIb alto
        JNE     S13
        TONO    923
        JMP     COMIENZA
S13:    CMP     AL,'z'   ;DO bajo
        JNE     S14
        TONO    261
        JMP     COMIENZA
S14:    CMP     AL,'x'   ;RE bajo
        JNE     S15
        TONO    293
        JMP     COMIENZA
S15:    CMP     AL,'c'   ;MI bajo
        JNE     S16
        TONO    329
        JMP     NOSALTO2
SALTO2:
   JMP SALTO1
NOSALTO2:
        JMP     COMIENZA
S16:    CMP     AL,'v'   ;FA bajo
        JNE     S17
        TONO    349
        JMP     COMIENZA
S17:    CMP     AL,'b'   ;SOL bajo
        JNE     S18
        TONO    392
        JMP     COMIENZA
S18:    CMP     AL,'n'   ;LA bajo
        JNE     S19
        TONO    466
        JMP     COMIENZA
S19:    CMP     AL,'m'   ;SI bajo
        JNE     S20
        TONO    498
        JMP     COMIENZA
S20:    CMP     AL,'s'   ;DO# bajo
        JNE     S21
        TONO    277
        JMP     COMIENZA
S21:    CMP     AL,'d'   ;RE# bajo
        JNE     S22
        TONO    311
        JMP     COMIENZA
S22:    CMP     AL,'g'   ;FA# bajo
        JNE     S23
        TONO    370
        JMP     COMIENZA
S23:    CMP     AL,'h'   ;SOL# bajo
        JNE     S24
        TONO    415
        JMP     COMIENZA
S24:    CMP     AL,'j'   ;SIb bajo
        JNE     S25
        TONO    515
        JMP     COMIENZA
S25:    CMP     AL,27 ;27 = tecla ESC (terminar).
        JNE     SALTO2
        RET
SPEAKER ENDP

;----------------------------------------------------------------------------

MENSAJE PROC
        MOV     AH,9
        LEA     DX,MENSAJEPLAY
        INT     21H
        RET
MENSAJE ENDP

;----------------------------------------------------------------------------

EMPIEZA:
        MOV     AX, @data         ;se mandan llamar todos los
        MOV     DS, AX            ;procedimientos
        CALL    CLRSCR            ;Limpiar pantalla.
        CALL    MENSAJE           ;Despliega la explicaci¢n del programa.
        CALL    SPEAKER           ;Sonidos.
        MOV     AX, 4C00H
        INT     21H

;----------------------------------------------------------------------------

END EMPIEZA

它的作用是向您显示按键以使音符发声。您可以在EMU8086中打开并运行它,但由于Windows 8,扬声器中断的行为很奇怪。

Orange刚编辑了这个问题,现在他想要同时播放音符。好吧,我的代码没有这样做,它一次只播放一个音符。要同时播放两个或多个音符,我们将要求执行该方式的线程或进程。

我不确定汇编程序能做到这一点,甚至不确定是否允许由中断控制的发言人这样做。这是因为称为“重入”的东西,或类似的东西,它指的是当中断在执行时执行时引起的问题,通常程序在发生时停止。