# 基于汇编语言的多任务飞机大战游戏
# 一 需求分析
系统所具备的功能包括:
- 飞机游戏
- 击落敌机
- 游戏结束
- 游戏暂停
- 游戏胜利
- 音乐播放器
- 音乐暂停
- 音乐开始
- 中断调度设计处理
- 采用轮转的方式进行任务的调度
- 采用软中断的方式来进行轮转
- 用PCB块来保存任务的上下文
- 在中断处理函数中切换中断上下文
- 系统能够实现对多个任务的管理,在调度方面采用时间片轮转的方式进行多个任务的调度;或者是在调度方面采用时钟中断的方式对多个任务进行切换,并且任务切换后,能够对任务的上下文信息进行保存
- 多个任务进行切换,如果当前任务是飞机游戏时,按左右键飞机会向左向右移动并发射子弹,当子弹打中敌机时,歼灭敌机;只有将全部的敌机通通歼灭才能获得胜利,否则游戏game over。选用软件中断的方式切换到音乐播放器的任务时或者飞机游戏
# 二 程序设计
## 2.1 设计内容
- 设计任务管理系统,对多个任务(任务数量≥2)进行管理和调度,能够实现任务之间的切换、保存上下文信息
- 任务数量有两个分别是飞机游戏和音乐播放
- 采用分屏的方式显示运行结果
- 采用轮转的方式进行任务调度
- 采用软件中断的方式进行任务切换,并且对内存指针指令的管理,实现上下文信息的保存与切换
## 2.2 系统结构
![](http://www.writebug.com/myres/static/uploads/2021/10/19/03361b01502bed7689bcfcb1d36fdadf.writebug)
## 2.3 游戏模块流程
![](http://www.writebug.com/myres/static/uploads/2021/10/19/cff3b1d23e374f4cc0139c3c461a8d02.writebug)
![](http://www.writebug.com/myres/static/uploads/2021/10/19/f333cce1f197f471b67edb9af5a8ab29.writebug)
## 2.4 中断处理流程
![](http://www.writebug.com/myres/static/uploads/2021/10/19/0acea7b6a70de6367a78da4558b71bf1.writebug)
## 2.5 音乐播放流程
![](http://www.writebug.com/myres/static/uploads/2021/10/19/4a278aed39c57c6c3e7c7dee72dfe2c7.writebug)
# 三 程序实现
## 3.1 功能模块实现
### 3.1.1 中断处理模块
**PCB与进程表**
我们用数组(而不是链表)来实现进程表,进程表含若干PCB(ProcessControl 部分段寄存器,用PUSH指令一个个压入栈。
```
PCB dw 0 ; ES || 部分段寄存器,用PUSH指令一个个压入栈
dw 0 ; DS /
dw 0 ; DI \
dw 0 ; SI | 指针寄存器 \
dw 0 ; BP | |
dw 0 ; SP / | 通用寄存器,用PUSHA指令一起压入栈
dw 0 ; BX \ |
dw 0 ; DX | 数据寄存器 /
dw 0 ; CX |
dw 0 ; AX /
dw 0 ; IP 指令指针寄存器 \
dw 0 ; CS 代码段寄存器 | 中断时由CPU压入栈
dw 0 ; Flags 标志寄存器 /
dw 0 ; SS 堆栈段寄存器,手工赋值
dw 1 ; ID 进程ID
Dw 0; 0是可以调度的,1是不可以调度的
```
### 3.1.2 中断处理
在实模式下,x86处理器在中断发生时执行如下操作:
- 将标志寄存器FLAGS值压入栈
- 先后将CS和IP寄存器中的当前值压入栈
- 清除标志寄存器FLAGS中的IF(中断允许标志)标志以禁止中断
- 清除标志寄存器EFLAGS中的TF(陷阱标志/单步调试)、RF([调试]恢复标志) 和AC(对齐检测标志)标志
- 转换程序控制到IVT指定的位置
### 3.1.3 复制数据块
我们PCB中的14个寄存器值,现在有13个在当前进程的栈中(另外一个是栈段寄存器SS)。我们安排在内核的调度函数schedule中,将这些寄存器值复制到进程表的对应PCB中。使用的是(功能为内存块复制的)重复字串传送指令REP MOVSW(以CX为计数值),它将DS:SI处的字传送到ES:DI处,并SI+=2、DI+=2、CX--,直到CX=0。
### 3.1.4 恢复上下文
因为恢复上下文寄存器,和栈切换,以及进程切换的准备操作,是交错进行的,所以程序的逻辑有些复杂,我们先尽可能多地恢复寄存器的值,再进行栈切换。但是将还需要使用到的DS先不恢复,而是在栈切换完成后,先压入新进程栈中,等以后切换进程前再弹出。IP和CS也从PCB中取出后压入新进程的栈中。在这些操作中还需使用一个寄存器,我们用的是SI,也需要先从PCB中取出压入新进程栈中,等最后一刻才恢复。
## 3.2 飞机游戏模块
- **绘制屏幕**
- 使用显示器与内存的映射关系,给内存写数据,然后显示到屏幕上
- **绘制敌机**
- 采用重力下降的方法来降落一个飞机
- **本机的方向的捕获**
- 使用BIOS中断来捕获键盘的事件,然后将方向存放到变量中,通过变量的值来判断方向在那里
- **是否调度音乐**
- 通过给PCB块赋值,在中断处理函数中判断
- **敌机是否存活**
- 使用变量来判断敌机是否死亡
## 3.3 音乐播放模块
音乐播放模块,顾名思义就是对音乐播放进行处理的模块。该模块通过对8255和8253对应接口赋予相应的值让其发声,实现了音乐的发声、暂停、结束、以及关闭扬声器的功能。
通过在8253中的42端口送入一个控制字0b6h,对定时器2进行初始化,使定时器2准备接受计数初值。当把输出端口61h的PB0和PB1两位置1时发声。
# 四 运行测试
按q键为暂停音乐,只显示飞机游戏的任务。再次按下w音乐继续播放。在飞机游戏中,按a键为暂停飞机游戏,只显示音乐的任务。s键来恢复飞机的任务。Z键来结束所有的任务,但是在只放音乐时,不能终止所有的任务。
![](http://www.writebug.com/myres/static/uploads/2021/10/19/d0cce792ef7c1fe464c285b642f03955.writebug)
![](http://www.writebug.com/myres/static/uploads/2021/10/19/6aa621c93c512327c4fd7df2c2c20e11.writebug)
![](http://www.writebug.com/myres/static/uploads/2021/10/19/502d474d2f74945992d9cd022d23db58.writebug)
![](http://www.writebug.com/myres/static/uploads/2021/10/19/89f0c9be9f38ef52bdee455d33ae6f69.writebug)
![](http://www.writebug.com/myres/static/uploads/2021/10/19/66be3ae890a43ac630b4743528d1225d.writebug)