汇编个位数求和实验


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

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

相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习