汇编语言程序设计——仿win7计算器(功能部分)

   

           下面代码实现的计算机基本的功能,包括加、减、乘、除、求倒、开方、百分比、记忆相关功能等,支持快捷键,显示也可以分段显示,如下图。

            界面部分源码:http://blog.csdn.net/zhangjiajie023/article/details/7728268

            整体设计参考自:http://www.cnblogs.com/kingwolfofsky/archive/2011/07/07/2100375.html

 

        不多说了,下面贴出源代码,挺多的:

;********************************************
;      仿win7计算器                         *
;                                           *
;                CS0****                    *
;                     U200915**             *
;********************************************

.386
.model flat,stdcall
option casemap:none

;********************************************

include  d:\masm32\include\windows.inc
include  d:\masm32\include\shell32.inc
include  d:\masm32\include\user32.inc
include  d:\masm32\include\comctl32.inc
include  d:\masm32\include\masm32.inc
include  d:\masm32\include\kernel32.inc

includelib  d:\masm32\lib\user32.lib
includelib  d:\masm32\lib\comctl32.lib
includelib  d:\masm32\lib\masm32.lib
includelib  d:\masm32\lib\kernel32.lib
includelib  d:\masm32\lib\shell32.lib

;*******************************************

IDB_0  EQU  100
IDB_1  EQU  101
IDB_2  EQU  102
IDB_3  EQU  103
IDB_4  EQU  104
IDB_5  EQU  105
IDB_6  EQU  106
IDB_7  EQU  107
IDB_8  EQU  108
IDB_9  EQU  109
;------------------------
IDB_NEG    EQU  110
IDB_POINT  EQU  111
IDB_DIV    EQU  112
IDB_MUL    EQU  113
IDB_SUB    EQU  114
IDB_ADD    EQU  115
IDB_SQRT   EQU  116
IDB_PER    EQU  117
IDB_DAO    EQU  118
IDB_EQU    EQU  119
;------------------------
IDB_MC     EQU  120
IDB_MR     EQU  121
IDB_MS     EQU  122
IDB_MPLUS  EQU  123
IDB_MSUB   EQU  124
IDB_M      EQU  125
IDB_BACK   EQU  126
IDB_CE     EQU  127
IDB_C      EQU  128
;------------------------
IDT_MEMORY EQU  129
IDT_RESULT EQU  130
;------------------------
Icon          EQU  1000
IDM_COPY      EQU  1001
IDM_PASTE     EQU  1002
IDM_STANDARD  EQU  1003
IDM_SCIENCE   EQU  1004
IDM_GROUP     EQU  1006
IDM_HELP      EQU  1007
IDM_ABOUT     EQU  1008
IDM_EXIT      EQU  1009
IDM_KJJ       EQU  1010
IDM_NOTIFYICON  EQU  2000
WM_SHELLNOTIFY  EQU  2001

;**********************函数原型说明***************************

WinMain  PROTO :DWORD, :DWORD, :DWORD, :DWORD     ; 窗口主程序
Calculate  PROTO :DWORD, :DWORD, :DWORD, :DWORD ; 消息处理程序
Init  PROTO                        ; 初始化
NumBtn  PROTO :DWORD             ; 数字按键消息处理程序
AddDelNeg  PROTO               ; 添加或删除‘-’号
SavePreData  PROTO          ; 保存当前文本框中的数据
ShowMemory  PROTO			   ; 显示存储信息
GetResult  PROTO				   ; 双目运算
MemoryFunc PROTO :DWORD      ; 记忆加或记忆减
GroupNum  PROTO					       ; 数字分组
UnGroupNum  PROTO			           ; 数字取消分组 

;****************************数据段****************************
.data
      CommandLine  DD  0
      Output       DB  "0",0,40 DUP(0)
      IsStart      DB  0
      IsError      DB  0  
      HasPoint     DB  0
      HasEqual     DB  0          ;判断是否存在等号
      HasNeg1      DB  0					;各数是否有‘-’号
      HasNeg2      DB  0
      ResultNeg    DB  0
      MemoryNeg    DB  0
      IsShowMem    DB  0          ;是否显示记忆
      IsGroup      DB  0         
      Operator     DB  '.'        ;记录双目运算符
      Buffer       DB  '.'        ;用于暂存字符     
      Memory       DQ  0.0
      Temporary    DQ  0.0        ;临时数据
      Operand1     DQ  0.0        ;操作数1
      Operand2     DQ  0.0
      Result       DQ  0.0        
      NumLittle    REAL8    1.0E-12
      Num100       REAL8    100.0     ;实数100
      NotifyIcon   NOTIFYICONDATA<>   ;通知栏图标
;------------------------------------------------------------           
.data?
      hInstance    DD  ?
      hEdit1       DD  ?        ; 下面输出文本框句柄
      hEdit2       DD  ?        ; 上面输出文本框句柄
      hTextM       DD  ?
      hMenu        DD  ?
      hIcon        DD  ?
      hGlobal      HANDLE  ?
      pGlobal      DB  ?
;------------------------------------------------------------
.const
      DivError     DB  "除数不能为0",0
      FuncError    DB  "输入函数无效",0
      About        DB  '作者: 张**', 0ah,0dh,'时间:2010-10-10',0
      ShortCuts    DB  '字母->功能:X->倒数  N->取反  S->开方  E->CE  R->C',0ah,0dh,
                       '            Y->MC  U->MR  I->MS  O->M+  P->M-',0
      HelpFile     DB  "help.hlp",0
      ProgramName  DB  "计算器",0
      DialogName   DB  "Calculator",0
      MenuName     DB  "Menu",0
      IconName     DB  "Icon",0
      TextM        DB  'M',0
;----------------------------------------------------------

;***************************代码段**************************
.code
   start:
   
;----------------------------------------------------------
   invoke GetModuleHandle,NULL
   mov hInstance,eax
   invoke WinMain,hInstance,0,0,SW_SHOWDEFAULT
   invoke ExitProcess,eax
;---------------------------------------------------------
   
WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hWnd:HWND
        
        mov wc.cbSize,sizeof WNDCLASSEX
        mov wc.style,CS_BYTEALIGNWINDOW or CS_BYTEALIGNWINDOW
        mov wc.lpfnWndProc,OFFSET Calculate
        mov wc.cbClsExtra,0
        mov wc.cbWndExtra,DLGWINDOWEXTRA
        mov eax,hInst
        mov wc.hInstance,eax
        mov wc.hbrBackground,COLOR_BTNFACE+1
        mov wc.lpszMenuName,OFFSET MenuName
        mov wc.lpszClassName,OFFSET DialogName
        invoke LoadIcon,hInst,addr IconName
        mov wc.hIcon,eax
        invoke LoadCursor,NULL,IDC_ARROW
        mov wc.hCursor,eax
        mov wc.hIconSm,0
        
        invoke RegisterClassEx,addr wc
        invoke CreateDialogParam,hInst,addr DialogName,0,addr Calculate,0        
        mov hWnd,eax
        invoke ShowWindow,hWnd,CmdShow
        invoke UpdateWindow,hWnd
        
     StartLoop:
        invoke GetMessage,addr msg,0,0,0
        cmp eax,0
        je ExitLoop
        invoke TranslateMessage,addr msg
        invoke DispatchMessage,addr msg
        jmp StartLoop
     ExitLoop:
        mov eax,msg.wParam
        ret
       
WinMain endp
;---------------------------------------------------------------

;---------------------------------------------------------------
;消息处理程序用于处理用户消息。
;hWin:窗口句柄
;uMsg:消息标识
;param1 param2:消息所带的参数
;---------------------------------------------------------------
Calculate proc hWin:DWORD,uMsg:UINT,param1:DWORD,param2:DWORD
			LOCAL pt:POINT         
      ;-------------------------------------------------------
      .if uMsg == WM_INITDIALOG          				;	初始化窗口
              invoke GetDlgItem,hWin,IDT_RESULT
              mov hEdit1,eax
              invoke GetDlgItem,hWin,IDT_MEMORY
              mov hEdit2,eax
              invoke GetDlgItem,hWin,IDB_M  		 
              mov hTextM,eax
              invoke LoadIcon,hInstance,addr IconName
              mov hIcon,eax
              invoke SendMessage,hWin,WM_SETICON,ICON_SMALL,eax
              invoke LoadMenu,hInstance,addr MenuName
              mov hMenu,eax
              invoke SetMenu,hWin,eax
              invoke CheckMenuRadioItem,hMenu,IDM_STANDARD,IDM_SCIENCE,IDM_STANDARD,MF_BYCOMMAND ;选中标准型
              invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output  					
      ;-----------------------------------------------------------
      .elseif uMsg == WM_SIZE
         		  .if param1==SIZE_MINIMIZED        ;最小化
         					  mov NotifyIcon.cbSize,sizeof NOTIFYICONDATA
         						push hWin
         						pop NotifyIcon.hwnd
         						mov NotifyIcon.uID,IDM_NOTIFYICON
         						mov NotifyIcon.uFlags,NIF_ICON+NIF_MESSAGE+NIF_TIP
         						mov NotifyIcon.uCallbackMessage,WM_SHELLNOTIFY
         						mov eax,hIcon
         						mov NotifyIcon.hIcon,eax
         						invoke lstrcpy,addr NotifyIcon.szTip,addr ProgramName      						
         						invoke Shell_NotifyIcon,NIM_ADD,addr NotifyIcon        					
         			.endif         			
       ;---------------------------------------------------------------
       .elseif uMsg == WM_SHELLNOTIFY
         			.if param1==IDM_NOTIFYICON
         						.if(param2==WM_LBUTTONDOWN)           ;鼠标左键按下
         									invoke ShowWindow,hWin,SW_SHOW
         									invoke Shell_NotifyIcon,NIM_DELETE,addr NotifyIcon
         						.elseif(param2==WM_RBUTTONDOWN)       ;鼠标右键按下
         									invoke GetCursorPos,addr pt
         									invoke GetSubMenu,hMenu,3
         									invoke TrackPopupMenu,eax,TPM_LEFTALIGN,pt.x,pt.y,NULL,hWin,NULL
         						.endif
         			.endif
       ;----------------------------------------------------------------
       .elseif uMsg == WM_CHAR     ;热键操作
         			mov eax,param1         		
         			add eax,IDB_0
         			sub eax,'0'         			
         			.if (eax>=IDB_0) && (eax<=IDB_9)
         						invoke Calculate,hWin,WM_COMMAND,eax,0         						
         			.elseif (eax==98)
         						invoke Calculate,hWin,WM_COMMAND,IDB_POINT,0         						
         			.elseif (eax==95)
                 		invoke Calculate,hWin,WM_COMMAND,IDB_ADD,0         						
         			.elseif (eax==97)
         						invoke Calculate,hWin,WM_COMMAND,IDB_SUB,0         						
         			.elseif (eax==94)
         						invoke Calculate,hWin,WM_COMMAND,IDB_MUL,0         						
         			.elseif (eax==97)
         						invoke Calculate,hWin,WM_COMMAND,IDB_DIV,0         						
         			.elseif (eax==89)                  
         						invoke Calculate,hWin,WM_COMMAND,IDB_PER,0         						
         			.elseif (eax==60)  
         						invoke Calculate,hWin,WM_COMMAND,IDB_BACK,0         						
         			.elseif (eax==113)  
         						invoke Calculate,hWin,WM_COMMAND,IDB_EQU,0
         			;-------------------------------------------------			
         			.elseif (eax==140 || eax==172)     ; x 倒数1/x
         						invoke Calculate,hWin,WM_COMMAND,IDB_DAO,0         						
         			.elseif (eax==135 || eax==167) 		 ; s 开方
         						invoke Calculate,hWin,WM_COMMAND,IDB_SQRT,0         						
         		  .elseif (eax==130 || eax==162) 		 ; n 正负
         						invoke Calculate,hWin,WM_COMMAND,IDB_NEG,0         				
         			.elseif (eax==121 || eax==153) 		 ; e 清除当前数据
         						invoke Calculate,hWin,WM_COMMAND,IDB_CE,0         					
         			.elseif (eax==134 || eax==166) 		 ; r 初始化
         						invoke Calculate,hWin,WM_COMMAND,IDB_C,0
         			;-------------------------------------------------			
         		  .elseif (eax==141 || eax==173) 		 ; y 记忆清零
         						invoke Calculate,hWin,WM_COMMAND,IDB_MC,0         				
         			.elseif (eax==137 || eax==169) 		 ; u 显示记忆
         						invoke Calculate,hWin,WM_COMMAND,IDB_MR,0         						
         			.elseif (eax==125 || eax==157)  	 ; i 记忆当前数据
         						invoke Calculate,hWin,WM_COMMAND,IDB_MS,0         						
         		  .elseif (eax==131 || eax==163) 		 ; o 记忆加
         						invoke Calculate,hWin,WM_COMMAND,IDB_MPLUS,0         						
         		  .elseif (eax==132 || eax==164)  	 ; p 记忆减
         						invoke Calculate,hWin,WM_COMMAND,IDB_MSUB,0
         			;-------------------------------------------------		
         			.elseif (eax==119 || eax==151)  	 ; c 复制
         						invoke Calculate,hWin,WM_COMMAND,IDM_COPY,0         						
         			.elseif (eax==138 || eax==170)  	 ; v 粘贴
         						invoke Calculate,hWin,WM_COMMAND,IDM_PASTE,0         						
         			.elseif (eax==133 || eax==165)		 ; q 退出
         						invoke Calculate,hWin,WM_COMMAND,IDM_EXIT,0         						
         			.elseif (eax==155 || eax==123)		 ; g 分组
        						invoke Calculate,hWin,WM_COMMAND,IDM_GROUP,0 
        			.elseif (eax==127 || eax==159)		 ; k 快捷键
         						invoke Calculate,hWin,WM_COMMAND,IDM_KJJ,0        						
         			.elseif (eax==124 || eax==156)		 ; h 帮助
         						invoke Calculate,hWin,WM_COMMAND,IDM_HELP,0         						
         			.elseif (eax==117 || eax==149)		 ; a 关于计算器
         						invoke Calculate,hWin,WM_COMMAND,IDM_ABOUT,0
         			;-------------------------------------------------			
         			.endif
        ;---------------------------------------------------------
        .elseif uMsg == WM_COMMAND   				       ;按钮消息处理
         			mov eax,param1
         			finit
         			;---------------------------------------------
         			.if eax==IDB_C                      ;初始化
         						invoke Init
         						mov MemoryNeg,0
         						fldz
         						fstp Memory
         		  ;----------------------------------------------
         			.elseif eax==IDB_CE									;清除当前数据
         						.if IsError==1 || HasEqual==1
         									invoke Init
         									ret
         						.endif         						    						
         						fldz
         						.if Operator=='.'
         									mov IsStart,0         									
         									fst Operand1
         									mov HasNeg1,0
         						.else
         									fst Operand2
         									mov HasNeg2,0
         						.endif
         						fst Temporary
										fst Result
										finit
         						mov HasPoint,0
         						mov HasEqual,0
         						mov IsError,0
         						lea esi,Output
         						mov BYTE PTR [esi],'0'
         						mov BYTE PTR [esi+1],0 
         						invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output          					
         			;-----------------------------------------------
         			.elseif eax==IDB_BACK               ;退格
         						.if IsGroup==1
         									invoke UnGroupNum
         						.endif				         		
			         			lea esi,Output			         			
			         			.if BYTE PTR [esi+1]==0
			         					mov BYTE PTR [esi],'0'
			         					.if Operator=='.'
			         							mov IsStart,0
			         					.endif
			         			.else
			         					.while BYTE PTR [esi]!=0
			         								inc esi
			         					.endw			         						
			         					mov BYTE PTR [esi-1],0
			         			.endif
			         			invoke StrToFloat,addr Output,addr Temporary
			         			fld Temporary                  ;保存操作数
			         			.if Operator=='.'
			         					fstp Operand1
			         			.else
			         					fstp Operand2
			         			.endif
			         			.if IsGroup==1
			         					invoke GroupNum
			         			.endif
			         			invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output		
         		  ;---------------------------------------------
         			.elseif (eax>=IDB_0) && (eax<=IDB_9)       ;数字按键         						
         						.if HasEqual==1 
         						   		fldz		         									
         									fst Operand1	
         									fst Operand2
													fst Temporary
													fst Result
													finit
													mov IsStart,0
         									mov HasPoint,0
         									mov HasEqual,0
         									mov HasNeg1,0
         									mov HasNeg2,0
         									mov ResultNeg,1
         									mov Operator,'.'
         									mov IsError,0
         									lea esi,Output
         									mov BYTE PTR [esi],'0'
         									mov BYTE PTR [esi+1],0       					
         						.endif          						   						
         				    invoke NumBtn,eax		
         			;--------------------------------------------
         		  .elseif eax==IDB_POINT										;小数点
         		  			.if HasEqual==1
         		  					invoke Init
         		  			.endif        		  			
         						.if HasPoint==0
         								lea esi,Output
         								.while BYTE PTR [esi]!=0
         										inc esi
         								.endw
         								mov BYTE PTR [esi],'.'
         								mov BYTE PTR [esi+1],0
         								mov HasPoint,1
         								mov IsStart,1
         								invoke SavePreData
         								invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
         						.endif
         			;-------------------------------------------
         			.elseif eax==IDB_NEG 										;取反
         			      invoke AddDelNeg 
         			      lea esi,Output
										.if BYTE PTR [esi]=='0' && BYTE PTR [esi+1]==0
													;不加负号的情况
              			.elseif Operator=='.'
              						xor HasNeg1,1
              			.elseif Operator!='.'
              						xor HasNeg2,1
              			.endif 
										invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output												
         			;------------------------------------------
         		  .elseif (eax>=IDB_DIV) && (eax<=IDB_ADD)   ;加减乘除
         		  				.if Operator!='.' && HasEqual==0
         		  						invoke GetResult
         		  				.endif	
									  	.if eax==IDB_DIV 
		  										mov BYTE PTR Operator,'/'
		  												
		 									.elseif eax==IDB_MUL
		  										mov BYTE PTR Operator,'*'
		  												
		 									.elseif eax==IDB_SUB
		  										mov BYTE PTR Operator,'-'
		  												
		  								.elseif eax==IDB_ADD
		  										mov BYTE PTR Operator,'+'
		  												
		 							 	 	.endif
		 							 	 	
		 									mov HasEqual,0
		 									mov HasPoint,0
		 									fldz
		 									fstp Operand2
		 									mov IsStart,1
		 									invoke SendMessage,hTextM,WM_SETTEXT,0,NULL
											;------在上面文本框显示操作数1-----		
											lea esi,Output
											invoke FloatToStr,Operand1,addr Output
											.while BYTE PTR [esi]!=0
													inc esi
											.endw
											mov bl,Operator
											mov [esi],bl
											mov BYTE PTR [esi+1],0
											.if HasNeg1==1
													invoke AddDelNeg
											.endif
											invoke SendMessage,hEdit2,WM_SETTEXT,0,addr Output
											
											;------在下面文本框显示0------
											lea esi,Output
											mov BYTE PTR [esi],'0'
											mov BYTE PTR [esi+1],0
											invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output 
         			;-----------------------------------------
         			.elseif eax==IDB_EQU              ;等于
         						.if Operator!='.'
         								invoke GetResult
         						.endif         							
         			;------------------------------------------
         			.elseif eax==IDB_PER              ;百分号
         						finit
         						.if Operator=='.'
         								fld Num100
         								fld Operand1
         								fdiv ST(0),ST(1)
         								fstp Operand1
         								invoke FloatToStr,Operand1,addr Output
         								.if HasNeg1==1
         										invoke AddDelNeg
         								.endif
         								.if IsGroup==1
         										invoke GroupNum
         								.endif
         								invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output 
         								
         						.else 
											   ;功能 Op1 + Op2 % = Op1 + Op1*Op2÷100 											   
												 fld Num100
												 fld Operand2
												 fdiv ST(0),ST(1)             
												 fstp Operand2 				;Op2÷100=>Op2
												 ;--------保护操作数1及运算符-----          
												 mov bl,Operator
												 mov Buffer,bl        ;Operator=>Buffer
												 mov Operator,'*'
												 fld Operand1
												 fstp Temporary       ;Op1=>Temporary
												 mov bh,HasNeg1       ;HasNeg1=>bh
												 ;-------------------------------------
												 invoke GetResult     ;Op1*Op2÷100 =>Op1
												 ;-------运算结果给Op2-------	
												 fld Operand1
												 fstp Operand2
												 mov bl,HasNeg1
												 mov HasNeg2,bl   
												 ;-------换回Op1和运算符-----											 
												 fld Temporary
												 fstp Operand1       
												 mov HasNeg1,bh
												 mov bl,Buffer
												 mov Operator,bl      
												 invoke GetResult     ;最后一步运算												 											  
										.endif 
										mov HasEqual,1     									
         			;------------------------------------------
         			.elseif eax==IDB_DAO           ;倒数
         						lea esi,Output
         						mov bx,4000h
         						finit
         						.if Operator=='.'         ;只有一个操作数
         									fld Operand1         									         									
         									ftst
         									fstsw ax         									
         									and bx,ax                   									
         									jnz dao_error      ;Operand1==0
         							 				 							 
         									fld1               ;Operand1!=0
         									fld Operand1
         									fdiv
         									fst Result
         									fstp Operand1 
         									mov bl,HasNeg1
         						 			mov ResultNeg,bl 
         						 			mov HasEqual,1     								
         						.else                
         								 ;已经有操作数1,并且有双目操作符	,算操作数2的倒数
         						 			fld Operand2
         						 			ftst
         						 			fstsw ax
         						 			and ax,bx        						 		    		 
         						 			jnz dao_error 		 ;0perand2==0          						 										
         						 			fld1               ;0perand2!=0
         						 			fld Operand2
         						 			fdiv           		 ;ST(1) ÷ ST(0) => ST(1),弹出ST
         						 			fst Result
         						 			fstp Operand2	         						 			
         						 			mov bl,HasNeg2
         						 			mov ResultNeg,bl
         						 .endif
         						 jmp dao_show
         					dao_error:
         						  mov IsError,1
         							invoke SendMessage,hEdit1,WM_SETTEXT,0,addr DivError
         						 	mov BYTE PTR[esi],'0'
         						 	mov BYTE PTR[esi+1],0
         							ret
         						 
         					dao_show: 
         						 invoke FloatToStr,Result,addr Output
         						 .if ResultNeg==1
         						 		invoke AddDelNeg
         						 .endif
         						 lea edi,Output
         						 .while BYTE PTR[edi]!=0        ;判断结果是否有小数点
         						 		inc edi
         						 		.if BYTE PTR [edi]=='.'
         						 				mov HasPoint,1
         						 		.endif
         						 .endw
         						 .if IsGroup==1
         						 		invoke GroupNum
         						 .endif         						 
         						 invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
         			;-----------------------------------------------
         			.elseif eax==IDB_SQRT               ;开方
         						lea esi,Output
         						finit
         						.if Operator=='.'             ;只有一个操作数
         									.if HasNeg1==1					
         												jmp sqrt_error
         									.endif
         									fld Operand1
         									fsqrt
         									fst Result
         									fst Operand1 
         									mov HasEqual,1        									        									
         						.else              
         									;已经有操作数1,并且有双目操作符,算操作数2的开方
         									.if HasNeg2==1
         											jmp sqrt_error
         									.endif	
         						 			fld Operand2	 									
         						 			fsqrt
         						 			fst Result
         						 			fst Operand2
         						.endif
         						jmp sqrt_show
         						sqrt_error:
         							   mov IsError,1
         								 invoke SendMessage,hEdit1,WM_SETTEXT,0,addr FuncError
         								 mov BYTE PTR[esi],'0'
         								 mov BYTE PTR[esi+1],0
         							 	ret
         						sqrt_show: 
         						invoke FloatToStr,Result,addr Output
         						lea edi,Output
         						 .while BYTE PTR [edi]!=0        ;判断结果是否有小数点
         						 		inc edi
         						 		.if BYTE PTR [edi]=='.'
         						 				mov HasPoint,1
         						 		.endif
         						 .endw
         						.if IsGroup==1
         								invoke GroupNum
         						.endif         						
         						invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output        								  
         			;------------------------------------------------
         			.elseif eax==IDB_MC                  ;清除记忆
         					  fldz
         					  fstp Memory
         					  mov MemoryNeg,0
         					  invoke SendMessage,hTextM,WM_SETTEXT,0,NULL
         					  invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
         			;--------------------------------------------------
         			.elseif eax==IDB_MR   				     ;显示记忆
         					  invoke ShowMemory	
         			;------------------------------------------------
         		  .elseif eax==IDB_MS    					     ;记忆当前数据
         					 	.if Operator=='.' || Operator!='.' && HasEqual==1
         					 			fld Operand1
         					 			mov bl,HasNeg1	
         					 	.elseif Operator!='.' && HasEqual==0 
         					 			fld Operand2
         					 			mov bl,HasNeg2
         					 	.endif
         					
         					 	fstp Memory
         					 	mov MemoryNeg,bl
         					 	mov IsShowMem,0
         					 	invoke ShowMemory
         			;-----------------------------------------------
         			.elseif eax==IDB_MPLUS      			  ;记忆加
         					  invoke MemoryFunc,eax
         			;------------------------------------------------
         			.elseif eax==IDB_MSUB      				  ;记忆减          
         					  invoke MemoryFunc,eax
         			;------------------------------------------------
         			.elseif eax==IDM_COPY											  ;复制
         					  invoke GlobalAlloc,GMEM_MOVEABLE,35   ;配置一个内存块
                    mov hGlobal ,eax
                    invoke GlobalLock,hGlobal             ;锁定内存块
                    mov DWORD PTR pGlobal ,eax
                    lea esi,Output
                    mov edi,DWORD PTR pGlobal
                    mov ecx,35
                    rep movsb                             ;复制字符串
                    invoke GlobalUnlock,hGlobal           ;解锁内存块
                    invoke OpenClipboard, NULL            ;打开剪切板
                    invoke EmptyClipboard                 ;清空剪切板
                    invoke SetClipboardData,CF_TEXT,hGlobal ;把内存句柄交给剪贴簿
                    invoke CloseClipboard  
         			;------------------------------------------------
         			.elseif eax==IDM_PASTE
                    invoke IsClipboardFormatAvailable,CF_TEXT ;确定剪贴簿是否含有CF_TEXT格式的数据
                    invoke OpenClipboard,NULL  ;打开剪切板
                    invoke GetClipboardData,CF_TEXT       ;得到代表文字的内存块代号
                    mov hGlobal,eax
                    invoke GlobalLock ,hGlobal            ;解锁内存块
                    mov DWORD PTR pGlobal,eax
                    mov ecx,35
                    lea edi,Output
                    mov esi,eax
                    rep movsb                             ;复制字符串
                    invoke GlobalUnlock ,hGlobal          ;解锁内存块
                    invoke CloseClipboard                 ;关闭剪切板                      
                    invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output           
         			;--------------------------------------------------
         		  .elseif eax==IDM_GROUP                      ;分组
         					  .if IsGroup==0
         					  		invoke CheckMenuItem,hMenu,IDM_GROUP,MF_CHECKED
         					  		invoke GroupNum
         					  .else
         					  		invoke CheckMenuItem,hMenu,IDM_GROUP,MF_UNCHECKED
         					  		invoke UnGroupNum
         					  .endif
         					  xor BYTE PTR IsGroup,1
         					  invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
         			;---------------------------------------------------
         			.elseif eax==IDM_KJJ                        ;快捷键帮助
         					  invoke ShellAbout,hWin,addr ProgramName,addr ShortCuts,hIcon
         			;----------------------------------------------------
         			.elseif eax==IDM_HELP
         					  invoke WinHelp,hWin,addr HelpFile,HELP_CONTENTS,1
         			;---------------------------------------------------
         			.elseif eax==IDM_ABOUT
         					  invoke ShellAbout,hWin,addr ProgramName,addr About,hIcon
         			;---------------------------------------------------
							.elseif eax==IDM_EXIT
										invoke Calculate,hWin,WM_CLOSE,param1,param2
         		  .endif		
         	;-------------------------------------------------------
         	.elseif uMsg == WM_CLOSE
         				invoke Shell_NotifyIcon,NIM_DELETE,addr NotifyIcon
         				invoke EndDialog,hWin,NULL
         				invoke PostQuitMessage,0
         	;--------------------------------------------------------
         	.else
         				invoke DefWindowProc,hWin,uMsg,param1,param2  ;默认消息处理
         				ret
         	.endif
         	 ;-------------------------------------------------------
         	 invoke SetFocus,hWin
         	 mov eax,0
         	 ret
 Calculate endp	
;------------------------------------------------------------

;------------------------------------------------------------
; 初始化所有状态变量和FPU寄存器
;------------------------------------------------------------
Init  proc
			mov IsStart,0
			mov HasPoint,0
			mov HasEqual,0
			mov HasNeg1,0
			mov HasNeg2,0
			mov Operator,'.'
			mov IsError,0   
			fldz               
			fst Temporary
			fst Result
			fst Operand1
			fst Operand2     
			finit
			lea esi,Output
			mov BYTE PTR [esi],'0'
			mov BYTE PTR [esi+1],0
			invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
			invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
			invoke SendMessage,hTextM,WM_SETTEXT,0,NULL
			ret
Init endp
;-----------------------------------------------------------


;-----------------------------------------------------------
;数字按键消息处理程序  
;把按钮发送的数值eax添加在Output后面,并调用SavePreData保存
;------------------------------------------------------------                        
NumBtn proc USES eax,NUM:DWORD   
			mov eax,NUM
			sub eax,IDB_0
			add eax,'0'	
			lea esi,Output							
			.if IsStart==0 
			
					mov IsStart,1
					mov [esi],al
					mov BYTE PTR [esi+1],0
					
			.else	
					
					.if BYTE PTR [esi]=='0' && BYTE PTR [esi+1]==0 && al=='0' ; 0 再输入0
							 ret;-----不添加数字的情况--------
							 
					.elseif BYTE PTR [esi]=='0' && BYTE PTR [esi+1]==0 && al>='1' && al<='9' ; 0 再输入不为0数字
							mov [esi],al
							mov BYTE PTR [esi+1],0							
							
					.else
							.while BYTE PTR [esi]!=0
									inc esi
							.endw					
							mov [esi],al
							mov BYTE PTR [esi+1],0
					.endif
					
			.endif
			
			invoke SavePreData
			invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
			ret
NumBtn endp																															                  
;-----------------------------------------------------------


;-----------------------------------------------------------
;保存当前文本框中的数据
;如果运算符还没变变化,则当前显示的是操作数1,否则是操作数2
;-----------------------------------------------------------
SavePreData proc
		.if IsGroup==1
				invoke UnGroupNum
		.endif
		lea esi,Output
		
		.if Operator=='.'       ;当前显示的是第一个操作数
		;------------------------------------
				.if HasNeg1==1
						invoke AddDelNeg
				.endif
				
				invoke StrToFloat,addr Output,addr Operand1
				.if HasNeg1==1
						invoke AddDelNeg
				.endif		
		.else
		;-------------------------------------
				.if HasNeg2==1
						invoke AddDelNeg
				.endif
				.if IsGroup==1
						invoke UnGroupNum
				.endif
				invoke StrToFloat,addr Output,addr Operand2
				.if HasNeg2==1
						invoke AddDelNeg
				.endif
		.endif
		;-------------------------------------
		.if IsGroup==1
				invoke GroupNum
		.endif
		ret
SavePreData endp					
;-----------------------------------------------------------


;-----------------------------------------------------------
;显示存储信息
;无论Memory为何值,都在上面的文本框中显示M和Memory数值
;再按一次MR,取消显示
;------------------------------------------------------------
ShowMemory  proc	        
		.if IsShowMem==0    ;还没有显示
					invoke SendMessage,hTextM,WM_SETTEXT,0,addr TextM														
			 		invoke FloatToStr,Memory,addr Output
				  .if MemoryNeg==1
         			invoke AddDelNeg
       		.endif		 				
      		invoke SendMessage,hEdit2,WM_SETTEXT,0,addr Output
      		mov BYTE PTR IsShowMem,1	
    .else
    		 invoke SendMessage,hTextM,WM_SETTEXT,0,NULL
    		 invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
    		 mov BYTE PTR IsShowMem,0
    .endif
		ret
ShowMemory endp											
;-----------------------------------------------------------


;-----------------------------------------------------------
;在Output字符串前加上或取消‘-’号
;有'-'号,则取消;没有'-'号,则添上
;-----------------------------------------------------------
AddDelNeg proc USES ebx ecx
			lea esi,Output
			lea edi,Output
			.if BYTE PTR [esi]=='0' && BYTE PTR [esi+1]==0
					;----显示‘0’时不加----
					ret
			.endif
			;-----------没有‘-’--加上------------------
			.if BYTE PTR [esi]!='-'      
					.while BYTE PTR [esi]!=0
							inc esi
					.endw
					.while esi!=edi
							mov bl,[esi]
							mov [esi+1],bl
							dec esi
					.endw
					lea esi,Output
					mov bl,[esi]
					mov [esi+1],bl
					mov BYTE PTR [esi],'-'									
			;-----------有了‘-’--删除‘-’号------------
			.else 				              
					.while BYTE PTR [esi]!=0
							mov bl,[esi+1]
							mov [esi],bl
							inc esi
					.endw	
			;---------------------------------------------
			.endif

			ret					
AddDelNeg endp
;-----------------------------------------------------------


;-----------------------------------------------------------
;计算双目运算结果
;两个操作数都是保存的正数,正负号由HasNeg1和HasNeg2保存
;先进行绝对值的运算,再由两操作数的正负判定结果正负
;------------------------------------------------------------
GetResult  proc	USES eax ebx
			finit	
			.if IsStart==1   		
						fld Operand2
						fld Operand1
						.if Operator=='.'
									fst Result
									jmp show
									
						;++++++++++++++++++++++++++++++++++++++++++
						.elseif Operator=='+'
						  	  ;-----------------------------------
									.if HasNeg1==0 && HasNeg2==0
											fadd
											mov ResultNeg,0
									;-----------------------------------
									.elseif HasNeg1==1 && HasNeg2==0
											fcom ST(1)
											jle xiao_deng1           ;小于等于
											fsub ST(0),ST(1)         ;(-2 + 1)
											mov ResultNeg,1
											jmp over1
										xiao_deng1:                ;(-1 + 2) (-1 + 1)
											fsub ST(1),ST(0)
											fstp Result
											mov ResultNeg,0
									  over1:
									;-----------------------------------				
									.elseif HasNeg1==0 && HasNeg2==1
											fcom ST(1)
											jge da_deng2            											   
											fsub ST(1),ST(0)        ;(1 + -2)
											fstp Result
											mov ResultNeg,0
											jmp over2					 						
										da_deng2:                ;大于等于
											fsub 								 	 ;(2 + -1) (1 + -1)
											mov ResultNeg,1											
										over2:
									;-----------------------------------
									.elseif HasNeg1==1 && HasNeg2==1
											fadd
											mov ResultNeg,1
									.endif
								
						;-----------------------------------------	
						.elseif Operator=='-'
									;-----------------------------------
									.if HasNeg1==0 && HasNeg2==0
											fcom ST(1)
											jge da_deng3											  
											fsub ST(1),ST(0)   	   ;(1 - 2)
											fstp Result
											mov ResultNeg,0
										da_deng3:            		 ;(1 - 1)(2 - 1)
											fsub 
											mov ResultNeg,1 
										over3:
									;-----------------------------------
									.elseif HasNeg1==1 && HasNeg2==0
											fadd
											mov ResultNeg,1
									;-----------------------------------				
									.elseif HasNeg1==0 && HasNeg2==1
											fadd
											mov ResultNeg,0
									;-----------------------------------
									.elseif HasNeg1==1 && HasNeg2==1
											fcom ST(1)
											jle xiao_deng4       
											fsub                 	;(-2 - -1)
											mov ResultNeg,1
										xiao_deng4:							;(-1 - -1)(-1 - -2)
											fsub ST(1),ST(0)
											fstp Result
											mov ResultNeg,0
										over4:
								.endif
								
						;**************************************
						.elseif Operator=='*'
									fmul
									mov bl,HasNeg1
									xor bl,HasNeg2
									mov ResultNeg,bl
									
						;÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷
						.elseif Operator=='/'
									mov bx,4000h
									fld Operand2
									ftst
         					fstsw ax          					        									
         					and bx,ax                   									
									jz NotZero
									mov IsError,1
									invoke SendMessage,hEdit1,WM_SETTEXT,0,addr DivError
									ret									
							NotZero:
									fstp Operand2							    		
									fdiv ST(0),ST(1)
									mov bl,HasNeg1
									xor bl,HasNeg2
									mov ResultNeg,bl
						.endif 
						;----------------------------------------
						;-----获得结果------						
						fst Operand1
						fstp Result
						mov bl,ResultNeg
						mov HasNeg1,bl
				 		mov HasPoint,0
				 		mov HasEqual,1
				.endif
				
				;--------------显示结果------------------------
		show:
				invoke FloatToStr,Result,addr Output
				lea edi,Output
				.while BYTE PTR [edi]!=0
						inc edi
						.if BYTE PTR [edi]=='.'
								mov HasPoint,1
						.endif
				.endw
				.if IsGroup==1
						invoke GroupNum
				.endif
				.if ResultNeg==1
						invoke AddDelNeg
				.endif
				invoke SendMessage,hEdit1,WM_SETTEXT,0,addr Output
				invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
				ret
GetResult endp											
;------------------------------------------------------------
 
 
;------------------------------------------------------------
;记忆加/记忆减
;包括记忆加和记忆减
;------------------------------------------------------------
MemoryFunc proc USES eax ebx,param:DWORD
			mov eax,param
			finit
			;----------当前显示的是第一个操作数----------
      .if Operator=='.'                    
      			fld Memory
      			fld Operand1  
      			fstp Operand2      ;Op1=>Op2
         		fstp Operand1      ;Memory=>Op1         		
         		mov bl,MemoryNeg
         		mov HasNeg1,bl     ;Memory的符号给Op1的符号

         		.if eax==IDB_MPLUS
         				mov BYTE PTR Operator,'+'
         		.elseif eax==IDB_MSUB
         				mov BYTE PTR Operator,'-'
         		.endif
         		invoke GetResult   ;Op1+Op2=>Op1
         		fld Operand1
         		fstp Memory        ;Op1=>Memory
         		mov bl,HasNeg1
         		mov MemoryNeg,bl   ;Op1的符号给Memory
         		mov Operator,'.'
         		
         		mov bl,0
         		mov IsShowMem,bl
         		invoke ShowMemory
         		
       ;---------当前显示的是第二个操作数-------------  		
       .elseif Operator!='.'	        
      			;-----保护运算符和操作数1---------		
         		mov bl,Operator
         		mov Buffer,bl      ;Operator=>Buffer 
         		fld Operand1
         		fstp Temporary     ;Op1暂存Temporary
         		mov bh,HasNeg1     ;Op1的符号位暂存在BH
         		;---------------------------------
         		.if eax==IDB_MPLUS
         				mov BYTE PTR Operator,'+'
         		.elseif eax==IDB_MSUB
         				mov BYTE PTR Operator,'-'
         		.endif			  		
         		fld Memory
         		fstp Operand1      ;Memory=>Op1
         		mov bl,MemoryNeg
         		mov HasNeg1,bl     ;Memory的符号给Opd1的符号
         		invoke GetResult   ;Op2+Memory=>Op1
         		;-----------------------------------
         		fld Operand1
         	  fst Operand2       ;记忆运算的结果给Op2和Mempry
         		fstp Memory				
         		mov bl,HasNeg1
         		mov HasNeg2,bl     ;运算结果符号位给Op2和Mempry符号位
         		mov MemoryNeg,bl	
         		;-----换回运算符和操作数1----------			  		
         		fld Temporary
         		fstp Operand1      
         		mov HasNeg1,bh    
         		mov bl,Buffer      
         		mov Operator,bl		  		

      		  invoke SendMessage,hTextM,WM_SETTEXT,0,NULL
       		  invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
       		  ;----------在上面的文本框显示操作数1----------		
					  lea esi,Output
					  invoke FloatToStr,Operand1,addr Output
					  .while BYTE PTR [esi]!=0
								inc esi
					  .endw
						mov bl,Operator
						mov [esi],bl
						mov BYTE PTR [esi+1],0
						.if HasNeg1==1
								invoke AddDelNeg
						.endif
						invoke SendMessage,hEdit2,WM_SETTEXT,0,addr Output
				.endif
        ret
MemoryFunc endp
;------------------------------------------------------------ 
        					  			
        					  			
;------------------------------------------------------------
;GroupNum函数将输出数据的字符串Output进行数字分组。
;它首先获取小数点以前的数字位数并保存在寄存器eax中,然后将
;(eax-1)÷3 => eax,即为需要添加的字符‘,’数目,
;对于小数点及以后的字符都向后移动eax位,对于小数点以前的字符,
;向后移动eax位并用ecx计数,当ecx计数到3时添加字符‘,’
;并将ecx设为1且eax减一,重复上述步骤直到eax等于0
;-------------------------------------------------------------
GroupNum proc USES eax ebx ecx edx
				lea esi,Output
				mov eax,0
				;----------有小数点---------------------------
				.if HasPoint==1
						.while BYTE PTR [esi]!='.'
								inc eax
								inc esi
						.endw
						.while BYTE PTR [esi]!=0
								inc esi
						.endw
						
						dec eax
						mov edx,0
						mov ecx,3
						div ecx                     ;得到需要添加‘,’的个数						
						.while BYTE PTR [esi]!='.'  ;移动小数点之后的数据
								mov bx,[esi]
								mov [esi+eax],bx
								dec esi
						.endw
						mov bx,[esi]                 ;移动小数点
						mov [esi+eax],bx		
				;-----------没有小数点--------------------------		
				.elseif HasPoint==0
						.while BYTE PTR [esi]!=0
								inc esi
								inc eax
						.endw
						dec eax
						mov edx,0
						mov ecx,3
						div ecx											
				.endif
				;-----------------------------------------------
				dec esi
				mov ecx,0						
				.while eax!=0
						.if ecx<3
								mov bx,[esi]
								mov [esi+eax],bx
								inc ecx
						.else
								mov BYTE PTR [esi+eax],','
								dec eax
								mov ecx,1
						.endif
						dec esi
				.endw					
		ret
GroupNum endp							
;-----------------------------------------------------------


;-----------------------------------------------------------
;UnGroupNum函数将进行数字分组输出的字符串Output解分组。
;它首先获取Output地址存在esi中,然后ecx赋0,并将Output中字符
;向前移动ecx个单位,遇见‘,’字符则将ecx加1,直到字符串结束
;------------------------------------------------------------
UnGroupNum proc USES ebx ecx
				lea esi,Output
				mov ecx,0
				.while BYTE PTR [esi+ecx]!=0
						.if BYTE PTR [esi]==','
									inc ecx
						.endif
					  mov bx,[esi+ecx]     
					  mov [esi],bx
					  inc esi
				.endw
		ret
UnGroupNum endp
;-----------------------------------------------------------     
           
end start
;************************************************************    							        

版权所有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值