下面代码实现的计算机基本的功能,包括加、减、乘、除、求倒、开方、百分比、记忆相关功能等,支持快捷键,显示也可以分段显示,如下图。
界面部分源码: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
;************************************************************
版权所有