汇编竞赛作品——piano

       学校举办了汇编竞赛,因为兴趣,我参加了,记录一下。

       我写的是一个弹钢琴的小程序,程序比较简单。由于水平有限,程序中有的地方是借鉴网上的一些例子,光让我写我闷头写还真写不出来。

       程序的内容就是通过键盘的输入,发出各种音调。键盘的1 ~ 7(不是小键盘),q ~ u分别对应不同的音调,以特定的节奏按下可以演奏音乐。这里附上小星星的简谱:1155665,4422331,5544332,5544332,1155665,4433221。

       由于比赛的那段时间事多,所以写的代码没注释,这次记录的同时再补上注释。

data segment
    describe db 'piano key: 1~7,q~u'
                  db 0dh,0ah,'exit: 9'
                  db 0dh,0ah,'this is a procedure that play music'
                  db 0dh,0ah,'please input number for music__','$'


    tone_1 dw 882,-1                                   ;定义音调
    tone_2 dw 990,-1
    tone_3 dw 1112,-1
    tone_4 dw 1178,-1
    tone_5 dw 1322,-1
    tone_6 dw 1484,-1
    tone_7 dw 1655,-1
    tone_q dw 441,-1
    tone_w dw 495,-1
    tone_e dw 556,-1
    tone_r dw  589,-1
    tone_t dw  661,-1
    tone_y dw  742,-1
    tone_u dw  833,-1

data ends

stack segment
    db 200 dup('stack')
stack ends

code segment
     assume ds:data,ss:stack,cs:code
start:  mov ax,data
          mov ds,ax
          mov ah,0                                         ;设置显示模式
          mov al,03h                                      ;文字,80*25*16色
          int    10h

;定义一个宏

show macro b
    lea    dx,b
    mov ah,9
    int     21h
endm

;定义声音宏

sound macro sou,jumpto,char
    cmp al,char                                          ;匹配输入的字符
    jnz   jumpto                                         ;不相等就跳到jumpto继续匹配
    lea   si,sou                                         ;将音调的偏移存储在si中
    call  music
    jmp input
endm

show describe                                           ;调用宏

input: mov  ah,01h
          int     21h
          cmp  al,'9'                                   ;是否退出
          jnz    go1
          mov ah,4ch                                    ;返回DOS
          int    21h

go1:sound tone_1,go2,'1'
go2:sound tone_2,go3,'2'
go3:sound tone_3,go4,'3'
go4:sound tone_4 go5,'4'
go5:sound tone_5,go6,'5'
go6:sound tone_6,go7,'6'
go7:sound tone_7,goq,'7'
goq:sound tone_q,gow,'q'
gow:sound tone_w,goe,'w'
goe:sound tone_e,gor,'e'
gor:sound tone_r,got,'r'
got:sound tone_t,goy,'t'
goy:sound tone_y,gou,'y'
gou:sound tone_u,gon,'u'
gon:jmp input

play proc near

    push ax
    push bx
    push dx
    push di

    mov al,0b6h                                                           
    out   43h,al                                           ;初始化定时器
    mov dx,12h
    mov ax,348ch
    div   di                                               ;计算出AX=(DX+AX)/DI
    out   42h,al                                           ;将ax分为高低两位存储在
    mov al,ah                                              ;42h端口中,由此可以得到
    out   42h,al                                           ;输出的频率
    in     al,61h
    or    al,3                                             ;给61h端口写入11,打开定时器和开关
    out  61h,al
    mov ah,0
    int    1ah                                             ;ah==0时,读当前时钟值CX:DX
    add  dx,6                                              ;计数器从0加到6需要大约1/3秒的时间,
    mov bx,dx                                              ;这也就是每个音调播放的时间

delay: int   1ah
          cmp dx,bx                                        ;再次取得当前计数器的值,如果计数值==6
          jne    delay                                     ;延时结束

    mov al,1                                               ;关掉扬声器
    out   61h,al

    pop ax
    pop bx
    pop dx
    pop di

    ret
play endp

music proc near
    sub   ax,ax                               ;将ax清零,没有这句程序会异常停止
    push ax                                   ;ax入栈,没有这句回显的字符会一直存在
s:  mov di,[si]                               ;ds[si]存储的是音调的地址
    cmp di,-1                                 ;-1为播放结束的标志
    je     end_music                          ;结束播放
    call  play                                ;调用play开始播放音调
    add si,2                                  ;播放完后si+2,即si==-1
    jmp s

end_music: ret                                ;函数返回

music endp
code ends

end start

       由于是借鉴了一点网上的例子,不免有问题,问题就是在music函数的开头两句sub ax,ax和push ax;
sub ax,ax ;将ax清零,没有这句程序会异常停止
push ax ;ax入栈,没有这句回显的字符会一直存在
但是我一直想不出为啥去掉sub ax,ax程序会异常停止,没有push ax 回显的字符会一直存在。
如果有大佬知道希望不吝赐教。

       下面是程序的流程图:

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值