汇编语言 实验四 子程序结构

2022年2月4日 上午1:28 汇编语言

实验四 子程序结构

【实验目的】

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的时候首先需要交换AXBX,用到xchg ax,bx指令
3)在退出的时候需要重新设置一个exit,不能直接写retjmp不能跳转到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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注