使用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 ? ; 整型数字,有用户输入,?表示为某些数据预留的存储器单元
secondNumber 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