微机原理实训——汇编设计菜单(四)

实现成绩录入功能的子程序

本篇来实现成绩录入功能
为了方便调试我们新建一个asm文件来写,调试没问题再复制过去
首先需要设计一下数据段
先看一下文档
在这里插入图片描述
我们要用到INT 21H中断的0A号功能读取键盘输入,并且存到内存中去

下面的代码是演示一下这个中断

ASSUME CS:CODE,DS:DATA
DATA SEGMENT
	BUF1 DB 10 dup(2 dup(14,0,14 dup(?)))
DATA ENDS

CODE SEGMENT
START:	
	MOV AX,data
    MOV DS,AX

    MOV AH,0AH;键盘输入到缓冲区
    LEA DX,BUF1;取段内偏移地址
    INT 21H;调用系统dos中断
    
	mov ah,4ch
   	int 21h

CODE ENDS
	END START

看一下dosbox调试的时候,使用d0查看内存,可以看到,在这里一行正好是16个字节
根据上面的文档,
缓冲区第一个字节也就是(DS:DX)是来指定缓冲区最大字符数
缓冲区第二个字节也就是(DS:DX+1)是实际输入的字符数
而内存中一行是16个字节
所以为了方便,我们设计成一行放姓名,一行放成绩
我们这里键盘输入xiaoming并敲回车,
可以看到第一个字节是0E也就是十进制的14(我们自己设计的,最大字符数为14)
第二个字节是08(’xiaoming‘八个字符,所以是08)
这里注意在67(对应的字母是g)的后面,有个0D(对应的ascii就是换行),说明这里把我们敲得回车也读了进来
在这里插入图片描述

根据上面的示例
我们这样设计这样的数据段

data segment
	NUM DB 14,0,14 dup(?)
    BUF1 DB 10 dup(2 dup(14,0,14 dup(?)))
    INPUT DB 'welecome and please input the number of students N:$'
    INPUTNAME DB 'please input the name with student NO.$'
    INPUTSCORE DB 'please input the score with student NO.$'
    N DB '0'
data ends

第一行NUM 用来存要录入几个学生的成绩
下面BUF1 一行存姓名,一行存成绩,这里不设计那么大,只允许存十个学生的成绩
直接上完整代码

assume cs:code,ds:data
data segment
	NUM DB 14,0,14 dup(?)
    BUF1 DB 10 dup(2 dup(14,0,14 dup(?)))
    INPUT DB 'welecome and please input the number of students N:$'
    INPUTNAME DB 'please input the name with student NO.$'
    INPUTSCORE DB 'please input the score with student NO.$'
    N DB '0'
data ends


CODE SEGMENT
START:	
	MOV AX,data
    MOV DS,AX

    MOV AH,09H;显示字符串
    LEA DX,INPUT;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV AH,0AH;键盘输入到缓冲区
    LEA DX,NUM;取段内偏移地址
    INT 21H;调用系统dos中断

	MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    MOV SI,2
    MOV al,NUM[SI];把输入的数存入al
    SUB al,30H;ASCII数字变成纯数字
    MOV ah,0;高位清零
    MOV CX,AX;循环次数给CX

    LEA DX,BUF1;上面的中断DX寄存器的值被修改了 这句必须加
    push DX;dx入栈 存起来
L1:
    INC N
    MOV AH,09H;显示字符串
    LEA DX,INPUTNAME;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV DL,N;传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
    MOV DL,':';传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    pop DX;dx出栈
 
    MOV AH,0AH;键盘输入到缓冲区
    INT 21H;调用系统dos中断
    ADD DX,10h;dx加10h就是加16,指向内存里面的下一行
    push DX;dx入栈

    MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    MOV AH,09H;显示字符串
    LEA DX,INPUTSCORE;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV DL,N;传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
    MOV DL,':';传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    pop DX;dx出栈
    
    MOV AH,0AH;键盘输入到缓冲区
    INT 21H;调用系统dos中断
    ADD DX,10h
    push DX

    MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
LOOP L1
    pop DX;最后一定要出栈
    mov ah,4ch;0090
    int 21h
CODE ENDS
	END START

解释一下上面的代码

1.键盘输入已经说过了
2.提示用户输入,显示对应的学生编号NO1,NO2,那里实现的方法是
先用INT 21H的09H功能显示字符串
再用INT 21H 的02号功能显示一个字符冒号’:’
再用INT 21H 的02号功能显示一个字符,N,N的值就是第几个学生,因为数据段定义的时候N=‘0’,每次循环N都会加1,具体的看代码吧。。

3.再说一下换行
换行在汇编里面是两步,第一步先把光标置于最左边,第二步把光标移到下一行
所以先显示一个ODH再显示一个0AH

OK,继续,还有不懂的研究研究代码或者私信我

调试一下,看下有没有存入内存中
使用u命令查看代码地址
在这里插入图片描述
还没到,继续往下找,我们要找代码最后的地址
在这里插入图片描述
这里已经到最后了,使用g 0090 命令执行到这里
在这里插入图片描述
我们输入的姓名成绩全都存到了内存中,并且是整齐的按行排列
dx=0050 对应内存中的第六行
在这里插入图片描述
ok,录入功能的子程序写完了
我们把他放入之前的菜单程序里面去

1.先把数据段复制过去

data segment
NUM DB 14,0,14 dup(?)
BUF1 DB 10 dup(2 dup(14,0,14 dup(?)))
INPUT DB 'welecome and please input the number of students N:$'
INPUTNAME DB 'please input the name with student NO.$'
INPUTSCORE DB 'please input the score with student NO.$'
N DB '0'
l0 db '        MENU         '
l1 db '====================='
l2 db '|  score-recording   ';录入
l3 db '|  score-update      ';修改
l4 db '|  score-sort        ';排序
l5 db '|  score-output      ';输出
l6 db '|  RETURN            '
l7 db '====================='
LL EQU $-l7
XX equ (80-ll)/2
yy db ?
nn dw 1
tab dw ?,l2,l3,l4,l5,l6
addr dw ?
data ends

这里注意,我们把我们的数据段加在了最上面,不然会被其它的数据打乱结构

2.把程序复制到function1里面

敲击回车之后,要先清屏
这里加上清屏
在call function1加上清屏

first:
    mov ah,0
    mov al,3
    int 10h;BIOS中断3号功能 这个ah=0h可以快速清屏,demo用的就是这个
    call function1
    mov ah,4ch
    int 21h

把代码复制到function1 proc
注意去掉
MOV AX,data
MOV DS,AX
这两句

还要把最后的结束语句换成ret
看一下完整的function1 proc

function1 proc
	MOV AH,09H;显示字符串
    LEA DX,INPUT;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV AH,0AH;键盘输入到缓冲区
    LEA DX,NUM;取段内偏移地址
    INT 21H;调用系统dos中断

	MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    MOV SI,2
    MOV al,NUM[SI];把输入的数存入al
    SUB al,30H;ASCII数字变成纯数字
    MOV ah,0;高位清零
    MOV CX,AX;循环次数给CX

    LEA DX,BUF1;上面的中断DX寄存器的值被修改了 这句必须加
    push DX;dx入栈 存起来
L1:
    INC N
    MOV AH,09H;显示字符串
    LEA DX,INPUTNAME;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV DL,N;传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
    MOV DL,':';传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    pop DX;dx出栈
 
    MOV AH,0AH;键盘输入到缓冲区
    INT 21H;调用系统dos中断
    ADD DX,10h;dx加10h就是加16,指向内存里面的下一行
    push DX;dx入栈

    MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    MOV AH,09H;显示字符串
    LEA DX,INPUTSCORE;取段内偏移地址
    INT 21H;调用系统dos中断

    MOV DL,N;传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
    MOV DL,':';传送字符
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断

    pop DX;dx出栈
    
    MOV AH,0AH;键盘输入到缓冲区
    INT 21H;调用系统dos中断
    ADD DX,10h
    push DX

    MOV DL,0DH;CR
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
 	MOV DL,0AH;LF
 	MOV AH,2;显示一个字符
 	INT 21H;调用系统dos中断
LOOP L1
    pop DX;最后一定要出栈
	ret
function1 endp

ok编译一下试一试
这里报了个错误
因为之前定义过L1啦
我们换一个名字,把循环那里的L1改成LLLL1
在这里插入图片描述
改成LLLL1
下面的LOOP L1 也要改成 LOOP LLLL1

在这里插入图片描述
修改完毕
编译成功
调试一下
(这里我用-u一步步找的代码地址,然后-g 010f直接执行到010f)
在这里插入图片描述
全都存入到内存中了,很完美

3.处理菜单返回

这里我们call完function1之后直接结束了

first:
    mov ah,0
    mov al,3
    int 10h;BIOS中断3号功能 这个ah=0h可以快速清屏,demo用的就是这个
    call function1
    mov ah,4ch
    int 21h

我们不让它结束,让它录入完返回到主菜单
只需这样修改

first:
    mov ah,0
    mov al,3
    int 10h;BIOS中断3号功能 这个ah=0h可以快速清屏,demo用的就是这个
    call function1
    jmp main

很简单是不是
直接跳到main
这里的main在这个位置,后来加的,也可以直接跳到 beg (jmp beg)
在这里插入图片描述

编译,运行,录入结束,直接回到主菜单,没有问题
调试看一下,返回主菜单之后,成绩信息还在不在内存单元中
在这里插入图片描述

可以看到跳转到主菜单之后,成绩信息依然在内存中

本篇结束

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值