一、实验目的
掌握汇编编程规范,熟悉编程环境。
二、实验内容
1、编写子程序把字符串中的小写字母转变为大写字母(参见教材实验11)。
2、编写0号中断处理程序,使得在除法溢出发生时在屏幕中间显示“divide error!”(参见教材实验12)。(请预习第12章并完成实验,时间不够则在课后完成)
三、实验步骤算法及关键代码
题目一
1.实验思路与算法
①思路:
本题其实没有在程序思想上设置难度,但重点是子程序和转变的问题,其中转变问题在第七章其实已经讲到,只需要循环取出数据区域的字符,与11011111B进行与运算,将每个字符ASCII码的第五位置置0,这样就可以实现小写转大写;子程序需要使用call语句与ret语句,其中在子程序中,由于有循环的产生且未给出既定的字符串长度,希望可以验证字符串中0的存在,因此需要使用je语句当做高级程序中的break语句,判断数据区的当前数据是否等于0,如果减0等于0,则跳出循环返回主程序;还需要使用jb,ja语句当做高级语言中的continue,这样其实大体的框架就搭好了。
②相关设置与算法:
设置DS存储数据区域的段地址datasg,设置SI存储当前读到的数据区的偏移地址;
子程序中需要进行字符串的大写转化:
取出一个数据,首先判断是否完成循环,与AH进行CMP运算,使用JE语句验证,如果ZF为一,则证明数据为0,由JE语句调到RET指令完成循环;
如果未完成循环,则进行字符判断,将字符分别与61H(‘a’)与7BH(“z”)进行CMP运算,若ASCII码范围不在61H-7BH中则跳出本次循环。
否则,将数据进行与运算之后传回原位置
子程序:
LETTERC:
S:MOV AH,[SI]
CMP AH,0
JE S2
CMP AH,61H
JB S1
CMP AH,7BH
JA S1
AND AH,11011111B
MOV [SI],AH
S1:INC SI
LOOP S
S2:RET
2.实验代码
ASSUME CS:CODESG
DATASG SEGMENT
DB "beginner's All-purpose Symbolic Instruction Code.",0
DATASG ENDS
CODESG SEGMENT
BEGIN:
MOV AX,DATASG
MOV DS,AX
MOV SI,0
CALL LETTERC
MOV AH,4CH
INT 21H
LETTERC:
S:MOV AH,[SI]
CMP AH,0
JE S2
CMP AH,61H
JB S1
CMP AH,7BH
JA S1
AND AH,11011111B
MOV [SI],AH
S1:INC SI
LOOP S
S2:RET
CODESG ENDS
END BEGIN
3.实验结果
处理后
题目二
1.实验思路与算法
①思路:
本题其实在教材中使用了大半个章节进行讲解,具体的思路其实比较清晰
首先需要将中断处理程序安装到指定的0:200-0:2FF,然后设置中断向量表,将0号中断向量表中的IP与CS内容指向0:200处;由于操作系统随时可能调用中断处理程序,所以需要将显示的内容“divide error!”也存到0:200-0:2FF中,这样的话就需要在do0程序中使用jmp指令转到真正需要使用的中断处理程序。
安装程序的方法需要使用串传送指令,将代码段中的do0程序直接传送到0:200-0:2FF中;
中断向量的设置其实就是将CS与IP传到0号向量空间;
在中断处理程序中,其实是将数据区的内容复制到显示缓冲区的相应位置中即可
②相关设置与算法
见注释
2.实验代码
ASSUME CS:CODES
CODES SEGMENT
START:
;DS指向代码段段地址(源地址)
MOV AX,CS
MOV DS,AX
;SI指向代码段的偏移地址(源地址)
MOV SI,OFFSET DO0
;ES指向目标段的段地址
MOV AX,0
MOV ES,AX
;DI指向目标段的偏移地址
MOV DI,200H
;CX存储DO0程序的长度
MOV CX,DO0END-OFFSET DO0
;设置传输方向为正
CLD
;按照Byte进行传输指令
REP MOVSB
;设置中断向量表
MOV AX,0
MOV ES,AX
MOV WORD PTR ES:[0],200H
MOV WORD PTR ES:[2],0
;除法溢出程序
MOV AX,1000H
MOV BH,1
DIV BH
MOV AX,4C00H
INT 21H
;由于需要让目标字串存到内存中防止程序结束后被修改,需要使用另一个标号指向真正的
DO0: JMP SHORT DO0START
DB "divide error!"
;由于到目标段时代码段地址一定存储着中断处理程序段地址,所以将DS和CS一致
DO0START: MOV AX,0
MOV DS,AX
;设置SI指向DB数据
MOV SI,202H
;设置ES指向显示屏的中心位置
MOV AX,0B800H
MOV ES,AX
MOV DI,12*160+36*2
;设置CX为字符串长度,便于读取
MOV CX,13
;读取DB数据并挪到显示屏内存中进行显示
S:MOV AL,[SI]
MOV ES:[DI],AL
INC SI
INC DI
INC DI
LOOP S
MOV AH,4CH
INT 21H
DO0END: NOP
CODES ENDS
END START
3.实验结果
四、实验小结(简单说明实验过程中出现的问题和解决方法)
本次实验分为两道题,第一道题中考察了对之前学习的知识的整体运用,并使用CMP与JA,JB,JZ指令完成了条件循环与break,continue功能,从而完成对目标字符串中符合要求的字符进行处理的目的,同时复习了大小写字母转换的相关知识;而第二个题目对新学习的中断处理程序与中断向量表的知识进行了一定的应用与设计,起初由于对CMP与条件指令的应用不熟,在编程过程中碰到了比较多的问题,尤其是在子程序中对语句的跳转,一度无法编译,最终发现是死循环的问题并进行了解决;而在第二道题中因为教材中其实有对实验的讲解与代码,重要的其实变成了对程序的理解,在编程过程中我选择了边编程边注释的方式,在自己的理解中完成这次的中断过程,最终对其的理解深了一层。
总体来说,本次的实验难度是有的,尤其是在子程序部分,子程序完成了对功能的划分与封装,这个思想其实和高级语言的函数有着异曲同工之妙,因此在使用子程序的时候和函数进行了一定的类比,最终成功完成了标号与跳转的一个对应,这个是我在本次实验中十分重要的收获。