; CIS-261
; make_beeps.asm
; M09 demo: program that beeps
;
; @topic W100120 Lab M09 demo for Beep, Sleep, and GetLastError API calls
; @brief Lab M09, <a href="http:;www.c-jump.com/bcc/c261c/MLabs/M09arrays/M09arrays.html" target="_blank">Data Arrays and Windows API Calls</a>,
;
.586P
.MODEL FLAT ; Flat memory model
option casemap:none ; Treat labels as case-sensitive
INCLUDE IO.H ; header file for input/output
EXTERN _Beep@8:NEAR
EXTERN _GetLastError@0:NEAR
EXTERN _Sleep@4:NEAR
.CONST ; Constant data segment
WHITE_SPACE BYTE ' ', 0
PROPMT_FREQ BYTE "Enter an array of frequencies:", 0
PROPMT_DURATION BYTE "Enter an array of durations:", 0
NEWLINE BYTE 13, 10, 0
.STACK 100h ; (default is 1-kilobyte stack)
.DATA ; Begin initialized data segment
buffer BYTE 12 DUP (?), 0 ; input buffer for user interaction
dtoa_buffer BYTE 11 DUP (?), 0
frequency DWORD 16 DUP (?) ; array of frequencies in Hertz
frequency_end EQU OFFSET frequency + SIZEOF frequency
DWORD 0 ; zero marks freq end
duration DWORD 16 DUP (50) ; array sound duration in ms
duration_end EQU OFFSET duration + SIZEOF duration
.CODE ; Begin code segment
_main PROC ; Beginning of code
repeat_freq_input:
xor edi, edi ; set EDI = 0, to be used as array index
output NEWLINE
output PROPMT_FREQ
output NEWLINE
get_next_freq:
input buffer, 12
szlen buffer ; check the length of input
or eax, eax ; if input is empty (EAX == 0)
jz repeat_duration_input ; done with the input
atod buffer ; convert user input, result in EAX
jno @F ; Check the overflow flag
; Handle input error:
;...
jmp repeat_freq_input
@@:
; store freq or zero at the end of the array
mov frequency[ edi * 4 ], eax
inc edi ; increment array index
lea eax, frequency[ edi * 4 ] ; set EAX equal address of the array element
cmp eax, frequency_end ; out of bounds ?
je @F ; if yes, terminate the input loop
jmp get_next_freq
@@:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; input duratioin array
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
repeat_duration_input:
xor edi, edi ; set EDI = 0, to be used as array index
output PROPMT_DURATION
output NEWLINE
get_next_duration:
input buffer, 12
szlen buffer ; check the length of input
or eax, eax ; if input is empty (EAX == 0)
jz produce_sounds ; done with the input
atod buffer ; convert user input, result in EAX
jno @F ; Check the overflow flag
; Handle input error:
;...
jmp repeat_duration_input
@@:
; store freq or zero at the end of the array
mov duration[ edi * 4 ], eax
inc edi ; increment array index
lea eax, duration[ edi * 4 ] ; set EAX equal address of the array element
cmp eax, duration_end ; out of bounds ?
je @F ; if yes, terminate the input loop
jmp get_next_duration
@@:
produce_sounds:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; loop to produce sounds with Beep
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov cl, LENGTHOF frequency ; loop counter
mov esi, 0 ; frequency array index
repeat_beep:
mov eax, DWORD PTR frequency[esi*TYPE DWORD]
or eax, eax ; if freq iz zero, stop
jnz @F
jmp repeat_freq_input
@@:
mov ebx, DWORD PTR [duration]
call make_beep
or eax, eax
jz @F ; everything is okay
; report an error...
@@:
inc esi ; increment array index
dec cl ; decrement loop counter
jnz repeat_beep ; repeat
ret ; Exit the program
_main ENDP
; POSTCONDITION: modifies ebx
; input params: eax freq
; ebx duration
; returns: eax == 0 if no error, otherwise GetLastError result
make_beep PROC ; sample procedure
dtoa dtoa_buffer, eax ; convert 32-bit signed integer to string
output dtoa_buffer ; print frequency
output WHITE_SPACE ; print space
; preserve all gp registers
pushad
push ebx ; duration param
push eax ; freq param
call _Beep@8 ; make sound
; EAX != 0 indicates succeess, error otherwise
or eax, eax
jnz @F ; success
popad
call _GetLastError@0
; EAX contains the error code to report
ret
@@:
pushd 300 ; duration of sleep in MS
call _Sleep@4
; restore all registers
popad
xor eax, eax ; set EAX = 0
ret ; return from procedure
make_beep ENDP
END _main ; Marks the end of the module and sets the program entry point label