为什么这首歌在组装中一直没有播放?

时间:2016-04-05 03:10:10

标签: assembly 16-bit

我参加了一个介绍性的集会课程,对于最后的项目,我们必须制作一个节日生日快乐的节目。

问题是程序播放歌曲的中途(到第13个音符),然后停止播放。我已经尝试过所有尝试修复它的东西,我不知道它为什么不能正常工作。我尝试改变代码,改变循环的工作方式,改变哪些寄存器保存不同的值,但似乎没有任何工作。我看了调试,我看不到任何与众不同的东西。这是该程序的代码:

;data segment

dseg      segment para 'data'
    ;hex value for each note to send to port 42
    NOTES DW 11CAh,11CAh,0FDAh,11CAh,0D5Ah,0E1Fh,11CAh,11CAh
          DW 0FDAh,11CAh,0BE3h,0D5Ah,11CAh,11CAh,08E9h,0A97h
          DW 0D5Ah,0E1Fh,0FDAh,0A00h,0A00h,0A97h,0D5Ah,0BE3h,0D5Ah,"$"

    ;duration for each note
    DUR DB 1d,1d,2d,2d,2d,4d,1d,1d,2d,2d,2d
        DB 4d,1d,1d,2d,2d,2d,2d,6d,1d,1d,2d,2d,2d,4d    

dseg      ends

;----------------------------------------------------------------------
;code segment
cseg      segment para 'code'

main    proc far               ;this is the program entry point
    assume cs:cseg, ds:dseg, ss:sseg 
    mov  ax,dseg           ;load the data segment value
    mov  ds,ax             ;assign value to ds

    MOV AL, 0B6h
    OUT 43h, AL     ;output whats in AL to port 43h
    MOV SI, OFFSET NOTES    ;moves the address of the first note into SI
    MOV DI, OFFSET DUR  ;moves the address of the first duration into DI
    SUB BX, BX      ;clears BX
    SUB DX, DX      ;clears DX
    SUB CX, CX      ;cleasr CX
PLAY:   NOP
    MOV DX, [SI]        ;moves the frequency and divider for the note into DX
    CMP DX, "$"     
    JE EXIT         ;if at end of notes jump to exit
    MOV BL, [DI]        ;moves the number of times delay is called into BL
    CALL TONE       ;plays the note for the duration
    INC SI          ;move to next note
    INC DI          ;moves to next duration
    JMP PLAY        ;loop back to PLAY if there are still notes
EXIT:   NOP


      mov  ah,4Ch            ;set up interupt
      int  21h               ;Interupt to return to DOS

main      endp


TONE PROC 

    SUB AX, AX      ;clears ax
    MOV AL, DL      ;sets up the frequency for the tone
    OUT 42h, AL     ;output whats in AL to port 42h
    MOV DL, 0       ;use to compare to BL
    MOV AL, DH      ;divider for the tone smaller value = higher pitch
    OUT 42h, AL
    IN AL, 61h      ;input the contents of port 61h into AL
    MOV AH, AL      ;preserve contents of AL
    OR AL, 00000011b    ;uses mask to change the bits that we need
    OUT 61h, AL     ;outputs the changed bits back into the port to start tone
AGAIN:  NOP         ;loops 1/2 second delay for times needed
    CALL DELAY
    DEC BL
    CMP BL, DL      ;compares value in bl to 0
    JNE AGAIN       ;loops delay until bl is 0
    MOV AL, AH
    OUT 61h, AL     ;turns off tone with preserved contents from port 61h
    CALL DELAY_TWO      ;adds delay between notes
    RET

TONE ENDP

DELAY PROC NEAR     ;half second delay

    PUSH AX     ;preserve value in ax in stack
    MOV CX, 33156   ;delays for half second
WAITF:  NOP
    IN AL, 61h  ;read port 61
    AND AL, 10h ;gives 0001 0000 check PB4
    CMP AL, AH
    JE WAITF    ;jump to WAITF if AL is equal to AH
    MOV AH, AL  ;makes both AL and AH contain same number
    LOOP WAITF  ;continue until CX is 0
    POP AX  
    RET

DELAY ENDP

DELAY_TWO PROC NEAR ;small delay between notes

    PUSH AX     ;need value in ax for TONE so save it
    MOV CX, 331
WAITO:  NOP
    IN AL, 61h
    AND AL, 10h
    CMP AL, AH
    JE WAITO
    MOV AH, AL
    LOOP WAITO
    POP AX      ;get back ax value once delay is done
    RET

DELAY_TWO ENDP


cseg      ends
      end     main           ;Program exit point

我们只使用16位汇编。可能还有其他定时器和制作音调的方法,但我们必须这样做,使用程序中使用的端口。另外,我使用DOSBox来运行.exe,播放时听起来有点不对。

非常感谢任何帮助。

0 个答案:

没有答案