Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 组件8086-DOSBOX-如何产生蜂鸣音?_Assembly_X86_Dos_X86 16_Dosbox - Fatal编程技术网

Assembly 组件8086-DOSBOX-如何产生蜂鸣音?

Assembly 组件8086-DOSBOX-如何产生蜂鸣音?,assembly,x86,dos,x86-16,dosbox,Assembly,X86,Dos,X86 16,Dosbox,我正在组装一个“西蒙”游戏。每当按钮打开时,我需要发出嘟嘟声,嘟嘟声应该彼此不同。 谢谢您可以使用保持设计简单。 扬声器可以让你播放不同频率的方波,但这更复杂 扬声器只是一个电磁铁,当电流流过时,它会被拉回,否则它会保持在默认位置。 通过前后移动扬声器,可以产生声波 可以手动或使用的频道2移动扬声器。 端口61h的位0控制扬声器源(0=手动,1=PIT),使用PIT时,同一端口的位1为“扬声器启用”位(不使用PIT时为扬声器“位置”) 以下是缺少手动驱动部分的示意图(由此可知): PIT通过端

我正在组装一个“西蒙”游戏。每当按钮打开时,我需要发出嘟嘟声,嘟嘟声应该彼此不同。 谢谢

您可以使用保持设计简单。
扬声器可以让你播放不同频率的方波,但这更复杂

扬声器只是一个电磁铁,当电流流过时,它会被拉回,否则它会保持在默认位置。
通过前后移动扬声器,可以产生声波

可以手动或使用的频道2移动扬声器。
端口61h的位0控制扬声器源(0=手动,1=PIT),使用PIT时,同一端口的位1为“扬声器启用”位(不使用PIT时为扬声器“位置”)

以下是缺少手动驱动部分的示意图(由此可知):

PIT通过端口40h-43h进行控制,我们将使用模式3(方波发生器)设置,每次两个字节的分频器都进行设置。
PIT有一个运行频率约为1.193180 MHz的振荡器,分频器用于控制方波的周期。
不涉及内部构件:在PIT振荡器的每个刻度处,加载的分压器减小。方波的周期等于凹坑将分频器减小到零所需的时间

产生声音只需使用所需的分频器对PIT进行编程并启用扬声器即可。
稍后,我们需要禁用它。
一种简单的方法是使用每秒18.2次的

通过在第一次播放声音时将持续时间保存在变量中,在int 1ch的每一个滴答声时将其递减,并在计数为零时禁用扬声器,可以控制嘟嘟声的持续时间

使用int 1ch需要设置功能(
beep_setup
)和拆卸功能(
beep_teardown

特别感谢您修复了原始代码中的一个缺陷

您可以使用
beep\u play
播放蜂鸣音,使用的单位是上述硬件配置的“自然”单位。
如果您的频率和持续时间是固定的,那么这些单元可以免费简化代码

嘟嘟声在给定的持续时间后停止,您可以使用
beep_stop
强制停止

一次播放多个声音是不可能的(如果不使用PWM技术,甚至混音也是不可能的)。

当另一个蜂鸣音正在播放时,调用
beep\u play
,将产生停止当前蜂鸣音并启动新蜂鸣音的效果。

可能重复您是否参考了DOS中断参考?这是一个很好的答案+1但是beep_isr中断服务程序有一个重要问题!不能只使用
AX
寄存器而不保留它。如果您编写:
cmp单词[cs:sound\u counter],0
je\u bi\u stop
dec单词[cs:sound\u counter]
。根本不需要使用AX。非常感谢@SepRoland!我正在用学分更新答案:)
BITS 16

ORG 100h

__start__:

 ;Setup
 call beep_setup

 ;Sample beep of ~2sec
 mov ax, 2000
 mov bx, 36
 call beep_play

 ;Wait for input
 xor ax, ax
 int 16h

 ;Tear down
 call beep_teardown

 mov ax, 4c00h
 int 21h

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

 ;
 ;Setup the beep ISR
 ;

 beep_setup:
  push es
  push ax

  xor ax, ax
  mov es, ax

  ;Save the original ISR
  mov ax, WORD [es: TIMER_INT * 4]
  mov WORD [cs:original_timer_isr], ax
  mov ax, WORD [es: TIMER_INT * 4 + 2]
  mov WORD [cs:original_timer_isr + 2], ax

  ;Setup the new ISR

  cli
  mov ax, beep_isr
  mov WORD [es: TIMER_INT * 4], ax
  mov ax, cs
  mov WORD [es: TIMER_INT * 4 + 2], ax
  sti

  pop ax
  pop es
  ret 


 ;
 ;Tear down the beep ISR
 ;

 beep_teardown:
  push es
  push ax

  call beep_stop

  xor ax, ax
  mov es, ax

  ;Restore the old ISR

  cli
  mov ax, WORD [cs:original_timer_isr]
  mov WORD [es: TIMER_INT * 4], ax
  mov ax, WORD [cs:original_timer_isr + 2]
  mov WORD [es: TIMER_INT * 4 + 2], ax
  sti

  pop ax
  pop es
  ret 

 ;
 ;Beep ISR
 ;
 beep_isr:
  cmp BYTE [cs:sound_playing], 0
  je _bi_end

  cmp WORD [cs:sound_counter], 0
  je _bi_stop

  dec WORD [cs:sound_counter]

 jmp _bi_end

_bi_stop:
  call beep_stop

_bi_end:
  ;Chain
  jmp FAR [cs:original_timer_isr]

 ;
 ;Stop beep
 ;
 beep_stop:
  push ax

  ;Stop the sound

  in al, 61h
  and al, 0fch    ;Clear bit 0 (PIT to speaker) and bit 1 (Speaker enable)
  out 61h, al

  ;Disable countdown

  mov BYTE [cs:sound_playing], 0

  pop ax
  ret

 ;
 ;Beep
 ;
 ;AX = 1193180 / frequency
 ;BX = duration in 18.2th of sec
 beep_play:
  push ax
  push dx

  mov dx, ax

  mov al, 0b6h
  out 43h, al

  mov ax, dx
  out 42h, al
  mov al, ah
  out 42h, al


  ;Set the countdown
  mov WORD [cs:sound_counter], bx

  ;Start the sound

  in al, 61h
  or al, 3h    ;Set bit 0 (PIT to speaker) and bit 1 (Speaker enable)
  out 61h, al


  ;Start the countdown

  mov BYTE [cs:sound_playing], 1

  pop dx
  pop ax
  ret

 ;Keep these in the code segment
 sound_playing      db  0
 sound_counter      dw  0
 original_timer_isr     dd  0

 TIMER_INT      EQU     1ch