; sound.asm plays a note of an input frequency & duration on the speaker.

; Push the frequency in hertz, and then the duration in millisecs. onto the

; stack, and then call sound. It’s a near routine that fixes up the stack.

public sound

.model small

.data

nticks dd 0 ; number of ticks for delaying

.code

sound PROC near

; store the value ofthe note’s duration in millisecs in nticks

PUSH BP

MOV BP,SP

PUSHAD ; an instruction which pushes all the general and index

; registers onto the stack. POPAD, used below, pops them

; all in reverse order

mov bx,[bp+4] ; value of the duration into BX

movsx nticks, bx ; value of the duration intonticks

; program clock 0 to produce a 1000 hz signal

mov al,00110110b ; initialize timer 0

out 43h,al

mov ax,1193 ; latch to act as frequency divisor

out 40h,al ; send low byte of divisor

mov al,ah

out 40h,al ; send high byte of the divisor

; put the value of FREQ (sound frequency for the note) into DI

mov di,[bp+6] ; value of frequency into DI

; program clock 2 to produce the sound

mov al,10110110b ; initialize clock 2

out 43h,al ;

; evaluate the divisor required as timer_input-frequency/FREQ

mov dx,12h ; store 12 34DCh (1,193,180) into

mov ax,34dch ; DX:AX for DIV command (dividend)

div di ; obtain frequency divisor in AX

out 42h,al ; send low byte of divisor

mov al,ah

out 42h,al ; send high byte of divisor

; turn the sound on

in al,61h ; read PPI port

or al,00000011b ; set bits 0 and 1 of the port to 1

out 61h,al ; turn speaker and timer 2 clock on

; get current number of ticks since midnight

mov ax,0 ; Set ES to 40h

mov es,ax

; calculate the count of ticks to be reached before switching the sound off

mov edx,es:46Ch ; put current no. of ticks since into DX

; add the duration required

add edx, nticks

; wait for the evaluated no. of ticks in edx to be reached to provide

; the required duration for the note

Delay: cmp es:[6Ch],edx ; Has this no. of ticks been reached?

jb Delay ; if not, continue to wait

; turn the sound off

in al,61h ; read PPI port

and al, not 00000011b ; set bits 0 and 1 of port 61h to 1

out 61h,al ; turn speaker and timer 2 clock off

; restore the original frequency of timer 0 to 18.2 cyles per sec.

mov al,00110110b ; initialize timer 0 again

out 43h,al ; preparing to send new freq. divisor

mov al,0FFh ; low byte of divisor value 65535

out 40h,al ; send the low byte

out 40h,al ; send the high byte

popad ; see description of pushad above

pop bp

ret 4 ; this subroutine “fixes up” the stack

sound endp

end