【实验作业】微处理器原理与应用 CPUHomework4【汇编程序编写与提高 字符串复制 倒序显示字符串 中断调用 显示随机数 学生成绩统计标志寄存器 比较指令 字符串处理 CLI STI REP】

实验报告

课程名称:微处理器原理与应用
实验名称:CPUHomework4

【实验四】汇编程序编写与提高

1. 编写一个汇编程序,实现字符串的复制功能,并且将复制的字符串显示出来 (选做:倒序显示复制字符串)

流程图如下:

在这里插入图片描述

程序代码如下:

datas segment
	string_a db 'The School of Information Science and Engineering Shandong University','$'	; 定义字符串
datas ends

ext segment	; 附加段
	string_b db 100 dup(?)	; 开辟一个100字节的空间
ext ends

stacks segment
stacks ends

codes segment
	assume cs:codes,ds:datas,ss:stacks,es:ext
start:
	mov ax,datas	; 将datas的地址交给ds
	mov ds,ax
	mov ax,ext	; 将ext的地址交给es
	mov es,ax
	
	lea si, string_a	; 将string_a的地址交给si源变址寄存器
	lea di, string_b	; 将string_b的地址交给di目的变址寄存器
	
	mov cx, 72	; 循环72次
	std	; 方向标志位DF(Direction Flag)置1
	rep movsb	; repeat move string byte
	
	lea dx, string_b	; 将string_b的地址交给dx
	mov ah, 9	; 输出字符串
	int 21h	
	
	mov ah,4ch	; 返回dos
	int 21h
	
codes ends
	end start

程序运行结果如下:

在这里插入图片描述

倒序显示流程图如下:

请添加图片描述

倒序显示代码如下:

datas segment
	string_a db 'The School of Information Scinence and Engineering Shandong University','$'
datas ends

ext segment
	string_b db 100 dup(?)	; 开辟一个100字节的空间
ext ends

stacks segment
stacks ends

codes segment
	assume cs:codes, ds:datas, ss:stacks, es:ext

start:
	mov ax, datas
	mov ds, ax
	
	mov ax, ext
	mov es, ax
	
	lea si, string_a
	lea di, string_b
	
	mov cx, 72
	cld	; 方向标志位DF(Direction Flag)置0
	rep movsb
	
	lea dx, string_b
	mov ah, 9	; 输出字符串
	int 21h
	
	mov ah, 2	; 回车换行
	mov dl, 0dh
	int 21h
	mov ah, 2
	mov dl, 0ah
	int 21h
	
	mov cx, 72
	mov si, 69
	
loops: 
	mov dl, [si]	; 将si开始的第一个字符存入dl
	mov ah, 2
	int 21h	; 输出字符
	dec si	; si减1, 从而实现倒序输出
	loop loops
	
	mov ah, 4ch
	int 21h

codes ends
	end start

程序运行结果如下:

在这里插入图片描述

2. 利用中断调用,在屏幕上显示1-9之间的随机数。中断号86H (使用定义法和DOS INT21法实现)

流程图如下:

在这里插入图片描述

datas segment
	info db 0dh, 0ah, 'Random Number:', '$'	; 提示语句
	dw 100 dup(?)	; 开辟100字的空间
datas ends

stacks segment stack
stacks ends

codes segment
	assume ds:datas, ss:stacks, cs:codes

Random proc near
	mov ah, 0
	int 1ah	; 读取时钟滴答计数
	mov ax, dx
	mov dx, 0
	mov bx, 10
	div bx
	add dl, 30h	; 将dl中的数据转换为对应的ASCII码
	
	mov ah, 02h	; 输出数字
	int 21h
	ret
Random endp

start:
	mov ax, datas
	mov ds, ax
	lea dx, info
	mov ah, 9
	int 21h
	
	mov ax, 0	; 设置中断向量(定义法)
	mov ds, ax
	cli
	mov word ptr ds:[86h * 4], offset Random
	mov word ptr ds:[86h * 4 + 2], seg Random
	sti
	int 86h	; 调用子程序
	
	mov ah, 4ch
	int 21h
codes ends
	end start

程序运行结果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

INT 21法如下:

datas segment
	info db 0dh, 0ah, 'New Random Number:', '$'	; 提示语句
	dw 100 dup(?)	; 开辟100字的空间
datas ends

stacks segment stack
stacks ends

codes segment
	assume ds:datas, ss:stacks, cs:codes

Random proc near
	mov ah, 0
	int 1ah	; 读取时钟滴答计数
	mov ax, dx
	mov dx, 0
	mov bx, 10
	div bx
	add dl, 30h	; 将dl中的数据转换为对应的ASCII码
	
	mov ah, 02h	; 输出数字
	int 21h
	ret
Random endp

start:
	mov ax, datas
	mov ds, ax
	lea dx, info
	mov ah, 9
	int 21h
	
	mov ax, stacks
	mov ss, ax
	
	mov ax, seg Random
	mov ds, ax
	mov dx, offset Random
	mov al, 86h
	mov ah, 25h
	int 21h
	
	int 86h	; 调用子程序
	
	mov ah, 4ch
	int 21h
codes ends
	end start

程序运行结果如下:

在这里插入图片描述

在这里插入图片描述

3. 键盘输入10个学生的成绩,编写一个程序统计60-69分,70-79分,80-89分,90-99分以及100分的人数,分别存放在 Score6,Score7,Score8,Score9和Score10单元中

【输入10个学生的成绩如下】

65 98 78 82 88 95 72 62 90 100

流程图如下:

在这里插入图片描述

datas segment
	info db 0dh, 0ah, 'Input ten scores:','$'	; 提示输入10个score
	o_ten db 0dh, 0ah, 'The number of 100 is  :', '$'	; 输出提示
	o_nine db 0dh, 0ah, 'The number of 90 to 99 is  :', '$'
	o_eight db 0dh, 0ah, 'The number of 80 to 89 is  :', '$'
	o_seven db 0dh, 0ah, 'The number of 70 to 79 is  :', '$'
	o_six db 0dh, 0ah, 'The number of 60 to 69 is  :', '$'
	
	s_ten db 30h	; 初始化
	s_nine db 30h
	s_eight db 30h
	s_seven db 30h
	s_six db 30h
datas ends

stacks segment
	db 100 dup(?)	; 开辟100字节的栈空间
stacks ends

codes segment
	assume cs:codes, ds:datas, ss:stacks

start:
	mov ax, datas
	mov ds, ax
	
	lea dx, info
	mov ah, 9
	int 21h
	
	mov cx, 10
input:
	mov ah, 1	; 键盘录入并回显
	int 21h
	mov dl, al	; al = 输入字符
	int 21h
	
	call judge
	
	mov dl, 32	; 输出空格,使输入更加清晰
	mov ah, 2	; 显示输出, dl = 输出字符
	int 21h
	
	loop input
	
	call output
	
	mov ah, 4ch
	int 21h
	
judge proc near
	cmp dl, 31h	; dl与1的ASCII码比较
	jz ten
	cmp dl, 36h
	jz six
	cmp dl, 37h
	jz seven
	cmp dl, 38h
	jz eight
	cmp dl, 39h
	jz nine
	jmp fin
	
ten:
	add [s_ten], 1
	mov ah, 1
	int 21h
	jmp fin
six:
	add [s_six], 1
	jmp fin
seven:
	add [s_seven], 1
	jmp fin
eight:
	add [s_eight], 1
	jmp fin
nine:
	add [s_nine], 1
	jmp fin
	
fin:
	ret
	
judge endp

output proc near
	lea dx, o_ten
	mov ah, 9
	int 21h
	mov dl, [s_ten]	; 输出100分的人数
	mov ah, 2
	int 21h
	mov dl, 10	; 输出空格
	int 21h
	
	lea dx, o_nine
	mov ah, 9
	int 21h
	mov dl, [s_nine]	; 输出90-99的人数
	mov ah, 2
	int 21h
	mov dl, 10
	int 21h
	
	lea dx, o_eight
	mov ah, 9
	int 21h
	mov dl, [s_eight]	; 输出80-89的人数
	mov ah, 2
	int 21h
	mov dl, 10
	int 21h
	
	lea dx, o_seven
	mov ah, 9
	int 21h
	mov dl, [s_seven]	; 输出70-79的人数
	mov ah, 2
	int 21h
	mov dl, 10
	int 21h
	
	lea dx, o_six
	mov ah, 9
	int 21h
	mov dl, [s_six]	; 输出60-69的人数
	mov ah, 2
	int 21h
	
	ret
output endp
codes ends
	end start

程序运行结果如下:

在这里插入图片描述

【知识点】

标志寄存器PSW (程序状态字寄存器PSW)

标志寄存器PSW是一个16位的寄存器。它反映了CPU运算的状态特征并且存放某些控制标志。8086使用了16位中的9位,包括6个状态标志位和3个控制标志位

六个状态标志位

CF进位标志位:当执行一个加法(减法)运算时,最高位产生进位(或借位)时,CF为1,否则为0
ZF零标志位:若当前的运算结果为零,则ZF为1,否则为0
SF符号标志位:该标志位与运算结果的最高位相同。即运算结果为负,则SF为1,否则为0
OF溢出标志位:若运算结果超出机器能够表示的范围称为溢出,此时OF为1,否则为0。判断是否溢出的方法是:进行二进制运算时,最高位的进位值与次高位的进位值进行异或运算,若运算结果为1则表示溢出OF=1,否则OF=0
PF奇偶标志位:当运算结果的最低16位中含1的个数为偶数则PF=1否则PF=0
AF辅助进位标志位:一个加法(减法)运算结果的低4位向高4位有进位(或借位)时则AF=1否则AF=0

三个控制标志位

用来控制CPU的操作,可以由程序进行置位和复位
TF跟踪标志:该标志位为方面程序调试而设置。若TF=1,8086/8088CPU处于单步工作方式,即在每条指令执行结束后,产生中断。
IF中断标志位:该标志位用来控制CPU是否响应可屏蔽中断。若IF=1则允许中断,否则禁止中断。
DF方向标志位:该标志位用来控制串处理指令的处理方向。若DF=1则串处理过程中地址自动递减,否则自动递增。

比较指令 CMP

格式: CMP A,B

功能: 两个操作数的相减,即从A中减去B,其结果会影响标志位,对标志位的影响与SUB指令相同。本条指令主要是用于配合条件转移指令使用。如JZ ZF=0时,跳转

**条件转移指令 **JE/JZ

格式: JE/JZ 标号

功能: ZF=1,转到指定地址执行

说明:

  1. 指令JE与JZ等价,它们是根据标志位ZF进行转移的指令

  2. JE,JZ均为一条指令的两种助记符表示方法

CLD(CLear Direction flag):将标志寄存器Flag的方向标志位DF清零。在字串操作中使变址寄存器SI或DI的地址指针自动增加,字串处理由前往后

STD(SeT Direction flag):与CLD相反功能指令是STD,即将方向标志位DF置1。在字串操作中使SI或DI的地址指针自动递减,字串处理由后往前。STD用于将方向标志设置为1,使得Si和/或DI将自动递减到当其中一个字符串指令执行时指向下一个字符串元素。如果方向标志被设置,SI/DI对于字节字符串将减1,对于字符串将减2

**SI(source index)**源变址寄存器
DI(destination index)目的变址寄存器
SI和DI可以用来存放
数据、地址
,功能类似、用法类似、一般使用哪个都可以

但在串处理指令中,SI用作隐含的源串地址,默认在DS中;
DI用做隐含的目的串地址,默认在ES中

此时二者不能混用

si:指向要显示的字符
di:指向要存放的位置(目的空间)

字符串处理指令:是一种非数值处理指令,一般包括字符串传送字符串转换(把一种编码的字符串转换成另一种编码的字符串)、字符串替换(把某一字符串用另一字符串替换)等。这类指令在文字编辑中对大量字符串进行处理

MOVSB字符串传送指令,这条指令按字节传送数据。通过SI和DI这两个寄存器控制字符串的源地址和目标地址,比如DS:SI这段地址的N个字节复制到ES:DI指向的地址,复制后DS:SI的内容保持不变

中断是输入/输出程序中常用的控制方式,是指计算机暂停当前正在执行的程序而转去执行处理某事件的中断服务程序

当中断服务程序执行完毕,再恢复执行被暂时停止的程序

CLI汇编指令全称为Clear Interupt,该指令的作用是禁止中断发生,在CLI起效之后,所有外部中断都被屏蔽,这样可以保证当前运行的代码不被打断,起到保护代码运行的作用

STI汇编指令全称为Set Interupt,该指令的作用是允许中断发生,在STI起效之后,所有外部中断都被恢复,这样可以打破被保护代码的运行,允许硬件中断转而处理中断的作用

REP 指令即“重复前缀指令”, REP 前缀一次只能应用于一条字符串指令。要重复指令块,需要使用 LOOP 指令或其它循环结构。因此需要一个寄存器来控制串长度。这个寄存器就是CX,指令每次执行前都会判断CX 的值是否为0(为0 结束重复,不为0,CX 的值减1),以此来设定重复执行的次数

【实验心得】

这是微处理器原理与应用汇编的最后一次实验,这一次的心得也是之前所有汇编实验以及微处理器课程的总的体会

CPUHomework1.1的DOS方式以及Masm for Windows 集成实验环境的配置以及对Debug调试基本命令的学习为我之后的实验打下了基础,为我打开了汇编的大门

CPUHomework1.2让我更系统透彻地学习了Debug的六大功能,在此期间了解了CPU各种寄存器,内存以及程序运行之间的底层联系,同时也学会了许多基本的汇编程序指令,这次实验让我印象深刻,教会我只有不断地重复实践才能更快更好地掌握一系列汇编知识,正所谓纸上得来终觉浅,绝知此事要躬行

CPUHomework2.1则是对之前C语言学习的二进制原反补码的进一步理解,让我更多的角度去感受二进制的魅力

CPUHomework2.2 是分支程序实验和循环程序实验,对于分支语句和循环语句我们都已经很熟悉了,但是汇编语言的实现明显和绝大多数的高级语言不同,我们需要使用各种程序控制指令或者说是控制转移指令,有转移指令,循环控制指令,过程调用指令以及中断指令,这一次也为后面的程序编写打下了基础

CPUHomework3以及这次的CPUHomework4都是实战,在学习基础知识的基础上增加了程序逻辑设计的环节,让我们可以很好地体会到汇编语言编程的独特之处

在学习汇编的过程中遇到过许许多多的困难,但是如今的互联网为我们提供了许许多多的解决之道,汇编这个领域有许许多多的技术人的足迹也给我们这些初学者指引了前进的方向

最后,还是说咱痛并快乐着吧,这么课程的前半部分微处理器原理与汇编让我学到了许多,但更让我感受到的是自己的不足,我们唯一能做的就是继续努力!

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zanebla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值