装配扬声器和等待中断无尽的睡眠
Assembly speaker and wait interrupt endless sleep
我正在编写一个在 PC 扬声器上播放音乐的汇编程序 (8086)。
一切正常,但我遇到了一个问题。程序在第 78 个音符处进入无尽睡眠(扬声器打开),无论它是什么音符。
我正在使用 86h function of 15 interrupt
。
那么为什么会出现无休止的睡眠,如何解决?
这是代码(真人快打主题):
;constants
TB equ 38636; 1.19MHz/30Hz
TC equ 34546; 1.19MHz/33Hz
TD equ 30811; 1.19MHz/37Hz
TE equ 27805; 1.19MHz/41Hz
TF equ 25909; 1.19MHz/44Hz
TG equ 23265; 1.19MHz/49Hz
TA equ 20727; 1.19MHz/55Hz
TH equ 18387; 1.19MHz/62Hz
TP equ 1;pause
;K end of melody
strophe1n equ 'ACADAEDCCECGCECGGHGCGDCFFAFCFCH'
strophe1o equ '3434344444444443333434433334343'
strophe1t equ '2222222222222222222222222222222'
strophe2n equ 'APAPAPAPGCAPAPAPAPGEAPAPAPAPGCAPAPAPAPAPAPA'
strophe2o equ '4040404045404040404440404040454040404040404'
strophe2t equ '2424242422242424242224242424222424284844484'
strophe3n equ 'AEACABACABGAEACABACABGAEACABACABGAEACGPGGPGAAPAA'
strophe3o equ '454545454544545454545445454545454454540440444044'
strophe3t equ '424242424424242424244242424242442424248488448848'
Progr segment
assume cs:Progr, ds:data, ss:stacky
interval:; waits DX:CX microseconds
mov ah,86h;
int 15h
ret
;here come notes every note set up its time and sleep
note:;0,5 sec
mov cx,7;
mov dx,41248;
call interval
ret
halfnote:;0,25sec
mov cx,3;
mov dx,53280;
call interval
ret
quarternote:;0,125sec
mov cx,1;
mov dx,58982;
call interval
ret
eighthnote:
mov cx,0;
mov dx,62455;
call interval
ret
turnon:;sets tone and turn on speaker
;setting up tone
mov ax,tone
mov dx,42h
out dx,al
mov al,ah
out dx,al
;turning speaker on
mov dx,61h
in al,dx;
or al,00000011B;
out dx,al;
ret
turnoff:;turning speaker off
mov dx,61h
in al,dx;
and al,11111100B;
out dx,al;
ret
play:
;simple switch for times
call turnon
cmp time,1
je whole
cmp time,2
je half
cmp time,4
je quarter
cmp time,8
je eighth
whole: call note;sleep for note time (while speaker is on) and then shuts up the speaker
jmp endplay
half: call halfnote
jmp endplay
quarter: call quarternote
jmp endplay
eighth: call eighthnote
jmp endplay
endplay:
call turnoff; turning speaker off
ret
exit:
mov ah,4ch
mov al,00h
int 21h;
;START--------------------------------------------------------------------
start: mov ax,data ;some start up
mov ds,ax
mov ax,stacky
mov ss,ax
mov sp,offset peak
mov si,0
melody:
lea bx,notes
mov dl,ds:[bx+si];dl = next note
cmp dl,'K'; if K then melody ends
je exit
;simple switch for notes
cmp dl,'A'
je A
cmp dl,'B'
je B
cmp dl,'C'
je C
cmp dl,'D'
je D
cmp dl,'E'
je E
cmp dl,'F'
je F
cmp dl,'G'
je G
cmp dl,'H'
je H
mov tone,TP
readoctave:
lea bx,octaves;reads next octave from array
mov cl,ds:[bx+si]
sub cl,'0'
shr tone,cl; double the tone octave times (tone = tone *2^octave)
lea bx,times;read next time from array
mov cl,ds:[bx+si]
sub cl,'0'
mov time,cl
call play;
inc si;;next index
jmp melody;play next note
;notes asignment
A: mov tone,TA
jmp readoctave
B: mov tone,TB
jmp readoctave
C: mov tone,TC
jmp readoctave
D: mov tone,TD
jmp readoctave
E: mov tone,TE
jmp readoctave
F: mov tone,TF
jmp readoctave
G: mov tone,TG
jmp readoctave
H: mov tone,TH
jmp readoctave
Progr ends
data segment
notes db strophe1n,strophe2n,strophe3n,'K';notes k means end of melody
octaves db strophe1o,strophe2o,strophe3o,'0';octaves, tone =(tone = frequency of note *2^octave)
times db strophe1t,strophe2t,strophe3t,'0';just times to play each note
tone dw 0
time db 0
data ends
stacky segment
dw 100h dup(0)
peak Label word
stacky ends
end start
我知道代码有点大,但我不知道问题出在哪里。
@编辑
也许数组大小太大但我不这么认为
@EDIT2
程序在第 78 个音符处失败,无论它是什么音符。
在 MS-DOS 中,不要尝试自己管理堆栈,除非您确切地知道自己在做什么。我唯一一次看到这样做是在内存非常关键的 TSR 应用程序中。
另请参阅:why must we initialize DS And ES registers in MS-DOS?
此外,256字节很小;请注意 所有 硬件中断处理程序可能会在您的程序 运行.
时占用您的堆栈份额
我建议您删除:
mov ax,stacky
mov ss,ax
mov sp,offset peak
和
stacky segment
dw 100h dup(0)
peak Label word
stacky ends
希望对您有所帮助。
原来
interval:
mov ah,86h;
int 15h
ret
因为 int 15h 86h 函数以某种方式失败,所以工作错误,
所以我写了自己的程序
interval:
mov ah, 0
int 1Ah ; actual time
mov bx,dx
delay:
mov ah, 0
int 1Ah
sub dx,bx
cmp di,dx
ja delay
ret
还有注释以其他方式定义它们的时间(现在在 di 寄存器中)例如:
note:;0,5 sec
mov di, 8
call interval
ret
halfnote:;0,25 sec
mov di, 4
call interval
ret
我正在编写一个在 PC 扬声器上播放音乐的汇编程序 (8086)。
一切正常,但我遇到了一个问题。程序在第 78 个音符处进入无尽睡眠(扬声器打开),无论它是什么音符。
我正在使用 86h function of 15 interrupt
。
那么为什么会出现无休止的睡眠,如何解决?
这是代码(真人快打主题):
;constants
TB equ 38636; 1.19MHz/30Hz
TC equ 34546; 1.19MHz/33Hz
TD equ 30811; 1.19MHz/37Hz
TE equ 27805; 1.19MHz/41Hz
TF equ 25909; 1.19MHz/44Hz
TG equ 23265; 1.19MHz/49Hz
TA equ 20727; 1.19MHz/55Hz
TH equ 18387; 1.19MHz/62Hz
TP equ 1;pause
;K end of melody
strophe1n equ 'ACADAEDCCECGCECGGHGCGDCFFAFCFCH'
strophe1o equ '3434344444444443333434433334343'
strophe1t equ '2222222222222222222222222222222'
strophe2n equ 'APAPAPAPGCAPAPAPAPGEAPAPAPAPGCAPAPAPAPAPAPA'
strophe2o equ '4040404045404040404440404040454040404040404'
strophe2t equ '2424242422242424242224242424222424284844484'
strophe3n equ 'AEACABACABGAEACABACABGAEACABACABGAEACGPGGPGAAPAA'
strophe3o equ '454545454544545454545445454545454454540440444044'
strophe3t equ '424242424424242424244242424242442424248488448848'
Progr segment
assume cs:Progr, ds:data, ss:stacky
interval:; waits DX:CX microseconds
mov ah,86h;
int 15h
ret
;here come notes every note set up its time and sleep
note:;0,5 sec
mov cx,7;
mov dx,41248;
call interval
ret
halfnote:;0,25sec
mov cx,3;
mov dx,53280;
call interval
ret
quarternote:;0,125sec
mov cx,1;
mov dx,58982;
call interval
ret
eighthnote:
mov cx,0;
mov dx,62455;
call interval
ret
turnon:;sets tone and turn on speaker
;setting up tone
mov ax,tone
mov dx,42h
out dx,al
mov al,ah
out dx,al
;turning speaker on
mov dx,61h
in al,dx;
or al,00000011B;
out dx,al;
ret
turnoff:;turning speaker off
mov dx,61h
in al,dx;
and al,11111100B;
out dx,al;
ret
play:
;simple switch for times
call turnon
cmp time,1
je whole
cmp time,2
je half
cmp time,4
je quarter
cmp time,8
je eighth
whole: call note;sleep for note time (while speaker is on) and then shuts up the speaker
jmp endplay
half: call halfnote
jmp endplay
quarter: call quarternote
jmp endplay
eighth: call eighthnote
jmp endplay
endplay:
call turnoff; turning speaker off
ret
exit:
mov ah,4ch
mov al,00h
int 21h;
;START--------------------------------------------------------------------
start: mov ax,data ;some start up
mov ds,ax
mov ax,stacky
mov ss,ax
mov sp,offset peak
mov si,0
melody:
lea bx,notes
mov dl,ds:[bx+si];dl = next note
cmp dl,'K'; if K then melody ends
je exit
;simple switch for notes
cmp dl,'A'
je A
cmp dl,'B'
je B
cmp dl,'C'
je C
cmp dl,'D'
je D
cmp dl,'E'
je E
cmp dl,'F'
je F
cmp dl,'G'
je G
cmp dl,'H'
je H
mov tone,TP
readoctave:
lea bx,octaves;reads next octave from array
mov cl,ds:[bx+si]
sub cl,'0'
shr tone,cl; double the tone octave times (tone = tone *2^octave)
lea bx,times;read next time from array
mov cl,ds:[bx+si]
sub cl,'0'
mov time,cl
call play;
inc si;;next index
jmp melody;play next note
;notes asignment
A: mov tone,TA
jmp readoctave
B: mov tone,TB
jmp readoctave
C: mov tone,TC
jmp readoctave
D: mov tone,TD
jmp readoctave
E: mov tone,TE
jmp readoctave
F: mov tone,TF
jmp readoctave
G: mov tone,TG
jmp readoctave
H: mov tone,TH
jmp readoctave
Progr ends
data segment
notes db strophe1n,strophe2n,strophe3n,'K';notes k means end of melody
octaves db strophe1o,strophe2o,strophe3o,'0';octaves, tone =(tone = frequency of note *2^octave)
times db strophe1t,strophe2t,strophe3t,'0';just times to play each note
tone dw 0
time db 0
data ends
stacky segment
dw 100h dup(0)
peak Label word
stacky ends
end start
我知道代码有点大,但我不知道问题出在哪里。
@编辑 也许数组大小太大但我不这么认为 @EDIT2 程序在第 78 个音符处失败,无论它是什么音符。
在 MS-DOS 中,不要尝试自己管理堆栈,除非您确切地知道自己在做什么。我唯一一次看到这样做是在内存非常关键的 TSR 应用程序中。
另请参阅:why must we initialize DS And ES registers in MS-DOS?
此外,256字节很小;请注意 所有 硬件中断处理程序可能会在您的程序 运行.
时占用您的堆栈份额我建议您删除:
mov ax,stacky
mov ss,ax
mov sp,offset peak
和
stacky segment
dw 100h dup(0)
peak Label word
stacky ends
希望对您有所帮助。
原来
interval:
mov ah,86h;
int 15h
ret
因为 int 15h 86h 函数以某种方式失败,所以工作错误,
所以我写了自己的程序
interval:
mov ah, 0
int 1Ah ; actual time
mov bx,dx
delay:
mov ah, 0
int 1Ah
sub dx,bx
cmp di,dx
ja delay
ret
还有注释以其他方式定义它们的时间(现在在 di 寄存器中)例如:
note:;0,5 sec
mov di, 8
call interval
ret
halfnote:;0,25 sec
mov di, 4
call interval
ret