⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arith.asm

📁 80X86的一些例子程序
💻 ASM
字号:
;******************************************************
;* 文件名:Arith.asm
;* 创建日期:2001.6.29
;* 作者:陈文尧
;* 功能:计算数学表达式,比如:12*(1+2*4)^(30-5^2)/21
;* 备注:1、本程序由本人大学时代的C++程序改编而来,
;*         目的是用来测试“未来汇编”的堆栈库函数;
;*      2、本程序可以编译成.com文件或.exe文件;
;*      3、编译本程序必需使用“未来汇编”.
;*      4、由于本程序使用了栈的库函数,所以必须释放一些
;*         多余的内存给他使用,这只要在<汇编专家>里加上
;*         "程序中释放多余内存"就会添上ModifyMemory宏,
;*         该宏有一个可选的参数,这里就不细说。
;******************************************************
include system.inc
include stdio.inc
include stack.inc
;******************************************************
;* 以下代码由汇编专家产生,不要随便修改
;******************************************************
.CODE
	ifdef __COM__
		org	100h
	endif
@@Start:
;------------------------------------------------------
; 初始化数据段
;------------------------------------------------------
	InitDS	cs
;------------------------------------------------------
; 释放多余内存
;------------------------------------------------------
	ModifyMemory	;xxx
;------------------------------------------------------
; 调用主函数
;------------------------------------------------------
	call	main
;------------------------------------------------------
; 正常返回DOS
;------------------------------------------------------
@@Exit:
	ReturnDos

;++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+ 主函数,加入实现程序功能的代码
;++++++++++++++++++++++++++++++++++++++++++++++++++++++
main	proc
      ;创建空堆栈:opStk--操作符堆栈,每个结点长度为1;
      ;            opnStk--操作数堆栈,每个结点长度为4
	CreateStack	<offset opStk>,01h
	CreateStack	<offset opnStk>,04h

	
	;事先在操作符堆栈Push一个换行符作为运算结束标志
	mov		al,0ah
	mov		opBuffer,al
	StackPush	<offset opStk>,<offset opBuffer>
	
	;打印输入数学表达式的提示语句
	Puts	<offset msg1>
	
	;输入一个字符并保存到bl
	;“未来汇编”库函数与C/C++函数的pascal方式有点类似:
	;   1、除ax、dx、cx和es以外的寄存器(在函数里值改变)事先给予保存
	;   2、返回值一个字节在al,两个在ax,四个在eax或dx:ax
	;   3、参数从左到右压栈,栈由函数填平
	;   4、出错(这对部分函数来说),则cf=1;否则cf=0
	GetChar
	mov		bl,al
	
@Begin:
	;对输入的字符(在bl)进行判断,结果在al
	call		Judge
	;判断结果是1(操作符),则跳到第一种情况进行处理
	cmp		al,01h
	jz		short @Case1
	;判断结果是2(数字),则跳到第二种情况进行处理
	cmp		al,02h
	jz		short @Case2
	;判断结果是3(空格),则跳到第三种情况进行处理
	cmp		al,03h
	jz		short @Case3
	;其它则出错
	jmp		Error
	
	;第三种情况(空格),略过空格,重新输入一个字符,继续循环
@Case3:
      GetChar
      mov		bl,al
      jmp		@Begin
      
	;第二种情况(数字)
@Case2:
	sub		esi,esi
@Case2@Begin:
      ;edi=esi*10
	imul		edi,esi,0ah
	;esi=读入的数
	mov		esi,ebx
	and		esi,000000ffh
	sub		esi,'0'
	;esi+=edi
	add		esi,edi
	;读入字符,判断是否仍是数字
	GetChar
	mov		bl,al
	call		Judge
	cmp		al,02h
	;是数字,继续算数
	jz		@Case2@Begin
	;不是数字,则把得到的数压入操作数栈,继续循环
      mov		opnBuffer,esi
      StackPush	<offset opnStk>,<offset opnBuffer>
      jmp		@Begin
      
      ;第一种情况(操作符)
@Case1:
      ;求上一个操作符优先级别
      StackTop	<offset opStk>,<offset opBuffer>
      mov		al,opBuffer
      call		f
      ;求当前操作符优先级,并与上一操作符优先级别比较
      call		g
      cmp		al,ah
      jb		short @b
      ja		short @a
      ;两者相等,可能是一对括号或两个换行符(结束标记)
      ;前者,则读入一个字符,继续循环;后者循环结束
      StackPop	<offset opStk>,<offset opBuffer>
      cmp		opBuffer,0ah
      jz		short @End
      GetChar
      mov		bl,al
      jmp		@Begin      
@a:
      ;当前操作符优先级高。当前操作符压栈,读入字符,继续循环
      mov		opBuffer,bl
      StackPush	<offset opStk>,<offset opBuffer>
      GetChar
      mov		bl,al
      jmp		@Begin
@b:
      ;当前操作符优先级低。取出上个操作符,并判断操作数栈是否小于2
      ;小于2出错;否则再取出两个操作数,用取出的操作符对它们进行运算
      ;运算结果压入操作数栈。继续循环
      StackPop	<offset opStk>,<offset opBuffer>
      StackLength	<offset opnStk>
      cmp		ax,0002h
      jnl		short @Skip
      mov		bl,opBuffer
      jmp		short Error
@Skip:
      StackPop	<offset opnStk>,<offset opnBuffer>
      mov		esi,opnBuffer
      StackPop	<offset opnStk>,<offset opnBuffer>
      mov		edi,opnBuffer
      call		Operation
      mov		opnBuffer,edi
      StackPush	<offset opnStk>,<offset opnBuffer>
      jmp		@Begin
@End:
      ;操作数栈是否正常
      StackLength	<offset opnStk>
      cmp		ax,0001h
      jnz		short Error
      ;打印运算结果
      Puts		<offset msg3>
      StackPop	<offset opnStk>,<offset opnBuffer>
      PutLong	<word ptr opnBuffer+02h>,<word ptr opnBuffer>
	;
@Return:
	ret
main	endp

Error proc near
      Puts		<offset msg2>
      PutChar	bx
      ClearStack	<offset opnStk>
      ClearStack	<offset opStk>
      mov		ax,4c01h
      int		21h
Error endp

;判断字符:0、非法字符;1、运算符号;2、数字;3、空格
Judge proc near
      cmp	bl,'+'
      jz	short @Judge1
      cmp	bl,'-'
      jz	short @Judge1
      cmp	bl,'*'
      jz	short @Judge1
      cmp	bl,'/'
      jz	short @Judge1
      cmp	bl,'^'
      jz	short @Judge1
      cmp	bl,0ah
      jz	short @Judge1
      cmp	bl,'('
      jz	short @Judge1
      cmp	bl,')'
      jz	short @Judge1
      cmp	bl,'0'
      jb	short @NextJudge
      cmp	bl,'9'
      ja	short @NextJudge
      mov	al,02h
      ret
@NextJudge:
      cmp	bl,' '
      jz	short @Judge3
      cmp	bl,09h
      jz	short @Judge3
      mov	al,00h
      ret
@Judge1:
      mov	al,01h
      ret
@Judge3:
      mov	al,03h
      ret
Judge endp

;f、g函数:判断操作符的优先级别
f proc near
  cmp		al,'+'
  jz		short @f4
  cmp		al,'-'
  jz		short @f4
  cmp		al,'*'
  jz		short @f6
  cmp		al,'/'
  jz		short @f6
  cmp		al,'('
  jz		short @f2
  cmp		al,')'
  jz		short @f9
  cmp		al,'^'
  jz		short @f6
  mov		ah,01h
  ret
@f2:
  mov		ah,02h
  ret
@f4:
  mov		ah,04h
  ret
@f6:
  mov		ah,06h
  ret
@f9:
  mov		ah,09h
  ret
f endp

g proc near
  cmp		bl,'+'
  jz		short @g3
  cmp		bl,'-'
  jz		short @g3
  cmp		bl,'*'
  jz		short @g5
  cmp		bl,'/'
  jz		short @g5
  cmp		bl,'('
  jz		short @g8
  cmp		bl,')'
  jz		short @g2
  cmp		bl,'^'
  jz		short @g8
  mov		al,01h
  ret
@g2:
  mov		al,02h
  ret
@g3:
  mov		al,03h
  ret
@g5:
  mov		al,05h
  ret
@g8:
  mov		al,08h
  ret
g endp

;进行运算:操作符opBuffer;第一操作数edi;第二操作数esi;结果edi
Operation proc near
          mov	al,opBuffer
          cmp	al,'+'
          jz	short @Add
          cmp	al,'-'
          jz	short @Sub
          cmp	al,'*'
          jz	short @Mul
          cmp	al,'/'
          jz	short @Div
          cmp	al,'^'
          jz	short @Pow
          mov	bl,al
          jmp	Error
@Pow:
          mov	ecx,esi
          sub	eax,eax
          inc	eax
          jcxz	short @Skip2
@PowNext:
          imul	edi
          loop	@PowNext
@Skip2:
          mov	edi,eax
          ret
@Add:
          add	edi,esi
          ret
@Sub:
          sub	edi,esi
          ret
@Mul:
          mov	eax,edi
          imul	esi
          mov	edi,eax
          ret
@Div:
          mov	eax,edi
          sub	edx,edx
          idiv	esi
          mov	edi,eax
          ret
Operation endp

msg1      db '请输入数学表达式:',00h
msg2      db '输入错误:',00h
msg3      db '计算结果:',00h
opBuffer  db ?
opnBuffer dd ?
opStk	    FSTACK	<>
opnStk    FSTACK	<>
;******************************************************
;* 标志程序结束并指定程序入口
;******************************************************
	end	@@Start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -