您的位置:首页 > 其它

32位汇编写简单加减乘除计算器

2017-07-08 09:32 351 查看
使用Visual Studio 2015开发,引用到Intel汇编的Irvine32头文件,头文件下载地址:http://kipirvine.com/asm/gettingStartedVS2015/Irvine.zip

具体的Visual Studio 2015配置汇编环境方法,自行解决。
https://www.youtube.com/watch?v=9e1ER2o83N0
这个视频提供VS2015的配置方法。

16-bit applications will run under the 32-bit versions of Windows (XP, Vista, 7). But 16-bit applications will not run directly in any 64-bit version of Windows.

16位汇编现在只能在32位的Windows xp,Vista , 7以及更早的系统上运行,现在的64位机器无法直接运行16位汇编程序!

具体汇编代码如下:

TITLE MyProject make by LSX (LSXproject.asm)
;***********************************************************
; 版权所有 (C)2017, LSX
;
; 文件名称: LSXproject.asm
; 内容摘要:该代码用于实现简单的计算器任务,并且将结果以16进制的形式输入到文件,负数以补码形式保存
; 当前版本: V1.0
; 作   者:LSX
; 完成日期: 20170707
;**********************************************************

INCLUDE Irvine32.inc	;包含的Intel汇编的头文件

.data
useroption		DWORD	?			; 用户输入的选择数字
firstNumber		DWORD	?			; 整型数字,有用户输入,?表示为某些数据预留的存储器单元
sec
4000
ondNumber	DWORD	?			; 用户输入的第二个数字
result			DWORD	?			; 运算结果

;file set
filename		BYTE	"result.txt",0	; 保存结果的文件
filehandle		DWORD	?				;文件句柄
fileerrormsg	BYTE	"File error!" , 0
;sizeof伪指令 = result大小 * result长度 , 多开辟两个空间备用
filestring		BYTE	sizeof result DUP(0) , 0 , 0

;display menu
lineMenu	BYTE	"This is a simple calculator,input number to chose function",0dh,0ah
BYTE	"			1.add function",0dh,0ah
BYTE	"			2.sub function",0dh,0ah
BYTE	"			3.mul function",0dh,0ah
BYTE	"			4.div function",0

;basic strings
welcome		BYTE	"Welcome to my Assembly Language Project made by LSX.", 0	;打印消息
chosefunc	BYTE	"Please input your function number:",0
string1		BYTE	"Please input the first number:",0
string2		BYTE	"Please input the second number:",0
farewellmsg	BYTE	"Thank you use my program",0
diverrormsg	BYTE	"Your second number is zero!",0
inputerrormsg	BYTE	"Your input is illeagle!",0

;operate message
addResultMsg		BYTE	"Your result:" , 0

;Message Box Set
caption		BYTE	 "Message Box Test",0
question	BYTE	"Do you want to continue?",0

;改变字体颜色调用
colorset1 DWORD 11
colorset2 DWORD 16

.stack 100	;定义栈段

savereg MACRO	;保存现场宏指令
push eax
push ebx
push ecx
push edx
push esi
push edi
ENDM

returnreg MACRO	;恢复现场宏指令
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
ENDM

.code
main PROC
push	colorset1
push	colorset2
call	changeColor

;WriteString函数需要edx为字符串的入口地址为参数,并且字符串最后以0结尾
mov		edx, OFFSET welcome
call	WriteString	;输出到控制台
call	CrLf		;换行,由Irvine.inc提供

fileOperate:
;Create File
;savereg

mov		edx , OFFSET filename
call	CreateOutputFile
cmp		eax , INVALID_HANDLE_VALUE
je		file_error
mov		filehandle,eax
;returnreg
jmp		displaymenustart

file_error:
mov		edx , OFFSET fileerrormsg
call	WriteString
call	CrLf
jmp		stop_run

displaymenustart:
call	displayMenu

chosefunction:
mov		edx , OFFSET chosefunc
call	WriteString
call	ReadInt
cmp		eax , 1
jb		inputerror
cmp		eax , 4
jg		inputerror
jmp		inputnumber

inputerror:
mov		edx , OFFSET inputerrormsg
call	WriteString
call	CrLf
jmp		chosefunction

inputnumber:
mov		useroption , eax
mov		edx , OFFSET string1
call	WriteString
call	ReadInt		;Irvine提供,返回值放在eax中
mov		firstNumber, eax
mov		edx , OFFSET string2
call	WriteString
call	ReadInt		;Irvine提供,返回值放在eax中
mov		secondNumber, eax
mov		eax , useroption
cmp		eax , 1
je		addFunction
cmp		eax , 2
je		subFunction
cmp		eax , 3
je		mulFunction
cmp		eax , 4
je		divFunction

addFunction:
mov		eax , firstNumber
add		eax , secondNumber
jmp		displayResult

subFunction:
mov		eax , firstNumber
sub		eax , secondNumber
jmp		displayResult

mulFunction:
mov		eax , secondNumber
imul	firstNumber		;mul指令,EAX 做乘数, 结果放在 EDX:EAX,但是简单起见,假设结果eax可以存放
jmp		displayResult

divFunction:
mov		eax , secondNumber
cmp		eax , 0
je		divError
mov		edx , 0
mov		eax , firstNumber
idiv	secondNumber	;将把 EDX:EAX 做被除数; 商 -> EAX, 余数 -> EDX
jmp		displayResult

divError:
mov		edx , OFFSET diverrormsg
call	WriteString
call	CrLf
jmp		displaymenustart

displayResult:
mov		result , eax
mov		edx	, OFFSET addResultMsg
call	WriteString
call	WriteInt
call	CrLf

;调用写入文件函数,此函数调用不需要指定任何参数
pushf
call    write_to_file
popf

;调用对话框,ebx放对话框的标题,edx存放对话框内容
mov		ebx, OFFSET caption
mov		edx, OFFSET question
call	MsgBoxAsk		; Yes eax=6 , No eax = 7
cmp		eax , 7
je		close_file
jmp		chosefunction

close_file:
mov		eax , filehandle
call	CloseFile

stop_run:
mov		edx, OFFSET farewellmsg	;调用结束语
call	WriteString
call	CrLf
call	WaitMsg
exit
main ENDP

;*****************************************************************
; 子程序:changeColor
; 功能:改变控制台颜色
; 入口参数:colorset1和colorset2在调用函数之前压入栈中
; 出口参数:无
; 调用注意事项:colorset1和colorset2必须是0-16的整形数字
;*****************************************************************

changeColor PROC

; 天蓝色为控制台的字体颜色,若要改变颜色请自行设置colorset值
push	ebp				;使用到ebp,需要压栈,32位4个字
mov		ebp, esp

mov		eax, [ebp + 8]  ; colorset1
imul	eax, 16
add		eax, [ebp + 12] ; colorset2
call	setTextColor

pop		ebp
ret		8								; 清除栈,等价于将两个colorset去除,俩pop指令

changeColor	ENDP

;*****************************************************************
; 子程序:displayMenu
; 功能:	展示菜单
; 入口参数:无
; 出口参数:无
; 调用注意事项:无
;*****************************************************************

displayMenu	PROC
;使用时先进行压栈操作,最后进行出栈操作
savereg

mov		edx, OFFSET lineMenu
call	WriteString	;输出到控制台
call	CrLf		;换行,由Irvine.inc提供

returnreg
ret

displayMenu ENDP

;*****************************************************************
; 子程序:write_to_file
; 功能:	将运算结果保存至文件
; 入口参数:无
; 出口参数:无
; 调用注意事项:规范起见在调用函数之外进行标志寄存器压栈
;*****************************************************************

write_to_file PROC
;使用时先进行压栈操作,最后进行出栈操作
savereg

mov		edx , OFFSET filestring	;将生成的数字移入filestring处

;从这里开始每个地方进行相似的操作,因为数字由高位到地位排放,所以右移的时候开始是28位,每次减少4位,并且
;一次只要4位。
mov		eax , result
shr		eax , 28
add		al , 30h	;数字转化位ASCII码
cmp		al , 58		;Ascii码‘9’对应57,所以从58开始比较
jl		L1
add		al , 7
L1:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 24
and		ax , 1111b
add		al , 30h
cmp		al , 58
jb		L2
add		al , 7
L2:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 20
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L3
add		al , 7
L3:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 16
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L4
add		al , 7
L4:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 12
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L5
add		al , 7
L5:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 8
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L6
add		al , 7
L6:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
shr		eax , 4
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L7
add		al , 7
L7:
mov		byte ptr [edx], al
inc		edx

mov		eax , result
and		ax , 1111b
add		al , 30h
cmp		al , 58
jl		L8
add		al , 7
L8:
mov		byte ptr [edx], al
inc		edx

mov		byte ptr [edx] , 0dh	;写换行符,Windows是0dH,0aH。
inc		edx
mov		byte ptr [edx] , 0ah

;调用写入文件接口,eax是文件句柄,edx是要写入文件的起始地址
mov		eax , filehandle
mov		edx , OFFSET filestring
mov		ecx , (TYPE result)*2 + 2	;存放的结果大小加2是要写入文件的大小
call	WriteToFile

returnreg
ret

write_to_file ENDP

exit
end main
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: