如何在 ASM 8086 中演奏和弦?

How to play chords in ASM 8086?

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

O运行ge,下一个代码是很久以前用EMU8086和Windows XP(当时运行)制作的程序。现在我有 Windows 8 个 64 位,但它不再 运行。我会给你代码,因为它可能对你有帮助。所有的名字和评论都是西班牙语,因为我是哥斯达黎加人,但是汇编代码是通用的(google t运行slator 会帮你的):

.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.

,扬声器中断行为很奇怪

O运行ge 刚刚编辑了问题,现在他想同时播放音符。好吧,我的代码不会那样做,它一次播放一个音符。对于同时播放两个或更多音符,我们需要以这种方式执行的线程或进程。

我不确定汇编程序是否可以做到这一点,甚至不确定是否允许由中断控制的扬声器这样做。这是因为有一个叫"reentrancy"之类的东西,指的是在已经执行的时候执行中断导致的问题,通常是程序在中断的时候就挂了。