汇编《万年历》实验设计报告.docx
《汇编《万年历》实验设计报告.docx》由会员分享,可在线阅读,更多相关《汇编《万年历》实验设计报告.docx(20页珍藏版)》请在冰豆网上搜索。
汇编《万年历》实验设计报告
汇编《万年历》实验设计报告
912106840444王誉霖
一、设计思想
方案1:
利用bios调用,dos调用构建一个年历板式,然后根据zeller公式计算元旦的日期,循环输出年历。
二、程序源代码
;Calendar
DATASSEGMENT
TSTRDB"Pleaseinputayear=$"
IVLSTRDB"INVALIDINPUT!
$"
OVLSTRDB“LOWERTHAN1582”
LINESDB80DUP('_');分隔符
CRLFDB10,13,"$"
ERRFLAGDB0;非法输入标志0,1INVALID2OVERFLOW
YEARWDB10
DB?
DB10DUP(24H);年string
YEARDW0;年Num
LPYEARDW0;闰年
ONEDAYDW0;元旦的星期
DAYWDB2DUP(0)
DAYDB0
WEEKCTDB0;7d计数器
BASELDB0;line存储
BASECLDB0;column存储
IF3DB0;三个月循环
MTITLEDB
;Monthtitlenum=DOScharcolor
"_________Jan.________",12,'_________Feb.________',
11,'_________Mar.________',14,'_________Apr.________',
2,'_________May.________',13,'_________Jun.________',
3,'_________Jul.________',11,'_________Aug.________',
10,'_________Sep.________',2,'_________Oct.________',
12,'_________Nov.________',5,'_________Dec.________',12
SIGNDB'S.M.T.W.T.F.S.';weeksign
LPDAYSDB31,29,31,30,31,30,31,31,30,31,30,31;leapyeardays
DAYSDB31,28,31,30,31,30,31,31,30,31,30,31;nonleapyeardays
DATASENDS
STACKSSEGMENT
DB1024DUP(?
)
STACKSENDS
CODESSEGMENT
ASSUMECS:
CODES,DS:
DATAS,SS:
STACKS
START:
PUSH6MACRO
PUSHAX
PUSHBX
PUSHCX
PUSHDX
PUSHSI
PUSHES
ENDM
POP6MACRO
POPES
POPSI
POPDX
POPCX
POPBX
POPAX
ENDM
;保护及恢复现场
CLEARXXMACRO
XORAX,AX
XORBX,BX
XORDX,DX
XORCX,CX
ENDM
;MACRO________________________________宏定义结束
MOVAX,DATAS
MOVDS,AX
LEADX,TSTR
MOVAH,9
INT21H;人机友好
CALLINIT;输入及初始化数据
CALLZELL;计算元旦星期
CALLSHOW;输出
JMPFINISH
GOERR:
CALLERRINFO
FINISH:
MOVDH,36
MOVDL,0
MOVBH,0
MOVAH,2
INT10H;重置光标
MOVAH,4CH
INT21H
;___________________SUBROUTINE_______________________
INITPROCNEAR
LEADX,YEARW
MOVAH,10
INT21H
CLEARXX
MOVCL,YEARW+1
JCXZGOERR
;无输入时跳转
MOVSI,OFFSETYEARW+2
A2DLOOP:
MOVBL,[SI]
SUBBL,"0"
CMPBL,0
JBIVL
CMPBL,9
JGIVL
INCSI
DECCL
MOVAX,YEAR
MOVDX,10
MULDX
ADDAL,BL
MOVYEAR,AX
CMPCL,0
JZCHECK
JMPA2DLOOP
;年份转换十进制数
CHECK:
CMPYEAR,1582
JBOVFL
JMPA2DEXIT
OVFL:
MOVERRFLAG,2
JMPGOERR
IVL:
MOVERRFLAG,1
JMPGOERR
A2DEXIT:
XORDX,DX
RET
INITENDP
ERRINFOPROCNEAR
;ERRORINFOOUTPUT
;ERRFLAG0,1—INVALID2—OF1582
LEADX,CRLF
MOVAH,9
INT21H
CMPERRFLAG,1
JGOVS
LEADX,IVLSTR
MOVAH,9
INT21H
OVS:
LEADX,OVLSTR
MOVAH,9
INT21H
ERREXIT:
RET
ERRINFOENDP
IODAYPROCNEAR
;MAKEADAYSTRING
;SI--BUF
;AX--DAYS
PUSH6
MOVCX,0
MOVBX,10
IO1:
SUBDX,DX
DIVBX
ADDDL,48
PUSHDX
INCCX
CMPAX,0
JNZIO1
MOV[SI],CL
INCSI
IO2:
POPDX
MOV[SI],DL
INCSI
LOOPIO2
POP6
RET
IODAYENDP
ZELLPROCNEAR
MOVAX,YEAR
MOVBX,4
DIVBX
CMPDX,0
JNZUNLP
MOVAX,YEAR
MOVBX,100
XORDX,DX
DIVBX
CMPDX,0
JNZLP
MOVAX,YEAR
MOVBX,400
XORDX,DX
DIVBX
CMPDX,0
JZLP
;leapyearjudgement
LP:
MOVLPYEAR,1
UNLP:
DECYEAR
MOVAX,YEAR;ZELLERw=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
;m=13,d=1,y=year-1
MOVBX,100
SUBDX,DX
DIVBX
MOVONEDAY,DX;DX--Y
MOVCX,AX;AX--C
MOVAX,DX
MOVBX,4
SUBDX,DX
DIVBX
SUBBX,BX
MOVBL,AL
ADDONEDAY,BX
MOVAX,CX
MOVBX,4
SUBDX,DX
DIVBX
SUBBX,BX
MOVBL,AL
ADDONEDAY,BX
MOVBX,2
SUBAX,AX
MOVAX,CX
MULBX
MOVAH,0
SUBONEDAY,AX
ADDONEDAY,36
CMPONEDAY,0
JSDELNEG
JMPGOON
DELNEG:
NEGONEDAY
GOON:
MOVAX,ONEDAY
MOVBX,7
XORDX,DX
DIVBX
MOVONEDAY,DX
RET
ZELLENDP
SHOWPROCNEAR
MOVCX,0
MOVDL,79
MOVDH,24
MOVBH,7
MOVAL,0
MOVAH,6
INT10H;CLScreen
CLEARXX
MOVCH,12
MOVDH,0
MOVDL,36
MOVCL,4
MOVSI,OFFSETYEARW+2
CALLSHOWSTR
;输出年标头
MOVCH,12
MOVDH,1
MOVDL,0
MOVCL,80
MOVSI,OFFSETLINES
CALLSHOWSTR
;输出分隔符
MOVSI,OFFSETMTITLE
CLEARXX;calendartitleinit
LLOOP:
CMPBH,4
JZMSHOW
SUBBL,BL
MOVAL,BH
MOVDL,9
MULDL
MOVDH,AL
ADDDH,2
INCBH;SETLINEspace,columnspace
CLOOP:
MOVAL,BL
MOVDL,27
MULDL
MOVDL,AL
MOVCH,[SI+21]
MOVCL,21
CALLSHOWSTR
;monthtitle
INCDH
MOVCH,15
PUSHSI
MOVSI,OFFSETSIGN
MOVCL,21
CALLSHOWSTR
POPSI
DECDH;weekdaytitle
ADDSI,21
INCSI
INCBL
CMPBL,3
JZLLOOP
JMPCLOOP;linecolumnloop
MSHOW:
CLEARXX
SUBBP,BP
MOVBP,OFFSETDAYS
CMPLPYEAR,0
JZNOLP
MOVBP,OFFSETLPDAYS;DAYS
NOLP:
PUSHAX
PUSHBX
MOVAX,ONEDAY
MOVBX,3
MULBX
MOVDL,AL;FIRSTDAYCOLUMN
POPBX
POPAX
MOVDH,4;FIRSTDAYLINE
MOVBASEL,DH
;storeline=dh=4,column=basecl=0
MONTHLOOP:
INCBH
INCIF3
CMPBH,13;MONTHS
JZFIN
MOVCX,ONEDAY
MOVCH,[BP]
INCBP
CALLMONTH
CMPIF3,3;IF3MONTHRESETLINEROW
JZDEL3
ADDBASECL,27
PUSHAX
PUSHBX
MOVAX,ONEDAY
MOVBX,3
MULBX
MOVDL,AL;FIRSTDAYCOLUMN
POPBX
POPAX
ADDDL,BASECL
MOVDH,BASEL
JMPMONTHLOOP
DEL3:
PUSHAX
PUSHBX
MOVAX,ONEDAY
MOVBX,3
MULBX
MOVDL,AL;FIRSTDAYCOLUMN
POPBX
POPAX
MOVDH,BASEL
ADDDH,9
MOVBASEL,DH
MOVBASECL,0
MOVIF3,0
JMPMONTHLOOP
FIN:
JMPFINISH
RET
SHOWENDP
MONTHPROCNEAR
;PARA:
;CLFIRSTDAY
;CHDAYS
;DHLINE
;DLCOLUMN
PUSH6
SUBBX,BX
SUBAX,AX
MOVWEEKCT,CL
;weekct---countof1~7
;AL---countofdays
BG:
DECCH
INCAL
INCWEEKCT
MOVSI,OFFSETDAYW
CALLIODAY
PUSHCX
MOVSI,OFFSETDAYW+1
MOVCH,15
MOVCL,[SI-1]
CALLSHOWSTR;AX,SI
;outputaday
POPCX
ADDDL,3;column+3
CMPCH,0;days=0jmpexit
JZMEXIT
CMPWEEKCT,7;7dayendjmpnextweek
JZWEXIT
JMPBG
WEXIT:
MOVWEEKCT,0
MOVDL,BASECL
INCDH
JMPBG
;reset、weekcount
;columnreset
MEXIT:
CMPWEEKCT,7
JNZMFINISH;SPECIALDELIVERIFWEEKDAYCOUNT=7THENNEXTSET0
MOVWEEKCT,0
MFINISH:
SUBAX,AX
MOVAL,WEEKCT
MOVONEDAY,AX
POP6
RET
MONTHENDP
SHOWSTRPROCNEAR
;PRINTSTR,customCOLORset
;PARA:
DS:
SIPOINTATBUFFERADD
;(DH)=(0-24)
;(DL)=(0~79)
;(CH)=COLOR
;(CL)=NOFCHAR
PUSH6
MOVAX,0B800H
MOVES,AX
MOVAL,2
MULDL
PUSHAX
MOVAL,DH
SUBAH,AH
MOVBX,0A0H
MULBX
POPBX
ADDBX,AX
MOVDL,CH
SUBCH,CH
JCXZOK
S:
MOVAL,[SI]
MOVES:
[BX],AL
INCBX
MOVES:
[BX],DL
INCBX
INCSI
LOOPS
EXIT:
POP6
RET
OK:
MOVCL,[SI]
SUBCH,CH
JCXZEXIT
MOVES:
[BX],CL
INCBX
MOVES:
[BX],DL
INCBX
INCSI
JMPSHORTOK
SHOWSTRENDP
CODESENDS
ENDSTART
三、效果图
四、遇到的问题与心得体会
问题1
年份转换与数字问题:
因为课件中的strtodec是单个字符,2号调用。
我经过自己编程研究,写了个通用的字符串转十进制数解决了这个问题
问题2
日期输出问题:
因为日期有一位数也有两位数,于是上网找了一个通用的指定位置输出任意个数字符的子程序,并实现了彩色功能。
问题3
Zeller公式问题
主要是对乘除法机制理解不透彻,犯了很多低级错误。
认真看书加多次实践解决了此问题
体会:
这是我第二个比较大的汇编程序,跟上次的累加比起来也积累了不少经验,首先是堆栈的使用,因为寄存器紧缺,所以保护现场,子程序间的隔离至关重要,我也是用了个宏定义方便成对进出栈。
整个编程过程中最难的是坐标计算,又要乘法又要除法非常头疼,一不小心出现的bug你砸了电脑都看不懂,还是应该多加练习!
因为人懒,输入判断非法和溢出做的简陋,不过我认为实验重点在于让我们体会输入输出和字符串操作,所以无所谓啦
。
。
。
。
。
。
方案二
:
题目只是说输出个万年历,没要求一定是自己来做啊,笑嘻嘻,所以利用win32汇编,可以调用shell32.inc的API——ShellExecute,调用浏览器打开一个万年历网站即可,整个程序不超过50行!
完爆方案一!
Eg:
.modelflatsmall
includeshell32.inc
includelibshell32.lib
.data
szHomePagedb'
.code
start:
invokeShellExecute,NULL,NULL,offsetszHomePage,NULL,NULL,NULL
invokeExitProcess,NULL
endstart
2012.1.5王誉霖