汇编打字程序(emu8086)

一、实验目的 

1) 利用本学期所学汇编知识完成一次综合设计。 

2) 熟悉各种输入、输出方法的调用方法。 

二、实验内容 

设计一个打字练习软件,具体要求如下:

1)利用BIOS的屏幕窗口功能制作一个用户菜单,菜单包括:① 欢迎用语,提示按“ESC”键退出练习;② 开始练习,给出练习句子;③ 显示成绩和时间; ④ 退出用语

2)每次打字之前,屏幕上先显示出一个句子,然后打字员按照例句,将句中字符通过键盘输入。这个过程反复进行。利用BIOS 16H键盘功能调用来判断输入是否正确,不正确给出标示;

3)利用DOS系统时间调用计时,屏幕上以min:sec:msec的格式显示出练习时间

4)练习句子可用文件存储或定义在数据段中,定义10行,每行10个字符,区分大小写,分数根据准确率给出;允许中途退出,退出时给出提示语和选择,确定退出不给分和计时。

三、实验设备 

    PC机一台

四、实验步骤 

1) 画出程序的主流程图和子程序流程图。 

2) 输入源程序。 

3) 汇编、连接程序,执行程序,检查结果。                      

4) 程序的执行可用DEBUG的G命令,也可用T命令单步跟踪执行。  

五、实验报告的要求 

1) 列出源程序。 

2) 总结输入输出程序及菜单的编写方法。 

3) 总结常用系统调用的功能及调用方法。 

; multi-segment executable file template.

data segment
    ; add your data here!
    ;背景
    bg db 1,10,22,61,2,11,21,60   ;前4个是边框,后四个是内容
    center db 11,35               ;中心点偏左上一格的坐标
    
    welcome1 db "*Welcome!"
    lwelcome1 equ $-welcome1 ;长度
    welcome2 db "*Input number to choose:"
    lwelcome2 equ $-welcome2 ;长度
    enter db 0dh,0ah,'$'
    option1 db "  #1.Start game"
    loption1 equ $-option1 ;长度
    option2 db "  #2.Check the highest record" 
    loption2 equ $-option2 ;长度
    option3 db "  #Press 'ESC' Exit Game" 
    loption3 equ $-option3 ;长度
    gameHint db "*Print the same string as follow!"
    lgameHint equ $-gameHint
    scoreHint db "Your score is:"    ;分数的提示
    lscoreHint equ $-scoreHint       
    hscoreHint db "Your highest score is:" ;最高分提示
    lhscoreHint equ $-hscoreHint                    
    gameTimeHint db "Used Time:"          ;时间提示
    lgameTimeHint equ $-gameTimeHint
    gameOver db "Game Over,press any key to exit" ;游戏结束提示
    lgameOver equ $-gameOver                         
    anyKeyExit db "Press any key to exit"  ;按任意键退出提示
    lanyKeyExit equ $-anyKeyExit                            
    opErrorHint db "Input error!"          ;输入错误 
    lopErrorHint equ $-opErrorHint
    exitHint db "Do you want to exit",63     ;退出提示,63是问号
    lexitHint equ $-exitHint 
    exitOption1 db "#1.yes"
    lexitOption1 equ $-exitOption1
    exitOption2 db "#2.no"
    lexitOption2 equ $-exitOption2
    ;操作号
    op1 equ '1' 
    op2 equ '2' ;操作号
    op3 equ 27  ;esc键
    
    ;时间
    min db 0
    second db 0
    perSecond db 0
    
    ;游戏的串(顺序)
    lstr equ 10
    str1 db "Peacefully"
    str2 db "Enthraller"
    str3 db "StayStrong"
    str4 db "KeepsGoing"
    str5 db "Euphoricly"
    str6 db "Rainbowish"
    str7 db "Wonderment"
    str8 db "activeness"
    str9 db "winterless"
    str10 db "guarantied"
    
    ;输入的串
    istr db 11,0,11 dup('$') 
    
    ;背景加前景色
    pinkBlack equ 50H
    blackWhite equ 0fH
    blackRed equ 0cH
    blackYellow equ 0eh
    blackGreen equ 0ah
    blackGrey equ 07h
    
    ;记录
    hscore db 0
    score db 100

ends

stack segment
    dw   128  dup(0)
ends

code segment
start:
; set segment registers: 
    mov ax, data
    mov ds, ax
    mov es, ax

    ; add your code here
    
;光标位置
setCursorP macro row,col
    push ax
    push dx
    push bx
    mov dh,row
    mov dl,col
    mov bh,0  
    mov ah,02h
    int 10h
    pop bx
    pop dx
    pop ax     
endm
;在光标处打印字符
printChar macro char,attribute,times
    push ax
    push bx
    push cx
    mov al,char
    mov bh,0
    mov bl,attribute
    mov cx,times
    mov ah,09h
    int 10h
    pop cx
    pop bx
    pop ax
endm

;上滚
scroll macro N,TOP,LEFT,BUTTOM,RIGHT,ATTRIBUTE
    push ax
    push bx
    push cx
    push dx
    mov bh,ATTRIBUTE    ;形式
    mov ch,TOP
    mov cl,LEFT
    mov dh,BUTTOM
    mov dl,RIGHT
    mov ah,06h
    mov al,N    ;上卷数
    int 10h
    pop dx
    pop cx
    pop bx
    pop ax
endm    
;下滚
scrollDown macro N,TOP,LEFT,BUTTOM,RIGHT,ATTRIBUTE
    push ax
    push bx
    push cx
    push dx
    mov bh,ATTRIBUTE    ;形式
    mov ch,TOP
    mov cl,LEFT
    mov dh,BUTTOM
    mov dl,RIGHT
    mov ah,07h
    mov al,N    ;上卷数
    int 10h
    pop dx
    pop cx
    pop bx
    pop ax
endm

;画背景
getBackground macro
    scroll 0,0,0,24,79,02
    scroll 79,bg[0],bg[1],bg[2],bg[3],pinkBlack
    scroll 79,bg[4],bg[5],bg[6],bg[7],blackWhite
endm
;在光标位置输入字符
inputChar macro 
    mov ah,0h
    int 16h 
endm
;得到当前时间(用dos调用)
getTime macro 
    push ax
    push cx
    push dx
    mov ah,2ch
    int 21h
    mov min,cl
    mov second,dh
    mov persecond,dl
    pop dx 
    pop cx
    pop ax
endm
;打印游戏时间(光标已移到正确的位置)
printGameTime macro 
    local msNoChange,sNoChange,mNoChange
    push ax
    push bx
    push cx
    push dx
    ;得到光标位置
    mov bh,0
    mov ah,03h
    int 10h      ;;DH/DL =行号/列号
    and cx,0
    mov cl,dh ;;行号
    and dh,0
     
    push cx
    push dx  ;行和列号调用printNum 用
    
    mov dl,perSecond
    mov dh,min
    mov ch,second
    getTime ;;得到当前新的时间
    
    
    
    mov bl,min    ;分   
    ;秒结果在ax中
    ;msec在cl中
    mov al,second
    mov cl,persecond 
    
    sub cl,dl       
    jns msNoChange
    add cl,100
msNoChange:    
    sbb al,ch
    pushf
    jns sNoChange  ;>0不改
    ;改
    add al,60
sNoChange:    
    popf
    sbb bl,dh
    jns mNoChange
    add bl,60
mNoChange:    
    
    
    
    and ah,0
    and ch,0
    and bh,0
    push bx
    call printNum  ;打印分 
    printChar ':',blackWhite,1
    ;得到光标位置                           
    push cx
    mov bh,0
    mov ah,03h
    int 10h      ;;DH/DL =行号/列号  cx:属性   
    inc dl  ;列加1
    mov cl,dh
    and ch,0
    and dh,0
    push cx   ;行
    push dx   ;列
    push ax   ;打印秒
    call printNum 
    
    printChar ':',blackWhite,1 
    ;得到光标位置                           
    mov bh,0
    mov ah,03h
    int 10h      ;;DH/DL =行号/列号  cx:属性   
    inc dl  ;列加1
    mov cl,dh
    and ch,0
    and dh,0 
    pop bx
    push cx   ;行
    push dx   ;列

    push bx  
    call printNum   ;打印perSecond  
    printChar '0',blackGreen,1  
    pop dx
    pop cx
    pop bx
    pop ax
endm


;主程序
    ;开屏
    
    mov al,02h
    mov ah,0h
    int 10h
    
    ;光标样式
    mov ah,01h
    mov ch,06h
    mov cl,07h
    int 10h
    ;要有一个死循环
mainWhile:
    ;画背景
    getBackground
    call welcome
    
    inputChar 		;输入功能号
    
    cmp al,op1
    jz STARTGAME
    cmp al,op2
    jz RECORD
    
    cmp al,op3
    jz FINISH
    
    call opError   ;输入功能号错误 
    jmp mainWhile
    
    jmp FINISH
    
STARTGAME:
    call gameProc ;启动游戏
        
RECORD:
    call recordProc ;查看最高分
    
    jmp mainWhile   ;死循环
    
FINISH:            
    mov ax, 4c00h ; exit to operating system.
    int 21h 
    
    
    
    
    
    
    
    
    
;在光标处打印字符串         
;str地址                    18
;str长度                    16
;row+col                    14
;属性                       12
;出口
;ax
;bx
;cx
;dx
;bp   [sp]
printStr proc ;要push str地址,row,col
    push ax
    push bx
    push cx
    push dx
    push bp
    mov bp,sp 
    mov cx,[bp+16]
    mov bh,0
    mov al,0
    mov bl,[bp+12]
    mov dx,[bp+14]
    push bx
    mov bx,[bp+18]
    mov bp,bx
    pop bx
    mov ah,13h
    int 10h
    pop bp
    pop dx
    pop cx
    pop bx
    pop ax
    ret 8
endp    
;欢迎语句    
welcome proc
    push ax
    push cx
    push dx
    mov ch,bg[4]
    mov cl,bg[5]
    inc ch
    inc cl
    push offset welcome1
    push lwelcome1
    push cx 
    push blackWhite
    call printStr
    
    inc ch
    push offset welcome2
    push lwelcome2
    push cx
    push blackWhite
    call printStr
    
    inc ch
    push offset option1
    push loption1
    push cx
    push blackWhite
    call printStr
    
    inc ch
    push offset option2
    push loption2
    push cx
    push blackWhite
    call printStr
    
    inc ch
    push offset option3
    push loption3
    push cx
    push blackWhite
    call printStr
    
    inc ch
    setCursorP ch,cl
    
    pop dx
    pop cx
    pop ax
    ret
endp

;启动游戏
gameProc proc
    getBackground
    mov ch,bg[4]
    inc ch             
    mov cl,center[1]
    shr cl,1           ;col在1/4
    setCursorP ch,cl
    push offset gameHint 
    push lgameHint
    push cx 
    push blackWhite
    call printStr 
    
    ;开始计时
    getTime
    
    mov dl,0        ;dl:字符串循环次数为10
    mov bx,0  ;bx存输出的字符串起始下标
printSample:       ;打样例
    mov ch,center[0]
    mov cl,center[1]
    sub cl,5    
    setCursorP ch,cl    ;row为1/2,col为中心点-5
    printChar '*',blackYellow,1  
    
    inc cl
    ;打字符串
    setCursorP ch,cl
    lea ax,str1[bx]
    push ax
    push lstr
    push cx
    push blackWhite
    call printStr
    
    inc ch
    dec cl
    setCursorP ch,cl
    printChar '#',blackWhite,1
    
    ;打字
    mov dh,0          ;打lstr个字符
    lea si,str1[bx]    ;si是对应的答案
inputStr:
    inc cl
    setCursorP ch,cl 
    
inputC:
    inputChar
    printChar al,blackGrey,1
inputJudge: ;判断打的字
    cmp al,op3        ;是否是退出
    jnz NEXTCHAR
    ;是退出键
    push cx
    
    call isExit
    cmp al,op1
    jnz noChoose
    ;选择退出
    jmp MainWhile
    
noChoose:
    ;不退出
    pop cx
    push cx
    push cx
    call noExit    
    pop cx
    jmp inputC
    
NEXTCHAR:
    ;cmpsb
    cmp al,[si]
    jz INPUTRIGHT
    ;输入错误
    ;add cl,dh
    inc ch        ;光标向下移
    setCursorP ch,cl
    printChar [si],blackRed,1
    ;sub cl,dh
    dec ch
    dec score  ;得分减1
INPUTRIGHT:;正确
    inc si      
    inc dh
    cmp dh,lstr
    jnz inputStr   

    ;打了几个字符串
    add bx,lstr
    inc dl
    
    
    ;上卷 
    push cx
    
    mov ax,cx
    add ah,2
    add al,lstr
    
    mov ch,center[0]
    sub ch,4
    mov cl,center[1]
    sub cl,10
    
    
    
    scroll 4,ch,cl,ah,al,blackGrey 
    pop cx
    cmp dl,lstr
    jnz printSample
    ;游戏结束
    ;得到时间 
    mov ch,center[0]
    mov cl,center[1]
    sub cl,10    
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl   
    mov ax,offset gameTimeHint
    push ax
    push lgameTimeHint
    push cx
    push blackWhite
    call printStr
    add cl,lgameTimeHint
    setCursorP ch,cl
    printGameTime
    
    
    
    ;是否是最高分
    mov cl,score
    cmp cl,hscore
    jbe outputRes
    mov hscore,cl
    
    ;得到结果
outputRes:
    inc ch
    mov cl,center[1]
    sub cl,10    
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset scoreHint
    push ax
    push lscoreHint
    push cx
    push blackWhite
    call printStr
    add cl,lscoreHint
    setCursorP ch,cl
    mov ax,cx
    and ah,0
    mov cl,ch
    and ch,0
    push cx
    push ax
    and ax,0
    mov al,score 
    push ax
    mov ch,cl
    mov cl,al
    call printNum     ;输出分数
    
    ;按任意键返回
    inc ch
    mov cl,center[1]
    sub cl,10
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset gameOver
    push ax
    push lgameOver
    push cx
    push blackWhite
    call printStr
    inc ch
    setCursorP ch,cl
    inputChar
    
    ret
endp 

;查看最高分的子程序
recordProc proc
    getBackground
    mov ch,center[0]
    mov cl,center[1]
    sub cl,10    
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset hscoreHint
    push ax
    push lhscoreHint
    push cx
    push blackWhite
    call printStr
    add cl,lhscoreHint
    setCursorP ch,cl
    mov ax,cx
    and ah,0
    mov cl,ch
    and ch,0
    push cx
    push ax
    and ax,0
    mov al,hscore 
    push ax
    mov ch,cl
    mov cl,al
    call printNum     ;输出分数
    ;按任意键返回
    inc ch
    mov cl,center[1]
    sub cl,10
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset anyKeyExit
    push ax
    push lanyKeyExit
    push cx
    push blackWhite
    call printStr
    inc ch
    setCursorP ch,cl
    inputChar
    
    
    ret
endp

;按到退出的子程序
isExit proc
    ;上卷   
    mov ax,cx
    add ah,2
    add al,lstr
    
    mov ch,center[0]
    sub ch,4
    mov cl,center[1]
    sub cl,6
    
    scroll 4,ch,cl,ah,al,blackGrey 
    
    mov ch,center[0]
    mov cl,center[1]
    sub cl,10    
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    ;打字符串
    setCursorP ch,cl
    mov ax,offset exitHint
    push ax
    push lexitHint
    push cx
    push blackRed
    call printStr
    
    inc ch
    inc cl
    setCursorP ch,cl
    mov ax,offset exitOption1
    push ax
    push lexitOption1
    push cx
    push blackGrey
    call printStr
    
    inc ch
    setCursorP ch,cl
    mov ax,offset exitOption2
    push ax
    push lexitOption2
    push cx
    push blackGrey
    call printStr
    inc ch
    setCursorP ch,cl
    sub cl,2
    
    inputChar 
    ret
endp

;选择不退出的子程序
;cx     4
;出口 
;bp    [sp]
noExit proc
    ;下滚
    push bp
    mov bp,sp
    mov ch,center[0]
    mov cl,center[1]
    mov ax,cx
    add ah,3
    add al,10 
    sub ch,4
    sub cl,10 
    
    scrollDown 4,ch,cl,ah,al,blackGrey
    
    ;恢复上一个字符
    mov cx,[bp+4]
    setCursorP ch,cl
    printChar ' ',blackGrey,1
    
    pop bp
    ret 2
endp



;打印数字的程序
;光标row          16
;col              14
;数字             12
;出口
;bp
;ax
;bx
;cx
;dx   [sp] 
printNum proc 
    push bp
    push ax
    push bx
    push cx
    push dx
    
    mov bp,sp
    mov ax,[bp+12]    ;得到数字
    and cx,0      
    mov bx,[bp+16]    ;bl存:row
    mov dx,[bp+14]    ;dl存:col   
    setCursorP bl,dl
    and dh,0
    mov bh,10       ;bh:存10
continueDiv:
    and ah,0 
    div bh
    ;余数在ah(小于10),商在al
    add ah,'0'               
    mov cl,ah    ;cl:记录结果
    inc dh       ;dh:有几个数
    push cx      ;存结果 
    cmp al,0
    jnz continueDiv  ;除法的循环
    ;循环结束
outPutNum:
    pop cx  
    printChar cl,blackGreen,1
    inc dl       ;光标往后
    setCursorP bl,dl
    dec dh
    jnz outPutNum    ;输出的循环
    pop dx
    pop cx
    pop bx
    pop ax
    pop bp
    ret 6 
endp

;输入功能号错误
opError proc
    getBackground
    mov ch,center[0]
    mov cl,center[1]
    sub cl,10    
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset opErrorHint
    push ax
    push lopErrorHint
    push cx
    push blackWhite
    call printStr
    ;按任意键返回
    inc ch
    mov cl,center[1]
    sub cl,10
    setCursorP ch,cl    ;row为1/2,col为1/4中心点-10
    printChar '*',blackYellow,1
    inc cl
    mov ax,offset anyKeyExit
    push ax
    push lanyKeyExit
    push cx
    push blackWhite
    call printStr
    inc ch
    setCursorP ch,cl
    inputChar
    ret
endp

ends

end start ; set entry point and stop the assembler.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值