首页 > 编程语言 >汇编实战!手把手教你从“计算器”入门汇编语言

汇编实战!手把手教你从“计算器”入门汇编语言

时间:2023-10-12 23:44:25浏览次数:48  
标签:fq di 汇编语言 手把手 mov 运算符 计算器 bx cmp

  • 基于汇编语言的简单整数计算器设计与实现

 

(此代码仅供学习使用,请勿用作其他用途)

摘要

本论文介绍了一款使用汇编语言编写的简单整数计算器程序,该程序支持基本的四则运算操作,并能处理包含括号的数学表达式。本文通过分析程序的代码结构,宏定义、数据段、子程序以及关键功能的实现,详细介绍了其设计与实现。同时,还讨论了程序的输入输出流程、符号优先级处理、运算逻辑、错误处理机制等方面的内容,以及代码中所使用的宏定义的功能。通过本文的阐述,读者将能够了解汇编语言中如何实现一个简单但完整的计算器程序。

引言

计算器是现代计算机科学中的一个重要应用,能够进行数学运算,解决各种实际问题。虽然现代计算器通常是软件应用程序,但在本文中,我们将介绍如何使用汇编语言设计和实现一个简单的整数计算器。该计算器能够执行加法、减法、乘法、除法等基本运算,同时支持使用括号改变运算的优先级。

 

数据段(Datas Segment)

程序的数据段包括字符串、标志、数值和运算符缓冲区。其中,字符串用于用户界面和错误信息的显示,标志用于跟踪输入状态,数值缓冲区用于存储数字,运算符缓冲区用于存储运算符和其优先级。这些数据段在程序运行时将用于输入、输出和计算。

宏定义

程序中使用了三个宏定义,分别是showfqhchh。这些宏用于实现代码的复用和简化,使代码更加易读。show宏用于显示字符串,fq宏用于为运算符赋权值,hchh宏用于在控制台输出时添加回车换行。

主程序(Main Procedure)

主程序是程序的入口点,它包括初始化数据段、显示用户界面、处理用户输入、进行运算和输出结果。主程序使用循环来不断接收用户输入,并根据用户的操作执行相应的计算和输出。如果用户输入的表达式不合法,程序会进行错误处理并提供相应的错误提示。

子程序(Procedures)

程序中包含了多个子程序,用于实现不同的功能。其中,dyfq子程序用于为运算符赋予优先级,output子程序用于输出计算结果,ys子程序用于执行实际的运算操作。这些子程序提高了代码的可维护性和模块化程度。

运算逻辑

程序使用栈来处理运算符的优先级。栈中存储了运算符和它们的优先级,通过比较运算符的优先级来决定执行哪个运算。程序会根据用户输入的数学表达式,依次处理数字和运算符,同时根据运算符的优先级进行相应的计算。

错误处理

程序实现了错误处理机制,当用户输入的表达式存在括号不匹配、运算符不合法或其他错误情况时,程序会输出错误提示信息,并允许用户重新输入。这增加了程序的健壮性和用户友好性。

 

datas segment        str1     db 0ah,0dh,'*******************************************$'        str2     db 0ah,0dh,'*          1   2   3   4   5              *$'        str3     db 0ah,0dh,'*          6   7   8   9   0              *$'        str4     db 0ah,0dh,'*          +   -   *   /   =              *$'        str5     db 0ah,0dh,'*******************************************$'        str6     db 0ah,0dh,  'please input a formula:  $'        str7     db 'continue(y/n)$'        sign1    dw 0                                                            ;值为0代表输入的不是数字,为1代表输入的是数字        sign2    dw 0,0                                                          ;值为0代表输入的符号是匹配的,为1输入的符号不匹配        number   dw 20 dup(0)                                                    ;保存输入的数值        operator db '$'                                                          ;判断输入的运算符是否为空                 db 10 dup(0)                                                    ;保存该运算符对应的权值        error    db 'wrong!$' datas ends
STACKS SEGMENT         STACKS ENDS
show macro str               ;宏定义,显示字符串             lea dx,str             mov ah,9             int 21h endm fq macro ascii,a,b              ;宏定义,给运算符赋权值             cmp al,ascii             jne s&a             mov ch,b             jmp s7 endm hchh macro                   ;宏定义,回车换行             mov ah,2             mov dl,0dh             int 21h             mov ah,2             mov dl,0ah             int 21h endm
codes segment main proc far               assume cs:codes,ds:datas        start:               mov    ax,datas               mov    ds,ax               lea    di,number               lea    si,operator               show   str1               show   str2               show   str3               show   str4               show   str5               show   str6               mov    ax,0               mov    bx,0               mov    cx,0               mov    dx,0        start1:               hchh        input: mov    ah,1               int    21h               cmp    al,'='               je     let0               cmp    al,1bh               je     exit               cmp    al,28h                  ;第二种情况,第一次输入的与28h也就是‘(’比较               jb     input                   ;小于28h=(则重新输入  因为不管数字还是符号都比(大               cmp    al,39h               ja     input                   ;大于39h=9则重新输入  再大也用不着               cmp    al,2fh                  ;判断是数字还是符号               jbe    let1                    ;是符号转入响应操作               inc    word ptr sign1          ;是数字的话将数字标志位加1               sub    al,30h                  ;ASCII码与数字差               mov    ah,0               xchg   ax,[di]                 ;mul用ax中数乘源操作数               mul    bx               mov    bx,10               xchg   ax,[di]               add    [di],ax               jmp    input               call   fun               ret main endp fun proc near                                ;***********************************************************
       let0:                 cmp    word ptr sign2,0        ;判断配对标志位               je     let1                    ;经过左括号和右括号抵消为0则跳转               jmp    let8                    ;否则跳转到bc显示输入错误        let1:                 cmp    word ptr sign1,0               je     let2               add    di,2                    ;               mov    word ptr sign1,0        ;将数字标志位sign1复0        let2:                 call   dyfq                    ;设定优先级               cmp    ch,5                    ;判断输入的符号是否是左括号               jne    let3                    ;不是则判断输入的是否是右括号               inc    word ptr sign2          ;是左括号,括号标志位sign2加1        let3:                 cmp    ch,1                    ;判断输入的是否是右括号               jne    let4               dec    word ptr sign2          ;是右括号,括号标志位减1        let4:                 cmp    byte ptr[si],'$'        ;判断运算符存储区是否为空               je     let6               cmp    ch,[si]                 ;[si]的内容为前一个符号或其权值               ja     let6               cmp    byte ptr[si],'('               jne    let5               dec    si               jmp    input        let5:                 dec    si               mov    cl,[si]               call   ys                      ;判断是什么运算符并进行相应的计算               jmp    let4        let6:                 cmp    ch,0                    ;判断是否是等号               je     output               cmp    ch,1               je     input                   ;“)”不保存,输入下一个数               inc    si               mov    [si],al                 ;保存符号               inc    si               cmp    ch,5                    ;判断是否是左括号               jne    let7               mov    ch,2                    ;改变(的权值        let7:                 mov    [si],ch                 ;紧跟着保存符号的权值               jmp    input        let8:                 lea    dx,error               mov    ah,9               int    21h               jmp    exit               ret fun endp                                     ;********************************************************************** dyfq proc                                    ;子程序dyfq调用宏fq,判断优先级               fq     28h,1,5                 ;调用宏fq为(赋权值        s1:    fq     29h,2,1                 ;调用宏fq为)赋权值        s2:    fq     2ah,3,4                 ;调用宏fq为*赋权值        s3:    fq     2fh,4,4                 ;调用宏fq为/赋权值        s4:    fq     2bh,5,3                 ;调用宏fq为+赋权值        s5:    fq     2dh,6,3                 ;调用宏fq为-赋权值        s6:    fq     3dh,7,0                 ;调用宏fq为=赋权值        s7:    ret dyfq endp                                    ;*********************************************        output:                               ;输出运算结果               sub    di,2               cmp    word ptr[di],0               jge    k1               neg    word ptr[di]            ;求负数的绝对值               mov    dl,'-'               mov    ah,2               int    21h        k1:    mov    bx,10000               mov    cx,5               mov    si,0        k2:    mov    ax,[di]               cwd                            ;字到双字符的扩展               div    bx               mov    [di],dx               cmp    al,0               jne    k3               cmp    si,0               jne    k3               cmp    cx,1               je     k3               jmp    k4        k3:    mov    dl,al               add    dl,30h               mov    ah,2               int    21h               mov    si,1        k4:    mov    ax,bx                   ;实现进制转换               mov    dx,0               mov    bx,10               div    bx               mov    bx,ax               loop   k2               hchh               show   str7               mov    ah,1               int    21h               cmp    al,'n'                  ;判断是否继续输入,输入n则结束操作               je     exit               cmp    al,'N'               je     exit               mov    word ptr[di+2],0               lea    di,number               lea    si,operator               jmp    start1        exit:                 mov    ah,4ch               int    21h ys proc near                                 ;子程序,进行相应的运算               push   ax               mov    ax,0               mov    bx,0               cmp    cl,2ah                  ;乘法运算               jne    chu               sub    di,2               xchg   bx,[di]               sub    di,2               xchg   ax,[di]               imul   bx               mov    [di],ax               add    di,2               jmp    finish        chu:                 cmp    cl,2fh                  ;除法运算               jne    jia               sub    di,2               xchg   bx,[di]               sub    di,2               xchg   ax,[di]               cwd               idiv   bx               mov    [di],ax               add    di,2               jmp    finish        jia:                 cmp    cl,2bh                  ;加法运算               jne    jian               sub    di,2               xchg   bx,[di]               sub    di,2               add    [di],bx               add    di,2               jmp    finish        jian:                 cmp    cl,2dh                  ;减法运算               jne    finish               sub    di,2               xchg   bx,[di]               sub    di,2               sub    [di],bx               add    di,2        finish:               pop    ax               ret ys endp                                      ;************************************************************** codes ends     end start     运行截图:  

 

.

 

标签:fq,di,汇编语言,手把手,mov,运算符,计算器,bx,cmp
From: https://www.cnblogs.com/zzbcoder/p/17760895.html

相关文章

  • 忽视日志吃大亏,手把手教你玩转 SpringBoot 日志
    一、日志重要吗程序中的日志重要吗?在回答这个问题前,笔者先说个事例:❝笔者印象尤深的就是去年某个同事,收到了客户反馈的紧急bug。尽管申请到了日志文件,但因为很多关键步骤没有打印日志,导致排查进度很慢,数个小时都没能排查到问题,也无法给出解决对策。导致了客户程序一直阻断,最......
  • 11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查
    11.用Rust手把手编写一个wmproxy(代理,内网穿透等),实现健康检查项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://github.com/tickbh/wmproxy健康检查的意义健康检查维持着系统的稳定运行,极大的加速着服务的响应时间,并保证服务器不会把消息包转......
  • 可实现加、减、乘、除、开平方的计算器软件的实验设计
    可实现加、减、乘、除、开平方的计算器软件的实验设计1、思路代码:#include<stdio.h>#include<math.h>//牛顿迭代法计算平方根doublesqrt_newton(doublex){doubleguess=x/2.0;//初始猜测值为x的一半doubledelta=0.000001;//误差范围while(fabs(guess*gues......
  • 工程实践之高精度计算器
    说明本代码使用easyx绘制计算器界面,同时使用高精度算法实现大整数的连续运算前提准备需要安装easyx图形库,具体安装和使用流程请点击链接查看代码怎么用需要新建一个工程,向工程中添加头文件和源代码,或者先把所有头文件都提取出来放到一个新的cpp(虽然是c语言,但是easyx底层实现用......
  • Langchain-Chatchat项目:3-Langchain计算器工具Agent思路和实现
      本文主要讨论Langchain-Chatchat项目中自定义Agent问答的思路和实现。以"计算器工具"为例,简单理解就是通过LLM识别应该使用的工具类型,然后交给相应的工具(也是LLM模型)来解决问题。一个LLM模型可以充当不同的角色,要把结构化的Prompt模板写好,充分利用LLM的Zero/One/Few-Shot能力......
  • lesson9 简易计算器-3 内部类 更好的包装 访问 外部的属性和方法
    内部类更好的包装访问外部的属性和方法  packagecom.zym.lesson9;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;......
  • lesson9 简易计算器-2 面向对象的属性和方法写法
     packagecom.zym.lesson9;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;publicclassTestCalc2{publicsta......
  • lesson9 简易计算器-1
        packagecom.zym.lesson9;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;//简易计算器publicclassTestCa......
  • 导数计算器(Derivative Calculator)
    导数计算器(DerivativeCalculator) https://www.derivative-calculator.net/​a*e^x/(1+abs(x))......
  • 基于MFC框架的计算器小程序
    MFC介绍:MFC(MicrosoftFoundationClasses)是微软公司开发的一组C++类库,旨在简化Windows应用程序的开发。它提供了一系列用于创建和管理图形用户界面(GUI)的类和函数,为开发人员提供了丰富的工具和资源,用于构建功能强大的Windows应用程序。我使用VisualStudio2022的MFC模板开发的我......