一、课程设计的目的与任务
课程设计是计算机原理与汇编语言教学过程中的重要环节。本课程设计主要目的是使计算机专业学生深入学习计算机原理与汇编语言知识,进一步提高学生计算机原理与汇编语言综合能力和程序设计技能,锻炼运用计算机原理与汇编语言解决实际问题的能力。
二、课程设计的内容
题目一:
1.从键盘输入年份,通过计算后,输出该年份是否为闰年的信息。
判断闰年的规则是:如果某一年能被4整除但不能被100整除或者该年能被400整除,则该年为闰年。
2.输入20~30之间的任一数值,递归计算Fibonacci 数, 以十进制数输出。
3.编写一拷贝程序,要求在命令行指定源文件名和目标文件名。
问题解答部分:
问题1:从键盘输入年份,通过计算后,输出该年份是否为闰年的信息。
判断闰年的规则是:如果某一年能被4整除但不能被100整除或者该年能被400整除,则该年为闰年。
分析思路流程:
是 不是
代码分析:
首先,定义了数据段:
DATAsegment infon db 0dh,0ah,'Pleaseinput a year: $'
Y db 0dh,0ah,'This is a leap year! $'
N db 0dh,0ah,'This is not a leap year! $'
Errordb 0dh,0ah,'the input is wrong!please input after check!$'
w dw 0 ;保存年份
buf db 6
db ?
db 6 dup(?)
DATAends
在数据段中定义了需要的相关信息,提示字符串以及所需变量。还有一个长度为6的缓冲区来保存输入的年份。
下面定义了转化为数字的程序段:
changeproc ;将缓冲区的字符转化为数字
push cx
dec cx
lea si,buf+2
tt1: inc si
loop tt1 ;si指向最大数字
pop cx
mov dh,30h
mov bl,10
mov ax,1
l1: push ax
push bx
push dx
sub byte ptr [si],dh
mov bl, byte ptr [si]
mov bh,0
mul bx
cmp ax,0
ja wrong
cmp ax,9
jb wrong
add w,ax
pop dx
pop bx ;先保存到栈里,再恢复原来的值,此后bl的值恢复到10
pop ax
mul bl
dec si
loop l1
wrong:
lea dx,Error
mov ah,09
int 21h
ret
change endp
change程序段将缓冲区的字符转化为数字形式进行保存,以便下一步可以进行判断。然后将得到的数字进行除法判断。然后根据结果输出是或者不是的字符串。
运行结果如下:
我输入了2000和2014进行判断,分别输出了是闰年和不是闰年的信息。由结果可知正确。
完整代码段如下:
DATA segment ;定义数据段
infon db0dh,0ah,'Please input a year: $'
Y db0dh,0ah,'This is a leap year! $'
N db0dh,0ah,'This is not a leap year! $'
Error db0dh,0ah,'the input is wrong!please input after check!$'
w dw0 ;保存年份
buf db6
db?
db 6dup(?)
DATA ends
STACK segment stack
;此处输入堆栈段代码
STACK ends
CODE segment
assume ds:DATA,ss:STACK,cs:CODE
start:movax,data
movds,ax
leadx,infon
movah,9
int21h
leadx,buf
movah,10
int21h
movcl, [buf+1]
movch,0
leadi,buf+2
call change
call ifyears
jca1
leadx,n ;否则输出不是闰年信息
movah,9
int21h
jmpexit
a1: lea dx,y ;输出是闰年信息
movah,9
int21h
exit: movah,4ch ;程序结束
int21h
changeproc ;将缓冲区的字符转化为数字
push cx
deccx
leasi,buf+2
tt1: incsi
loop tt1 ;si指向最大数字
pop cx
movdh,30h
movbl,10
movax,1
l1:push ax
push bx
push dx
sub byte ptr [si],dh
mov bl, byte ptr [si]
mov bh,0
mul bx
addw,ax
popdx
popbx ;先保存到栈里,再恢复原来的值,此后bl的值恢复到10
popax
mulbl
decsi
loop l1
ret
changeendp
ifyearsproc ;判断是否是闰年的代码段,改变Cf标记位表示不同结果
push bx
push cx
push dx
mov ax, w
mov cx,ax
mov dx,0
mov bx,100
div bx
cmp dx,0
jnz lab1
mov ax,cx
mov bx,400
div bx
cmp dx,0
jzlab2
clc ;否则不是闰年,将C标记位清零,并跳转到lab3
jmp lab3
lab1:mov ax,cx
movdx,0
movbx,4
divbx
cmpdx,0
jzlab2
clc
jmplab3
lab2:stc ;若是闰年跳转到此处将c标志位置1 ,表示为闰年
lab3:pop dx ;相应寄存器恢复
pop cx
pop bx
ret
ifyearsendp
CODE ends
endstart
问题二:2.输入20~30之间的任一数值,递归计算Fibonacci 数, 以十进制数输出。
Fibonaccci数列递推式如下所示:
鉴于此,我决定用递归方法来实现数列的求解。在汇编中就是可以调用程序段本身直到当前n等于1或者2,然后每层带着值返回,直到结束。
首先定义一个缓冲区,然后在缓冲区中保存输入的数字,然后将其转化为10进制,将转化后的结果与20和30比较,看是否符合要求。然后把该数字作为循环次数进行递归调用。
INPUT PROC ;判断是否正确输入20-30
JMP T1
WRONG:
LEA DX,WRONGSTR
mov AH,9
INT 21H
JMP START
T1:LEA DX,STR1
MOV AH,9
INT 21H
LEADX,INPUTBUFFER
MOV AH,10
INT 21H
MOV AX,0
MOVCL,INPUTBUFFER+1 ;?
MOV CH,0
LEABX,INPUTBUFFER+2 ;?
T2:MULC10
MOVDL,[BX]
CMPDL,'0'
JB WRONG
CMPDL,'9'
JA WRONG
ANDDL,0FH
ADD AL,DL
ADC AH,0
INC BX
LOOP T2
CMPAX,001EH;判断是否比30大
JA WRONG
CMPAX,0014H;判断是否比20小
JB WRONG
CMP AX,1
JB WRONG
MOV N,AX
RET
INPUT ENDP
递归调用的程序段:
FIB PROC
CMPN,1
JZL1
CMPN,2
JZ L2
DEC N
CALLFIB
MOVAX,RESULT2L
MOVDX,RESULT2H
MOVCX,RESULT1L
ADDRESULT2L,CX
MOV CX,RESULT1H
ADCRESULT2H,CX
MOVRESULT1L,AX
MOVRESULT1H,DX
JMPEXIT
L1:MOVRESULT1L,1
MOVRESULT2L,1
JMPEXIT
L2:MOVRESULT2L,1
DECN
CALLFIB
EXIT:RET
FIB ENDP
然后将所得结果转化输出。
运行结果截图如下:
分析上述结果,可以得出程序正确的作出输入判断和输出运行结果的结论。经验证,该结果正确。
完整代码:DATAS SEGMENT
STRING DB 0dh,0ah,'Information Safety 1401hanjun','$'
STR1 DB 'Please enter a number between 20and 30:N=','$'
STR2 DB 0dh,0ah,'FIB(N)=','$'
WRONGSTR DB 0dh,0ah,0dh,0ah,'the numbermust between 20 and 30 please!',0dh,0ah,0dh,0ah,'$'
INPUTBUFFER DB 3,?,3 DUP('?')
N DW ? ;输入N值
RESULT1H DW 0
RESULT1L DW 0
RESULT2H DW 0 ;结果的高16位
RESULT2L DW 0 ;结果的低16位
C10 DW 10
OUTPUTBUFFER DB 11 DUP('0')
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AH,0
INT 10H
MOV BP,SEG STRING
MOV ES,BP
MOV BP,OFFSET STRING
mov cx,32
MOV DX,0
MOV BL,41H
MOV AL,0
MOV AH,13H
INT 10H ;彩色字符输出
lea dx,STRING
MOV AH,09H
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
XOR AX,AX
XOR BX,BX
CALL INPUT
CALL FIB
CALL OUTPUT
JMP QUIT
INPUT PROC ;判断是否正确输入20-30
JMP T1
WRONG:
LEA DX,WRONGSTR
mov AH,9
INT 21H
JMP START
T1:LEA DX,STR1
MOV AH,9
INT 21H
LEA DX,INPUTBUFFER
MOV AH,10
INT 21H
MOV AX,0
MOV CL,INPUTBUFFER+1 ;?
MOV CH,0
LEA BX,INPUTBUFFER+2 ;?
T2:MUL C10
MOV DL,[BX]
CMP DL,'0'
JB WRONG
CMP DL,'9'
JA WRONG
AND DL,0FH
ADD AL,DL
ADC AH,0
INC BX
LOOP T2
CMP AX,001EH;判断是否比30大
JA WRONG
CMP AX,0014H;判断是否比20小
JB WRONG
CMP AX,1
JB WRONG
MOV N,AX
RET
INPUT ENDP
FIB PROC
CMP N,1
JZ L1
CMP N,2
JZ L2
DEC N
CALL FIB
MOV AX,RESULT2L
MOV DX,RESULT2H
MOV CX,RESULT1L
ADD RESULT2L,CX
MOV CX,RESULT1H
ADC RESULT2H,CX
MOV RESULT1L,AX
MOV RESULT1H,DX
JMP EXIT
L1:MOV RESULT1L,1
MOV RESULT2L,1
JMP EXIT
L2:MOV RESULT2L,1
DEC N
CALL FIB
EXIT:RET
FIB ENDP
OUTPUTPROC
MOV AX,RESULT2L
LEA SI,OUTPUTBUFFER
MOV CX,5 ;二进制的16位65536十进制的五位
LO:MOV DX,0 ;低位加入OUTPUTBUFFER
DIV C10
INC SI
ADD [SI],DL ;dl为余数,最低位,要一位一位地放
LOOP LO
MOV AX,RESULT2H
LEA SI,OUTPUTBUFFER
MOV CX,5
HI:MOV DX,0
DIV C10
INC SI ;起始位在调整,即每次循环都要乘以10
PUSH CX ;高位加入OUTPUTBUFFER
CMP DX,0
JE NOADD ;dx为余数,余数不为0时要加上65536
MOV CX,DX ;dx为高位的余数,dx为几就要加上几个65536
ADDN:CALL ADD65536
LOOP ADDN
NOADD:POP CX
LOOP HI
LEA DX,STR2
MOV AH,9
INT 21H
LEA SI,OUTPUTBUFFER
MOV BX,10
R3:CMP BYTE PTR [SI+BX],'0'
JA PRINT
DEC BX ;si为起始地址,bx为偏移地址
JMP R3
PRINT:MOV DL,[SI+BX]
MOV AH,2
INT 21H
DEC BX
CMP BX,1
JAE PRINT
RET
OUTPUT ENDP
ADD65536PROC ;高位每一个都要加上一个加上65536
ADD BYTE PTR [SI],6
MOV DL,0
CMP BYTE PTR [SI],3AH
JB w1
SUB BYTE PTR [SI],10
MOV DL,1
w1:ADD BYTE PTR [SI+1],3
ADDBYTE PTR [SI+1],DL
MOV DL,0
CMP BYTE PTR [SI+1],3AH
JB w2
SUB BYTE PTR [SI+1],10
MOV DL,1
w2:ADD BYTE PTR [SI+2],5
ADD BYTE PTR [SI+2],DL
MOV DL,0
CMP BYTE PTR [SI+2],3AH
JB w3
SUB BYTE PTR [SI+2],10
MOV DL,1
w3:ADD BYTE PTR [SI+3],5
ADD BYTE PTR [SI+3],DL
MOV DL,0
CMP BYTE PTR [SI+3],3AH
JB w4
SUB BYTE PTR [SI+3],10
MOV DL,1
w4:ADD BYTE PTR [SI+4],6
ADD BYTE PTR [SI+4],DL
MOV DL,0
CMP BYTE PTR [SI+4],3AH
JB A0
SUB BYTE PTR [SI+4],10
MOVDL,1
w5:ADD BYTE PTR [SI+5],DL ;初始时只有前五位有数值
MOV DL,0
CMP BYTE PTR [SI+5],3AH
JB A0
SUB BYTE PTR [SI+5],10
MOV DL,1
w6:ADD BYTE PTR [SI+6],DL
MOV DL,0
CMP BYTE PTR [SI+6],3AH
JB A0
SUB BYTE PTR [SI+6],10
MOV DL,1
w7:ADD BYTE PTR [SI+7],DL
MOV DL,0
CMP BYTE PTR [SI+7],3AH
JB A0
SUB BYTE PTR [SI+7],10
MOV DL,1
w8:ADD BYTE PTR [SI+8],DL
MOV DL,0
CMP BYTE PTR [SI+8],3AH
JB A0
SUB BYTE PTR [SI+8],10
MOV DL,1
w9:ADD BYTE PTR [SI+9],DL
A0:RET
ADD65536 ENDP
QUIT: MOVAH,4CH
INT 21H
CODES ENDS
END START
问题3:编写一拷贝程序,要求在命令行指定源文件名和目标文件名。
分析过程:
代码分析:首先在数据段定义一个缓冲区用来接收源文件名和目的文件名,并定义提示相关信息的字符串。
然后再主程序段中主要调用了编号为3C(建立文件),3D(打开文件),3E(关闭文件),3F(读文件),40(写文件)的DOS功能。
运行结果截图:
首先,创建一个文件命名为1.txt,并添加文字
然后进行复制操作:
之后的结果:
可以看出,程序成功复制了文件。
完整代码如下所示:
DATAS SEGMENT
INFOR1 DB'Please input the goal file:$'
INFOR2 DB 'Please input the source file:$'
INFOR3 DB 'Copy successfully!$'
ERROR1 DB 'Can not open the file! Please make surewhether the source file is exit!',07H,'$'
ERROR2 DB 'Can not creat the file!',07H,'$'
ERROR3 DB 'Reading error!',07H,'$'
ERROR4 DB 'Writing error!',07H,'$'
HANDLE1 DW 0
HANDLE2 DW0
BUFFER DB 50
DB?
DB50 DUP (0)
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUMECS:CODES,DS:DATAS,SS:STACKS
START:
MOVAX,DATAS
MOV DS,AX
;此处输入代码段代码
MOV DX,OFFSET INFOR2
MOVAH,9H
INT21H
MOVDX,OFFSET BUFFER
MOVAH,0AH
INT21H
push AX
pushDX
MOV DL,0DH
MOV AH,2
INT 21H
MOV DL,0AH
MOV AH,2
INT 21H
POP DX
POP AX
LEASI,BUFFER
MOVAL,[SI+1]
XORAH,AH
ADDSI,2
ADDSI,AX
MOVBYTE PTR [SI],0
MOVDX,OFFSET BUFFER+2
MOVAX,3D00H
INT21H
JNCOPEN
MOVDX,OFFSET ERROR1
MOVAH,9H
INT21H
JMP OVER
OPEN: MOV HANDLE1,AX
MOVDX,OFFSET INFOR1
MOVAH,9H
INT21H
MOVDX,OFFSET BUFFER
MOVAH,0AH
INT21H
pushAX
pushDX
MOV DL,0DH
MOV AH,2 ;显示输出
INT 21H
MOV DL,0AH
MOV AH,2
INT 21H
POP DX
POP AX
LEASI,BUFFER
MOVAL,[SI+1]
XORAH,AH
ADD SI,2
ADDSI,AX
MOVBYTE PTR [SI],0
MOVDX,OFFSET BUFFER+2
MOVCX,0
MOVAH,3CH ;建立文件
INT21H
JNCCREAOK ;cf为一时溢出,复制错误
MOVBX,HANDLE1
MOVAH,3EH ;关闭文件
INT21H
MOVDX,OFFSET ERROR2
MOVAH,9H ;输入字符串
INT21H
JMPOVER
CREAOK: MOV HANDLE2,AX
CONT: MOV DX,OFFSET BUFFER
MOVCX,50
MOVBX,HANDLE1
MOVAH,3FH ;读文件
INT21H
JCREADERR
ORAX,AX
JZCOPY
MOVCX,AX
MOVBX,HANDLE2
MOVAH,40H ;写文件
INT21H
JCWRITERR
JMP CONT
READERR:MOV SI,OFFSET ERROR3
MOVAH,9H
INT21H
JMPCOPY
WRITERR:MOV SI,OFFSET ERROR4
MOVAH,9H
INT21H
COPY:MOV BX,HANDLE1
MOVAH,3EH
INT 21H
MOVBX,HANDLE2
MOVAH,3EH ;关闭文件
INT21H
MOVDX,OFFSET INFOR3
MOVAH,9H
INT21H
OVER: MOVAH,4CH
INT21H
CODES ENDS
END START
题目二:
虚拟平台的模型机实验,
1. 实验目的
1) 掌握模型机的基本原理和结构
2) 掌握机器指令与微程序的对应关系;
3) 掌握机器指令的执行流程;
2. 实验设备
74LS181芯片两片,memory 6116一片,微程序控制存储器芯片一片,编译器芯片一片,八位同步计数器芯片一片,ALU_G芯片一片,PC_G芯片一片,74LS273芯片若干,输入,输出芯片各一片,选择器芯片若干,连接器芯片若干,灯泡若干,开关若干等。
3. 实验原理
图1 模型机示意图
图1中所示模型机包括运算器、存储器、微控器、输入设备、输出设备以及寄存器。这些部件的动作控制信号都有微控器根据微指令产生。需要特别说明的是由机器指令构成的程序存放在存储器中,而每条机器指令对应的微程序存储在微控器中的存储器中。模型机详细原理见附件。
4. 实验内容
1) 选择实验设备,将所需要的组件从组件列表中拖到实验设计流程栏中
2) 搭建实验流程:根据原理图1和电路图(见附件),将已选择的组件进行连线。
3) 输入机器指令:选择菜单中的“工具”,再选择“模型机调试”,在指令输入窗口中输入如下指令:
00000000
00010000
00001001
00100000
00001011
00110000
实验分析与结果截图:
实验时的电路图如下所示:
下面是运行指令时的截图: