实验四 子程序结构
【实验目的】
1.掌握子程序结构
2.掌握如何输入输出十进制数字
【实验要求】
编写程序,在程序中设置两个加数,显示加法算式,用户输入运算结果,给出正确与否的信息。
提示:
1)显示十进制数据:p227 binidec
2)输入十进制数据:p200 decibin
【思考】
以为十进制好输入输出,实际上在汇编语言中还是得分成一位一位的,我以为在前三次上机里面是有过输入输出的,结果一看全是输出字符和字符串等,那么我们需要跟上次输出十六进制一样需要一位一位看,这里是不需要滚动的,因为我们正好是从左往右读的,直接输出即可。
【如何输入十进制】
步骤
我们将思路拆分成以下几个步骤:
1)读入一个字符
2)将字符减去48
成为对应的数字,也就是30H
3)判断是否小于零和大于9
,如果是的话就ret
4)用BX
专门每次乘以10再加上AX
注意
在这里我们需要注意:
1)读入的字符数值是在AL
中,我们需要用cbw
指令将AL
扩充至AX
2)我们得到的值和进行乘以10的操作都是在AX
寄存器中进行的,我们在对于BX
乘以10的时候首先需要交换AX
和BX
,用到xchg ax,bx
指令
3)在退出的时候需要重新设置一个exit
,不能直接写ret
,jmp
不能跳转到ret
decibin proc near
;从键盘输入一个十进制数,存入BX寄存器中
mov bx,0
getchar:
mov ah,01h
int 21h ;读入字符
sub al,30h ;减去30H,成为对应数字
jl exit ;如果小于0的话,就exit退出
cmp al,9d ;与9相比
jg exit ;如果大于9就退出
cbw ;将al扩充至ax
mov cx,10 ;给cx设置为10进行乘法操作
xchg ax,bx ;交换ax,bx,因为乘法是在ax中完成的
mul cx
add bx,ax ;乘以10之后加上
jmp getchar ;重新回到getchar再次进行
exit:
ret
decibin endp
【如何输出十进制】
步骤
这里按照书上给出的,需要输出五位
1)将除数从10000、1000...1的顺序设置放入cx
中,被除数放入bx
中,每次进行dec_div
从左往右一位一位输出
2)因为div cx
指令是以ax
为被除数,cx
为除数,然后将余数放入dx
中,商在al
中,所以我们需要将余数dx
放入bx
中,以便后面继续除以,bx
一直存的被除数,将商al
放入dl
中输出,因为输出指令是需要放入dl
中才输出的
简略的步骤如下:
1)设置cx
进入输出程序
2)除以cx
3)余数dx
放入bx
中(bx
一直存被除数)
4)将商al
放入dl
中输出
5)返回
binidec proc near
;把BX寄存器中的数以十进制数的形式在屏幕上显示出来
mov cx,10000d
call dec_div
mov cx,1000d
call dec_div
mov cx,100d
call dec_div
mov cx,10d
call dec_div
mov cx,1d ;每次这样设置可以从左到右分为每一位处理
call dec_div
ret
binidec endp
;------------------------------
dec_div proc near
;除法运算:(bx)/(cx)
;入口参数:(bx)=被除数,(cx)=除数
;出口参数:(bx)<--余数,商显示
mov ax,bx ;被除数给ax,div的指令要求
mov dx,0 ;dx置零
div cx ;除以cx
mov bx,dx ;余数给bx,成为下一次的被除数
mov dl,al ;al给dl输出,int指令要求是放入dl输出
add dl,30h ;+30H成为字符
mov ah,02h ;输出字符
int 21h
ret ;返回
dec_div endp
【主程序】
main proc far
assume cs:code,ds:data
start:
;段地址送段寄存器
mov ax,data
mov ds,ax
;加法计算,结果存入result
mov ax,oper1 ;将12放入ax中
mov bx,oper2 ;将45放入bx中
add ax,bx ;相加 12+45
mov result,ax ;result存答案45
;显示算式
mov bx,oper1 ;12放入bx中输出
call binidec ;输出bx
mov al,2bh ;ASCII中'+'是2BH
mov dl,al ;al放入dl才能输出
mov ah,02h ;输出加号+
int 21h
mov bx,oper2 ;45放入bx中输出
call binidec ;输出45
mov al,3dh ;ASCII中'=是3DH
mov dl,al ;放入dl才能输出
mov ah,02h
int 21h
;用户输入运算结果,存入(bx)寄存器中
call decibin ;读入放入bx中
;判断用户输入是否正常,并显示信息
;根据以上程序bx是读入的
mov ax,result ;ax放入result中
cmp ax,bx ;比较ax与bx
jz right ;jz:如果为0,那么就跳转right步骤,否则继续向下指向wrong
wrong:
lea dx,wrong_msg ;将wrong_msg字符串偏移地址给dx准备输出
jmp return ;返回到下面return中,这样可以跳过right指令
right:
lea dx,right_msg ;将right_msg字符串偏移地址给dx准备输出
jmp return ;可以不写,为了好看我还是写了
return:
mov ah,09h ;通过dx输出字符串
int 21h
mov ax,4c00h ;结束
int 21h
main endp
【总程序】
;-------------------------------
data segment
oper1 dw 12
oper2 dw 45
result dw ?
right_msg db 'right',0dh,0ah,'$'
wrong_msg db 'wrong',0dh,0ah,'$'
crlf db 0dh,0ah,'$'
data ends
;===================================
code segment
;------------------------------------------------------------
main proc far
assume cs:code,ds:data
start:
;段地址送段寄存器
mov ax,data
mov ds,ax
;加法计算,结果存入result
mov ax,oper1
mov bx,oper2
add ax,bx
mov result,ax
;显示算式
mov bx,oper1
call binidec
mov al,2bh
mov dl,al
mov ah,02h
int 21h
mov bx,oper2
call binidec
mov al,3dh
mov dl,al
mov ah,02h
int 21h
;用户输入运算结果,存入(bx)寄存器中
call decibin
;判断用户输入是否正常,并显示信息
;bx是读入的,ax存result
mov ax,result
cmp ax,bx
jz right
wrong:
lea dx,wrong_msg
jmp return
right:
lea dx,right_msg
jmp return
return:
mov ah,09h
int 21h
mov ax,4c00h
int 21h
main endp
;------------------------------
binidec proc near
;把BX寄存器中的数以十进制数的形式在屏幕上显示出来
mov cx,10000d
call dec_div
mov cx,1000d
call dec_div
mov cx,100d
call dec_div
mov cx,10d
call dec_div
mov cx,1d
call dec_div
ret
binidec endp
;------------------------------
dec_div proc near
;除法运算:(bx)/(cx)
;入口参数:(bx)=被除数,(cx)=除数
;出口参数:(bx)<--余数,商显示
mov ax,bx
mov dx,0
div cx
mov bx,dx
mov dl,al
add dl,30h
mov ah,02h
int 21h
ret
dec_div endp
;------------------------------
decibin proc near
;从键盘输入一个十进制数,存入BX寄存器中
mov bx,0
getchar:
mov ah,01h
int 21h
sub al,30h
jl exit
cmp al,9d
jg exit
cbw ;将al扩充至ax
mov cx,10
xchg ax,bx
mul cx
add bx,ax
jmp getchar
exit:
ret
decibin endp
;--------------------------------
code ends
;===================================
end start
注意其他细节不能丢,如ret
,ends
,end start
等
文章评论