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

📄 cal.asm

📁 一个带有图形界面的计算器程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
title	calculator
;--------------------------------------------------------------------------------------------------------------------------------
;	purpose	term project
;	programmer	sun
;	filename	cal.asm, cal.res resource.h
;	compiler	masm32
;	type	win32
;--------------------------------------------------------------------------------------------------------------------------------
	.386
	.model	flat,stdcall
	option	casemap:none		;case sensitive
;--------------------------------------------------------------------------------------------------------------------------------
;include files		need .inc and .lib files in masm32
include		\masm32\include\windows.inc
include		\masm32\include\user32.inc
include		\masm32\include\kernel32.inc
include		\masm32\include\gdi32.inc

includelib		\masm32\lib\user32.lib
includelib		\masm32\lib\kernel32.lib
includelib		\masm32\lib\gdi32.inc
;--------------------------------------------------------------------------------------------------------------------------------
;#define
MAX		equ	0ch
;the size of the input number
;defined in resource.h, is used to link with cal.res
IDD_DIALOG		equ	101	
IDC_BUTTON_1	equ	1001
IDC_BUTTON_2	equ	1002
IDC_BUTTON_3	equ	1003
IDC_BUTTON_4	equ	1004
IDC_BUTTON_5	equ	1005
IDC_BUTTON_6	equ	1006
IDC_BUTTON_7	equ	1007
IDC_BUTTON_8	equ	1008
IDC_BUTTON_9	equ	1009
IDC_BUTTON_0	equ	1000
IDC_BUTTON_SIGN	equ	1010
IDC_BUTTON_AC	equ	1011
IDC_BUTTON_ADD	equ	1012
IDC_BUTTON_SUB	equ	1013
IDC_BUTTON_MUL	equ	1014
IDC_BUTTON_DIV	equ	1015
IDC_BUTTON_EQU	equ	1016
IDC_EDIT_DISPLAY	equ	1017
IDC_EDIT_INFO	equ	1018
;--------------------------------------------------------------------------------------------------------------------------------
;definitions
	.data
count	dword	00000000h	;count:save the length of the input number
dlgflag	db	00h
;	dlgflag	00h	num1,num2 is not empty
;	dlgflag	01h	num1 is assigned,num2 is empty,operator is not assigned
;	dlgflag	02h	num1 and num2 are assigned
;	dlgflag	03h	num1 is assigned,num2 is empty,operator is assigned
num1	db	MAX dup(0),0	;inout number: in ASCII code first \
num2	db	MAX dup(0),0	;and is changed to binary code to operate
sign1	db	'+'
sign2	db	'+'
flag	word	0000h	;flag used in biger proc,Var1,Var2,@flag: 0000h--Var1>Var2; 1111h--Var1<Var2
lenth	word	MAX
result1	db	MAX dup(0)	;result number,to output \
result2	db	MAX dup(0),0	;extended result1 is reminder of a division
temp1	db	MAX dup(0)	;temporary number used in operation: in binary code
temp2	db	MAX dup(0),0	;will be set to 000...0 before use
temp3	db	MAX dup(0),0	
	.data?
resultsign	db	?	;the sign of the result
sign	db	?	;the operator between the two numbers
hInstance	dword	?	;handle of Dialog
	.const	;information
OverScale	db	'The input number is overscale.',0
Warning	db	'Warning!',0
Blank	db	0
;--------------------------------------------------------------------------------------------------------------------------------
;codes	
	.code
ProcDlgMain	proto	hWnd:dword,wMsg:dword,wParam:dword,lParam:dword
moveright	proto	_Var:dword			;move number right one byte
moveleft	proto	_Var1:dword,_Var2:dword		;move number left   one byte
StdNum	proto	_Var:dword			;@buffer is save in left to right sequence, change num to right to left sequence
Initial	proto
;;;main function
Calculate	proto	_num1:dword,_num2:dword,_result1:dword,_result4:dword,_sign:dword
asciitobin	proto	_Var:dword			;change num from ASCII code to Binary code
bintoascii	proto	_Var:dword			;change result from Binary code to ASCII code
addition	proto	_Var1:dword,_Var2:dword,_Var3:dword
subtraction	proto	_Var1:dword,_Var2:dword,_Var3:dword
multiplication	proto	_Var1:dword,_Var2:dword,_Var3:dword,_Var4:dword	;multiple bits	AAAAAA*BBBBBB
divition	proto	_Var1:dword,_Var2:dword,_Var3:dword,_Var4:dword
multiply	proto	_Var1:dword,_Var2:dword,_Var3:dword		;single bit	AAAAAA*B
bigger	proto	_Var1:dword,_Var2:dword,_Var3:dword		;tell if	Var1>Var2
shlresult	proto	_Var:dword
;--------------------------------------------------------------------------------------------------------------------------------
ProcDlgMain	proc	uses ebx edi esi hWnd,wMsg,wParam,lParam
	local	@buffer[MAX+2]:byte
	local	@address:dword
	local	@numaddress1:dword		;address of num to input as the first number in proc calculate
	local	@numaddress2:dword
	local	@temp:byte
	local	@distinction[4]:byte
;distinction[]:save sign1,sign,sign2,(num1>num2) to imply the sequence of @numaddress, the ultimate operator between
;the two numbers, and whether the sign of the result is positive or negative
;distinction[0~3]: sign1,sign,sign2,bigger
;sign1:	sign of num1 is positive	distinction[0]
;sign	operator is + or -; +:1,-:0	distinction[1]
;sign2:	sign of num2 is positive	distinction[2]
;bigger:	num1>num2		distinction[3]
;A:	the case that num1 is the first operand,num2 is the second
;B:	operator between the two operands
;C:	the sign of the result

;sign1	sign	sign2	bigger	A	B	C
;1	1	1	1&0	1	1	1
;1	1	0	1	1	0	1
;1	1	0	0	0	0	0
;0	1	1	1	1	0	0
;0	1	1	0	0	0	1
;0	1	0	1&0	1	1	0
;1	0	1	1	1	0	1
;1	0	1	0	0	0	0
;1	0	0	1&0	1	1	1
;0	0	1	1&0	1	1	0
;0	0	0	1	1	0	0
;0	0	0	0	0	0	1
;we can use K-MAP method to how out the relations between distinction[0~3] and A,B,C
;A=bigger+sign1^(sign)^(sign2)+(sign1)^sign^(sign2)+(sign1)^(sign)^sign2+sign1^sign^sign2
;B=sign1^(sign)^(sign2)+(sign1)^sign^(sign2)+(sign1)^(sign)^sign2+sign1^sign^sign2
;C=sign1^bigger+(sign)^(sign2)^(bigger)+sign^sign2^(bigger)
;;;(sign)= ┐sign

	mov	eax,wMsg
	.if	eax == WM_CLOSE
		invoke	EndDialog,hWnd,NULL
;--------------------------------------------------------------------------------------------------------------------------------
	.elseif	eax == WM_INITDIALOG
		invoke	SendDlgItemMessage,hWnd,IDC_EDIT_DISPLAY,EM_SETREADONLY,TRUE,NULL
		invoke	SendDlgItemMessage,hWnd,IDC_EDIT_INFO,EM_SETREADONLY,TRUE,NULL	
;--------------------------------------------------------------------------------------------------------------------------------
	.elseif	eax == WM_COMMAND
		mov	eax,wParam
		.if	(ax==IDC_BUTTON_1) || (ax==IDC_BUTTON_2) || (ax==IDC_BUTTON_3) || \
			 (ax==IDC_BUTTON_4) || (ax==IDC_BUTTON_5) || (ax==IDC_BUTTON_6) || \
			  (ax==IDC_BUTTON_7) || (ax==IDC_BUTTON_8) || (ax==IDC_BUTTON_9) || \
			   (ax==IDC_BUTTON_0)
			inc	count
			cmp	count,MAX
			jnbe	ProcDlgMain10
			.if	dlgflag==00h
				invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset Blank
				mov	dl,01h
				mov	dlgflag,dl
			.elseif	dlgflag==03h
				invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset Blank
				mov	dl,02h
				mov	dlgflag,dl
			.endif

			invoke	GetDlgItemText,hWnd,IDC_EDIT_DISPLAY,\	;put EDIT TEXT to @buffer
			addr	@buffer,sizeof @buffer

			mov	eax,wParam		;get input number
			.if	ax==IDC_BUTTON_1
				mov	dl,31h
			.elseif	ax==IDC_BUTTON_2
				mov	dl,32h
			.elseif	ax==IDC_BUTTON_3
				mov	dl,33h
			.elseif	ax==IDC_BUTTON_4
				mov	dl,34h
			.elseif	ax==IDC_BUTTON_5
				mov	dl,35h
			.elseif	ax==IDC_BUTTON_6
				mov	dl,36h
			.elseif	ax==IDC_BUTTON_7
				mov	dl,37h
			.elseif	ax==IDC_BUTTON_8
				mov	dl,38h
			.elseif	ax==IDC_BUTTON_9
				mov	dl,39h
			.elseif	ax==IDC_BUTTON_0
				mov	dl,30h
			.endif
			mov	ebx,count
			mov	dh,00h
			mov	@buffer[ebx-1],dl
			mov	@buffer[ebx],dh
			;set text @buffer
			invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,addr @buffer

			jmp	ProcDlgMain20
ProcDlgMain10:
			invoke	MessageBox,NULL,offset OverScale,offset Warning,MB_OK
ProcDlgMain20:
;---------------------------------------------------------------------------------------------------
		.elseif	ax==IDC_BUTTON_SIGN
			.if	(dlgflag==01h) || (dlgflag==02h)
				invoke	GetDlgItemText,hWnd,IDC_EDIT_DISPLAY,\
					addr	@buffer,sizeof @buffer
				;get text to @buffer
				.if	dlgflag==01h	;write sign to right place:sign1 or sign2
					.if	sign1==2bh
						mov	dl,2dh
						mov	sign1,dl
					.else
						mov	dl,2bh
						mov	sign1,dl
					.endif
				.else
					.if	sign2==2bh
						mov	dl,2dh
						mov	sign2,dl
					.else
						mov	dl,2bh
						mov	sign2,dl
					.endif
				.endif
				mov	@temp,dl				
				
				mov	dh,@buffer
				.if	dh==2dh	;the first byte of @buffer is '-',negative sign
					invoke	moveleft,addr @buffer,01h
					dec	count
					mov	dl,00h
					mov	ebx,count
					mov	@buffer[ebx],dl
					
					invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,addr @buffer
				.else		;the first byte of @buffer is a number: positive sign is not not output
					invoke	moveright,addr @buffer
					mov	dl,@temp
					mov	@buffer,dl
					inc	count
					mov	dl,00h
					mov	ebx,count
					mov	@buffer[ebx],dl
					invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,addr @buffer
				.endif
			.endif
;---------------------------------------------------------------------------------------------------
		.elseif	ax==IDC_BUTTON_AC
			invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset Blank
			invoke	SetDlgItemText,hWnd,IDC_EDIT_INFO,offset Blank
			call	Initial
;---------------------------------------------------------------------------------------------------
		.elseif	(ax==IDC_BUTTON_ADD) || (ax==IDC_BUTTON_SUB) || (ax==IDC_BUTTON_MUL) \
			|| (ax==IDC_BUTTON_DIV)
			.if	(dlgflag==01h)	 || (dlgflag==03h)
				mov	edx,00000000h
				mov	count,edx
				mov	eax,wParam		;assign operator
				.if	ax==IDC_BUTTON_ADD
					mov	dl,2bh
				.elseif	ax==IDC_BUTTON_SUB
					mov	dl,2dh
				.elseif	ax==IDC_BUTTON_MUL
					mov	dl,2ah
				.elseif	ax==IDC_BUTTON_DIV
					mov	dl,2fh
				.endif
				
				mov	sign,dl		;display selected operator
				invoke	SetDlgItemText,hWnd,IDC_EDIT_INFO,offset sign
				;dlgflag->03h step changed
				mov	dlgflag,03h
				;save the first number
				invoke	GetDlgItemText,hWnd,IDC_EDIT_DISPLAY,\
					addr	@buffer,sizeof @buffer
				mov	cx,lenth
				mov	edi,offset num1
				lea	esi,@buffer
				;if the first byte of @buffer is '-', then copy from the second byte
				mov	dl,[esi]
				.if	dl==2dh	
					inc	esi
					dec	cx
				.endif
ProcDlgMain30:
				mov	dl,[esi]
				mov	[edi],dl
				inc	esi
				inc	edi
				dec	cx
				jnz	ProcDlgMain30
			.endif	 
;---------------------------------------------------------------------------------------------------
		.elseif	ax==IDC_BUTTON_EQU
			.if	dlgflag==02h
				invoke	SetDlgItemText,hWnd,IDC_EDIT_INFO,offset Blank
				invoke	GetDlgItemText,hWnd,IDC_EDIT_DISPLAY,\
					addr	@buffer,sizeof @buffer
				mov	cx,lenth
				mov	edi,offset num2
				lea	esi,@buffer
				mov	dl,[esi]
				.if	dl==2dh
					inc	esi
					dec	cx
				.endif
ProcDlgMain40:
				mov	dl,[esi]
				mov	[edi],dl
				inc	esi
				inc	edi
				dec	cx
				jnz	ProcDlgMain40

				invoke	StdNum,offset num1
				invoke	StdNum,offset num2
				
				;after the input round, get distinction, in order to determine
				;how to execute the operands
				mov	flag,0000h
				invoke	bigger,offset num1,offset num2,offset flag
				.if	flag==0000h	;num1>num2------>bigger(element 4)
					mov	@distinction[3],01h
				.else	
					mov	@distinction[3],00h
				.endif
				.if	sign1==2bh	;sign of num1------>sign1(element 1)
					mov	@distinction[0],01h
				.else	
					mov	@distinction[0],00h
				.endif
				.if	sign==2bh	;operator------------>sign(element 2)
					mov	@distinction[1],01h
				.elseif	sign==2dh	
					mov	@distinction[1],00h
				.elseif	sign==2ah
					mov	@distinction[1],02h
				.elseif	sign==02fh
					mov	@distinction[1],03h
				.endif
				.if	sign2==2bh	;sign of num2------->sign2(element 3)
					mov	@distinction[2],01h
				.else	
					mov	@distinction[2],00h
				.endif
				;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				;use K-MAP method, we can get
				;A=bigger+sign1^(sign)^(sign2)+(sign1)^sign^(sign2)+(sign1)^(sign)^sign2+sign1^sign^sign2
				mov	@numaddress1,offset num2
				mov	@numaddress2,offset num1
				.if	(@distinction[3]==01h) || (@distinction[1]==02h) || (@distinction[1]==03h) || \
					((@distinction[0]==01h) && (@distinction[1]==00h) && (@distinction[2]==00h)) || \
					((@distinction[0]==00h) && (@distinction[1]==01h) && (@distinction[2]==00h))
					mov	@numaddress1,offset num1
					mov	@numaddress2,offset num2
				.endif
				.if	((@distinction[0]==00h) && (@distinction[1]==00h) && (@distinction[2]==01h)) || \
					((@distinction[0]==01h) && (@distinction[1]==01h) && (@distinction[2]==01h))
					mov	@numaddress1,offset num1
					mov	@numaddress2,offset num2
				.endif
				;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
				;use K-MAP method, we can get
				;B=sign1^(sign)^(sign2)+(sign1)^sign^(sign2)+(sign1)^(sign)^sign2+sign1^sign^sign2
				mov	sign,2dh
				
				.if	((@distinction[0]==01h) && (@distinction[1]==00h) && (@distinction[2]==00h)) || \
					((@distinction[0]==00h) && (@distinction[1]==01h) && (@distinction[2]==00h))
					mov	sign,2bh
				.elseif	((@distinction[0]==00h) && (@distinction[1]==00h) && (@distinction[2]==01h)) || \
					((@distinction[0]==01h) && (@distinction[1]==01h) && (@distinction[2]==01h))
					mov	sign,2bh
				.elseif	@distinction[1]==02h
					mov	sign,2ah
				.elseif	@distinction[1]==03h
					mov	sign,2fh
				.endif
				;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				;use K-MAP method, we can get
				;C=sign1^bigger+(sign)^(sign2)^(bigger)+sign^sign2^(bigger)
				mov	resultsign,2dh
				.if	((@distinction[1]==00h) && (@distinction[2]==00h) && (@distinction[3]==00h)) || \
					((@distinction[1]==01h) && (@distinction[2]==01h) && (@distinction[3]==00h)) || \
					((@distinction[0]==01h) && (@distinction[3]==01h) && ((@distinction[1]==00h) || (@distinction[1]==01h)))
					mov	resultsign,2bh
				.elseif	((@distinction[0]==01h) && (@distinction[1]==02h) && (@distinction[2]==01h)) || \
					((@distinction[0]==00h) && (@distinction[1]==02h) && (@distinction[2]==00h))
					
					mov	resultsign,2bh
				.elseif	((@distinction[0]==01h) && (@distinction[1]==03h) && (@distinction[2]==01h)) || \
					((@distinction[0]==00h) && (@distinction[1]==03h) && (@distinction[2]==00h))
					mov	resultsign,2bh
				.endif
				;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>				
				mov	edx,00000000h
				mov	dl,sign
				invoke	Calculate,@numaddress1,@numaddress2,offset result1,offset result2,edx

				.if	(sign==2bh) || (sign==2dh)
					.if	resultsign==2dh
						mov	dl,02dh
						mov	result2,dl
					.endif
					invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset result2
				.elseif	sign==2fh
					.if	resultsign==2dh
						mov	dl,02dh
						mov	result2,dl
					.endif
					.if	sign1==2dh
						mov	dl,02dh
						mov	result1,dl
					.endif
					mov	cx,lenth
					lea	edi,@address
					mov	esi,offset result1
ProcDlgMain60:
					mov	dl,[esi]
					mov	[edi],dl
					inc	edi
					inc	esi
					dec	cx
					jnz	ProcDlgMain60
					mov	dl,00h
					mov	[edi],dl
					invoke	SetDlgItemText,hWnd,IDC_EDIT_INFO,addr @address
					invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset result2
				.elseif	sign==2ah
					.if	resultsign==2dh
						mov	dl,02dh
						mov	result1,dl
					.endif
					invoke	SetDlgItemText,hWnd,IDC_EDIT_DISPLAY,offset result1
				.endif
				call	Initial
			.endif
;--------------------------------------------------------------------------------------------------
		.endif
	.else
		mov	eax,FALSE
		ret
	.endif
		mov	eax,TRUE
		ret
ProcDlgMain	endp
;--------------------------------------------------------------------------------------------------------------------------------
start:
		invoke	GetModuleHandle,NULL
		mov	hInstance,eax
		invoke	DialogBoxParam,hInstance,IDD_DIALOG,NULL,offset ProcDlgMain,NULL
		invoke	ExitProcess,NULL
;--------------------------------------------------------------------------------------------------------------------------------
moveright	proc	_Var
	pushad
	pushf

	mov	ecx,00000000h
	mov	cx,lenth
	dec	cx
	mov	edi,_Var
	add	edi,ecx
moveright10:
	dec	edi
	mov	ah,byte ptr [edi-1]
	mov	byte ptr [edi],ah
	dec	cx
	jnz	moveright10
	dec	edi
	mov	dl,00h
	mov	[edi],dl
	popf
	popa
	ret
moveright	endp
;--------------------------------------------------------------------------------------------------------------------------------
moveleft	proc	_Var1,_Var2
	pushad
	pushf
	mov	cx,lenth

	cmp	_Var2,01h		;if _Var2==02h, mean the scale is 2*MAX
	jz	moveleft10
	shl	cx,01h
moveleft10:
	dec	cx
	mov	edi,_Var1
moveleft20:
	mov	ah,byte ptr [edi+1]
	mov	byte ptr [edi],ah
	inc	edi
	dec	cx
	jnz	moveleft20
	mov	ah,00h
	mov	byte ptr [edi],ah

	popf
	popa
	ret
moveleft	endp
;--------------------------------------------------------------------------------------------------------------------------------
StdNum	proc	_Var
	pushad
	pushf
;	@bufer is saved from left to right
;	find the first byte that is 00h
;	from that byte backward, save them from right to left
	

⌨️ 快捷键说明

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