汇编个位数求和实验


title: 汇编求和实验

keywords: 汇编

tags: [汇编]

categories: 嵌入式


汇编求和实验

刚开始学习汇编 给大家做个参考

实验 5 子程序 5.1 实验目的 ①掌握利用堆栈传递参数的子程序调用方法。 ②过程调用伪指令:PROC,ENDP,NEAR和FAR。 ③8088指令:CALL,RET,RETn。 5.2 实验类型 验证型实验\2. 操作步骤 ①输入,编译并运行程序。 ②用emu8086运行此程序,观察并记录每次过程调用及进出栈指令前后的SP和堆栈内容。 ③记录最后结果:SUM1,SUM2的段及偏移地址和它们的内容。 ④修改并自编程序,使得在屏幕上可以输入任意6个十进制数字,同时在屏幕上输出SUM1 的结果(要求输出十进制数字,打印出有效2位数即可)。

  1. AX:这是一个通用寄存器,通常用于算术和逻辑操作。在这段程序中,它被用来存储 DATAS 段的地址,然后这个地址被移动到 DS 寄存器。

  2. DS:这是一个段寄存器,用于存储数据段的地址。在这段程序中,它被设置为 DATAS 段的地址,这样程序就可以访问在 DATAS 段中定义的数据了。

  3. SI:这是一个索引寄存器,通常用于存储数组或字符串的索引。在这段程序中,它被用来存储 DATA 数组的当前索引。

  4. CX:这是一个计数寄存器,通常用于存储循环的次数。在这段程序中,它被设置为6,表示输入循环的次数。

  5. DX:这是一个通用寄存器,通常用于I/O操作。在这段程序中,它被用来存储字符串的地址,然后这个地址被用于 INT 21H 中断,以打印字符串。

  6. AH:这是 AX 寄存器的高8位,通常用于存储操作码。在这段程序中,它被设置为9,表示打印字符串的操作。

  7. DI:这是一个索引寄存器,通常用于存储数组或字符串的索引。在这段程序中,它被初始化为0,用于打印总和。

    修改并自编程序,使得在屏幕上可以输入任意6个十进制数字,同时在屏幕上输出SUM1 的结果(要求输出十进制数字,打印出有效2位数即可)。

    DATAS SEGMENT
    string_1 DB 'input','' ; 提示输入 string_2 DB 'input again','' ; 无效输入的错误消息
    string_3 DB ' ','' ; 空格字符 DATA DW 10 DUP(?) ; 存储输入数字的数组 message DB 0ah,'sum:',0DH,'' ; 总和输出的消息
    DATAS ENDS

    STACKS SEGMENT
    DW 256 dup(?)
    STACKS ENDS

    CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS

    START:
    MOV AX,DATAS
    MOV DS,AX ; 设置DS寄存器指向DATAS段
    MOV SI, 0 ; 指针初始化
    MOV CX, 6 ; 循环次数

     MOV DX, OFFSET string_1 ; 提示输入
     MOV AH, 9
     INT 21H
    

    Lp:
    CALL Input ; 调用输入子程序
    ADD SI, 2 ; 指针增加2(每个输入数字占2个字节)
    Loop Lp ; 循环直到所有数字输入完毕

     MOV DX, OFFSET message ; 打印总和消息
     MOV AH, 9
     INT 21H
    
     CALL Get_sum ; 调用Get_sum子程序计算总和
    
     MOV DX, AX
     ADD DX, 30H
     MOV AH, 2
     INT 21H
     
     MOV AH, 4CH 
     INT 21H
    

    Input PROC Near
    push AX
    push BX
    push CX
    push DX

     MOV BX, 0 
     CLC ; 清除进位标志
     MOV DX, 0 
    
     Lp_0:
         MOV AH, 1
         INT 21H ; 从输入中读取一个字符
    
         CMP AL, 20H ; 检查输入是否为空格字符
         JE L_CRLF ; 如果是空格,跳转到L_CRLF
         
         SUB AL, 30H ; 将ASCII转换为整数
         MOV AH, 0 ; 清除AH寄存器
         XCHG AX, BX ; 交换AX和BX寄存器
         JMP Lp_0 ; 继续输入循环
    
    
     L_CRLF: ; 输入结束标记(换行)
         MOV DX, 0
         MOV DATA[SI], BX ; 将输入数字存储在DATA数组中
         POP DX
         POP CX
         POP BX
         POP AX
         RET
    

    Input ENDP

    Get_sum PROC NEAR
    PUSH BX
    PUSH CX

     MOV BX, 0
     MOV CX , 6
     MOV DI, 0
    

    LOP1:
    MOV AX, DATA[DI]
    ADD BX, AX
    ADD DI , 2
    LOOP LOP1

     MOV AX, BX
     POP BX
     POP CX
     RET
    

    Get_sum ENDP

    CODES ENDS
    END START

Input过程是一个子程序,用于读取用户的输入。它首先将AX、BX、CX和DX寄存器的值压入堆栈以保存它们的当前状态。然后,它使用DOS中断21H的功能1来读取用户的输入。如果输入是空格(ASCII值为20H),则结束输入;否则,将输入的ASCII值转换为数字,并存储在BX寄存器中。最后,将BX寄存器的值存储在DATA数组中,并恢复AX、BX、CX和DX寄存器的值。

Get_sum过程是另一个子程序,用于计算DATA数组中的所有数字的和。它首先将BX和CX寄存器的值压入堆栈以保存它们的当前状态。然后,它初始化BX寄存器为0,用于存储和;初始化CX寄存器为6,表示要加的数字的数量;初始化DI寄存器为0,表示数组的索引。然后,它在循环中将DATA数组中的每个数字加到BX寄存器中。最后,将和存储在AX寄存器中,并恢复BX和CX寄存器的值。

但这个有致命缺点

笑死了 直接加0x30得到十进制数字就是 只有0-9可以正常输出结果

首先,它将12赋值给AX寄存器,然后将10赋值给CL寄存器。然后,它使用div cl指令将AX寄存器的值除以CL寄存器的值。在这个操作后,商(也就是十位数)存储在AL寄存器中,余数(也就是个位数)存储在AH寄存器中。然后,它将AH寄存器的值复制到BH寄存器中。

然后,它检查AL寄存器的值是否为0。如果AL寄存器的值为0,那么它将跳转到tito标签,否则,它将继续执行。

接下来,它将AL寄存器的值复制到DL寄存器中,然后将DL寄存器的值增加30H(因为在ASCII编码中,数字字符的编码是从30H开始的)。然后,它将AH寄存器的值设置为2,然后调用DOS中断21H的功能2,将DL寄存器中的字符输出。

tito标签处,它将BH寄存器的值复制到DH寄存器中,然后将DH寄存器的值增加30H。然后,它将AH寄存器的值设置为2,然后调用DOS中断21H的功能2,将DH寄存器中的字符输出。

DATAS SEGMENT
    string_1 DB 'input','$' ; 提示输入
    string_2 DB 'input again','$' ; 无效输入的错误消息
    string_3 DB ' ','$' ; 空格字符
    DATA  DW 6 DUP(?) ; 存储输入数字的数组
    message  DB 'sum:',0ah,'$' ; 总和输出的消息
DATAS ENDS

STACKS SEGMENT
    DW 256 dup(?) 
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS

START:
    MOV AX,DATAS
    MOV DS,AX ; 设置DS寄存器指向DATAS段
    MOV SI, 0  ; 指针初始化
    MOV CX, 6 ; 循环次数

    MOV DX, OFFSET string_1 ; 提示输入
    MOV AH, 9
    INT 21H

Lp:
    CALL Input ; 调用输入子程序
    ADD SI, 2 ; 指针增加2(每个输入数字占2个字节)
    Loop Lp ; 循环直到所有数字输入完毕

  
    MOV DX, OFFSET message ; 打印总和消息
    MOV AH, 9
    INT 21H

    CALL Get_sum ; 调用Get_sum子程序计算总和存到ax
                   
    mov cl, 10
    div cl     
    mov bh,ah 

    cmp al, 0
    je tito          ;十位为零 跳转tito

    MOV Dl, al  
    ADD dl, 30H
    MOV AH, 2
    INT 21H        

tito:
    MOV Dl, bh  
    ADD dl, 30H
    MOV AH, 2
    INT 21H 


    

Input PROC Near
    push AX 
    push BX
    push CX 
    push DX 

    MOV BX, 0 
    CLC ; 清除进位标志
    MOV DX, 0 

    Lp_0:
        MOV AH, 1
        INT 21H ; 从输入中读取一个字符

        CMP AL, 20H ; 检查输入是否为空格字符
        JE L_CRLF ; 如果是空格,跳转到L_CRLF
        
        SUB AL, 30H ; 将ASCII转换为整数
        MOV AH, 0 ; 清除AH寄存器
        XCHG AX, BX ; 交换AX和BX寄存器
        JMP Lp_0 ; 继续输入循环


    L_CRLF: ; 输入结束标记(换行)
        MOV DX, 0
        MOV DATA[SI], BX ; 将输入数字存储在DATA数组中
        POP DX
        POP CX
        POP BX
        POP AX
        RET
Input ENDP

Get_sum PROC NEAR
    PUSH BX
    PUSH CX

    MOV BX, 0
    MOV CX , 6
    MOV DI, 0

LOP1:
    MOV AX, DATA[DI]
    ADD BX, AX
    ADD DI , 2
    LOOP LOP1


    MOV AX, BX
    POP BX
    POP CX
    RET
Get_sum ENDP

CODES ENDS
END START

如此我们便完成这节课的任务了

相关推荐
小A15911 分钟前
STM32完全学习——SPI接口的FLASH(DMA模式)
stm32·嵌入式硬件·学习
岁岁岁平安33 分钟前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA37 分钟前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
qq_5895681042 分钟前
数据可视化echarts学习笔记
学习·信息可视化·echarts
兔C2 小时前
微信小程序的轮播图学习报告
学习·微信小程序·小程序
海海不掉头发2 小时前
苍穹外卖-day05redis 缓存的学习
学习·缓存
小木_.3 小时前
【Python 图片下载器】一款专门为爬虫制作的图片下载器,多线程下载,速度快,支持续传/图片缩放/图片压缩/图片转换
爬虫·python·学习·分享·批量下载·图片下载器
一棵开花的树,枝芽无限靠近你3 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器
犬余3 小时前
设计模式之桥接模式:抽象与实现之间的分离艺术
笔记·学习·设计模式·桥接模式
啊瞑4 小时前
学习记录:配置mybatisplus的分页查询插件,mybatis-plus-jsqlparser 依赖
学习