;;; ; ; playNotes.asm
;;; ; ; Amy Gray
;;; ; ; December 2008
;;; ; ;
;;; ; ;
;;; ; ;
;;; ; ; to assemble and run:
;;; ; ;
;;; ; ; nasm -f elf -F stabs playNotes.asm
;;; ; ; gcc -o playNotes driver.c playNotes.o
;;; ; ; ./playNotes
;;; ; ; =========================================================
;; %include "asm_io.inc"
;;; External Labels =============================================
extern getchar
extern getc
EXIT equ 1
WRITE equ 4
STDOUT equ 1
;;; ; ===========================================================
;;; ; data areas
;;; ; ===========================================================
;;; ; note: 78 is dec for N and is essentially arbitrary. When
;;; ; playing the array, the program will check to see if the
;;; ; "note" equals 78, and if so, knows there are no more notes
;;; ; contained in the array and will end the loop. I chose N
;;; ; for "null" or "no note."
;;; ; ===========================================================
section .data
array dd 78,78,78,78,78,78,78,78,78,78,78,78,78,78
dd 78,78,78,78,78,78,78,78,78,78,78,78,78,78
dd 78,78,78,78,78
arrayLen equ $-array
nextIndex dd 0 ;next index to be written to
message1 db "Would you like to quit after this round?"
db " Type 'n' for no, 'y' for yes.", 10
message1Len equ $-message1
message2 db "Sorry, input not valid. "
message2Len equ $-message2
message3 db "Enter a new note: c, d, e, f, g, a, b, C,"
db " or p for pause."
message3Len equ $-message3
message4 db "There's no more room to add notes!"
db "Your loop will continue to play and "
db "you can continue to make adjustments "
db "until you choose to exit. Type 'e' to exit."
message4Len equ $-message4
section .bss
MAXBUF equ 100000
buffer resb MAXBUF ; 100,000 bytes of storage
;;; ; =============================================================
;;; ; code area
;;; ; =============================================================
section .text
global asm_main
asm_main:
mov eax, WRITE
mov ebx, STDOUT
mov ecx, message1 ;quit after play?
mov edx, message1Len
int 0x80
mov eax, 0 ;clear eax
mov ebx, 0
mov ecx, 0
mov edx, 0
;; call getchar
ReadLoop1:
mov ah, 0 ;read key opcode
;; art of assembly says use 16h. 16h is BIOS
;; 80h for Linux?
int 0x80
cmp al, 1 ;special function?
je ReadLoop1 ;if so, don't echo this keystroke
putc
cmp al, 0x16 ;carriage return (ENTER)
jne ReadLoop1
checkKey:
cmp al, 0x79 ;check for y
je lastRound1
cmp al, 0x6E ;check for n
jne badAnswer1
lastRound1: jmp lastRound2
badAnswer1: jmp badAnswer2
main:
mov eax, WRITE
mov ebx, STDOUT
mov ecx, message3
mov edx, message3Len
int 0x80
;; mov eax, message3 ;ask for new note
;; call print_string
mov eax, 0 ;clear eax
ReadLoop2:
mov ah, 0 ;read key opcode
;; art of assembly says use 16h. 16h is BIOS
;; 80h for Linux?
int 80h
cmp al, 0 ;special function?
jz ReadLoop2 ;if so, don't echo this keystroke
cmp al, 0dh ;carriage return (ENTER)
jne ReadLoop2
getNextIndex:
mov ebx, 0
mov ecx, [arrayLen]
gniLoop:
cmp dword[array + ebx], 78
je checkNote
inc ebx
loop gniLoop
checkNote:
cmp ebx, [arrayLen-1];end of array?
je noMoreRoom1 ;array has exceeded 32 notes
mov [nextIndex], ebx
cmp ah, 0x63 ;low c?
je noteClow1
cmp ah, 0x64 ;d?
je noteD1
cmp ah, 0x65 ;e?
je noteE1
cmp ah, 0x66 ;f?
je noteF1
cmp ah, 0x67 ;g?
je noteG1
cmp ah, 0x61 ;a?
je noteA1
cmp ah, 0x62 ;b?
je noteB1
cmp ah, 0x43 ;high C?
je noteChigh1
cmp ah, 0x70 ;pause?
je notePause1
jmp badNote
;; Steps for Short Jumps ===========================
lastRound2: jmp lastRound
badAnswer2: jmp badAnswer
noMoreRoom1: jmp noMoreRoom
noteClow1: jmp noteClow
noteD1: jmp noteD
noteE1: jmp noteE
noteF1: jmp noteF
noteG1: jmp noteG
noteA1: jmp noteA
noteB1: jmp noteB
noteChigh1: jmp noteChigh
notePause1: jmp notePause
;;==================================================
;; TONES ==========================================
;; Start by defining the relationship between
;; note, period, & frequency.
;; #define c 3830 // 261 Hz
;; #define d 3400 // 294 Hz
;; #define e 3038 // 329 Hz
;; #define f 2864 // 349 Hz
;; #define g 2550 // 392 Hz
;; #define a 2272 // 440 Hz
;; #define b 2028 // 493 Hz
;; #define C 1912 // 523 Hz
;; #define p 0
;; ==================================================
noteClow:
mov ebx, [nextIndex]
mov dword[array + ebx], 3830
jmp checkPots
noteD:
mov ebx, [nextIndex]
mov dword[array + ebx], 3400
jmp checkPots
noteE:
mov ebx, [nextIndex]
mov dword[array + ebx], 3038
jmp checkPots
noteF:
mov ebx, [nextIndex]
mov dword[array + ebx], 2864
jmp checkPots
noteG:
mov ebx, [nextIndex]
mov dword[array + ebx], 2550
jmp checkPots
noteA:
mov ebx, [nextIndex]
mov dword[array + ebx], 2272
jmp checkPots
noteB:
mov ebx, [nextIndex]
mov dword[array + ebx], 2028
jmp checkPots
noteChigh:
mov ebx, [nextIndex]
mov dword[array + ebx], 1912
jmp checkPots
notePause:
mov ebx, [nextIndex]
mov dword[array + ebx], 0
jmp checkPots
;;====================================================
noMoreRoom:
mov eax, message4 ;no more room, but
;loop will play
;; call print_string
;; play loop that checks for arduino input
;;====================================================
checkPots:
jmp mainPlay
mainPlay:
mov ecx, 0 ;clear ecx
mov ecx, [nextIndex] ;#of notes
mov ebx, 0 ;which note to play
;; for testing, just print the array
.loop:
mov eax, [array + ebx]
;; call print_int
inc ebx
loop .loop
jmp asm_main
lastRound:
;plays once, then quits
jmp exit
badAnswer:
mov eax, WRITE
mov ebx, STDOUT
mov ecx, message2
mov edx, message2Len
int 0x80
jmp asm_main
badNote:
mov eax, WRITE
mov ebx, STDOUT
mov ecx, message2
mov edx, message2Len
int 0x80
jmp main
exit:
ret