基于C语言模拟一个简易的冯诺依曼式计算机CPU的工作(bupt计导)

发布于:2025-03-01 ⋅ 阅读:(54) ⋅ 点赞:(0)

1 高层数据结构设计

(包括:重要的数据常量定义、数据变量定义,即各模块要共享的数据类型和参数设计,相当于头文件内容,加文字描述)

1.1 全局常量/变量定义

int Memory[50000];        //内存,下标0-16383为代码段,16384及其以后为数据   段,均以0和1的形式存储(二进制形式)
HANDLE hMutex,hMutexOfPrint;    //两个互斥对象的句柄
int Lockedaddress;              //被上锁的内存地址
typedef struct threadArugement
{
char filename[10];      //所要打开的文件名
int ax[9];              
int ip;                 
int ir; 
int flag;                 //一套寄存器
int id;                     //线程id 
int sell;             //所卖出去的票的总数
}  THREADARGUMENT ;           //结构体用于传参

2 系统模块划分

2.1 系统模块结构图

图2-1 模块结构图示例

1. 模块名称 main.c

模块功能简要描述:主函数,创建互斥对象,线程,开始一系列操作。

2. 模块名称Readcommand.c

模块功能简要描述:从指定的文件中读取二进制指令并存入指定内存中。

3. 模块名称 Distinguish.c

模块功能简要描述:识别指令,然后传入Operation.c中进行操作。

4. 模块名称 Conversion.c

模块功能简要描述:把数字根据要求完成进制的转换。

5. 模块名称 Operation.c

模块功能简要描述:根据不同的指令,调用Instructionsets.c中相对应得函数执行。

6. 模块名称 Instructionsets.c

模块功能简要描述:不同指令对应函数得集合

7. 模块名称 Print.c

模块功能简要描述:输出寄存器状态和segment

8.模块名称Run.c

模块功能简要描述:线程函数,执行不同得线程得指令

9.模块名称Initialization.c

模块功能简要描述:对结构体进行初始化,作为参数传入不同线程

模块功能简要描述:输出内存的代码段和数据段

2.2各模块函数说明

模块名称Readcommand.c

序号

函数原型

功能

参数

返回值

1

void Readcommand(char *name);

将指令从指定文件中存入内存的代码段

char *name

//指定文件的名称

模块名称 Distinguish.c:

序号

函数原型

功能

参数

返回值

1

int Distinguish(int *command,THREADARGUMENT *th);

识别指令,并通过Conversion.c转化二进制指令为十进制并存入指令寄存器,将识别的指令传入Operation.c执行。

int *command

//代码段内存中每段指令的首地址

THREADARGUMENT *th

//结构体参数

0:已运行至关机指令

1:未运行至关机指令

模块名称Conversion.c:

序号

函数原型

功能

参数

返回值

1

int conversion(int *str,int n);

把二进制数组的前n位看作一个二进制数并转化为十进制

int *str, int n

//二进制数组地址和需要转换的位数

转换后的十进制数

2

int *conversion_to_binary(int n);

把十进制转化成16位二进制

int n

//某十进制数

二进制数组的地址

3

void conversion_positive(int n,int *a);

把正的十进制转化成16位二进制

int n,int *a

//某十进制数和存放二进制得数组得首地址

4

void conversion_negative(int n,int *a);

把负的十进制转化成16位二进制

同上

模块名称 Operation.c:

序号

函数原型

功能

参数

返回值

1

int Operation(int key,int *binary,THREADARGUMENT *th);

执行指令

int key, int *binary

//key用来判断执行哪条指令,binary指向二进制指令

THREADARGUMENT *th

//结构体参数

0:已运行至关机指令

1:未运行至关机指令

模块名称Instructionsets.c:

序号

函数原型

功能

参数

返回值

2

void Convey(int *command,THREADARGUMENT *th);

数据传送

int *command

//某条指令

THREADARGUMENT *th

//结构体参数

3

void Calculate(int *command,int key,THREADARGUMENT *th);

算数运算的指令分析

int *command,

int key

//某条指令和进行加减乘除的判断标志

THREADARGUMENT *th

//结构体参数

4

void Add(int data,int register1,int register2,THREADARGUMENT *th);

加法

int data,int register1,int register2

//立即数和两个寄存器

THREADARGUMENT *th

//结构体参数

5

void Subtract(int data,int register1,int register2,THREADARGUMENT *th);

减法

同上

6

void Multiply(int data,int register1,int register2,THREADARGUMENT *th);

乘法

同上

7

void Divide(int data,int register1,int register2,THREADARGUMENT *th)

除法

同上

8

void Logicaloperation(int *command,int key,THREADARGUMENT *th);

逻辑运算的指令分析

int *command,

int key

//某条指令和进行与或非运算的判断标志

THREADARGUMENT *th

//结构体参数

9

void And(int data,int register1,int register2,THREADARGUMENT *th);

逻辑与运算

同(4)

10

void Or(int data,int register1,int register2,THREADARGUMENT *th)

逻辑或运算

同(4)

11

void Not(int data,int register1,int register2,THREADARGUMENT *th)

逻辑非运算

同(4)

12

void Compare(int *command,THREADARGUMENT *th);

比较运算

int *command

THREADARGUMENT *th

13

void Jump(int *command,THREADARGUMENT *th);

跳转指令

int *command

THREADARGUMENT *th

14

void Input(int *command,THREADARGUMENT *th);

输入指令

int *command

THREADARGUMENT *th

15

void Output(int *command,THREADARGUMENT *th);

输出指令

int *command

THREADARGUMENT *th

16

void Dormancy(int *command);

休眠

int *command

17

void Lock(int *command,THREADARGUMENT *th);

加锁

int *command

THREADARGUMENT *th

18

void Unlock(int *command,THREADARGUMENT *th);

解锁

int *command

THREADARGUMENT *th

模块名称 Print.c:

序号

函数原型

功能

参数

返回值

1

void Printmemory(void);

内存的代码段和数据段的输出

2

void Printregister(THREADARGUMENT *th);

寄存器状态输出

THREADARGUMENT *th

模块名称Run.c:

序号

函数原型

功能

参数

返回值

1

unsigned __stdcall run(void *pArgument);

线程函数

void *pArgument

0

模块名称Initialization.c:

序号

函数原型

功能

参数

返回值

1

void Initialization(THREADARGUMENT*th,int id);

初始化结构体

THREADARGUMENT*th,int id

//结构体指针

线程id

2.3 函数调用图示及说明

图2-2 函数调用关系图示例

解释说明:

函数run(---)为线程所要执行函数,通过调用函数Readcommand(---)实现读取指令,调用函数Printregister(---)来输出寄存器状态,调用函数Distinguish(---)来完成对二进制指令的识别。

函数Distinguish(---)识别完指令后,调用函数Operation(---)来执行指令,通过调用函数conversion(---)将二进制指令中的一部分指定寄存器内的十进制,将二进制指令中的特定的一部分转化成十进制传入函数Operation(---)内使用。

函数Operation(---)通过调用下面的一系列功能函数,来完成指令的要求,这被调用的一系列的函数都包含在Instructionsets.c模块中。

Instructionsets.c模块中的一系列函数调用函数conversion(---)和conversion_to_binary(---)来完成所需的进制间的转换,以便功能的实现。

3 高层算法设计

  1. 构建一个一维数组来模拟内存,从中间分开,前边为代码段,后面为数据段。然后再创建两个互斥对象(一个用于执行锁内存的指令,一个用于所输出)和两个线程。
  2. 用fgets 从指令文件中读取指令,每次读一行,即32位指令,存入代码段中,两个线程分别对应自己的代码段起始地址。关于模拟内存所的地址的规则:每使用8个数组单元地址就加一。(其实也可以创建一个二维数组)
  3. 将指令文件中的指令完全存入代码段后,对结构体初始化,便于对线程传参使用,然后每个线程从头开始对代码段进行读取,每次读取32位(即一个指令),然后识别,执行(执行完一条指令会有一个返回值,通过返回值判断是否读取到停机指令,从而停止),输出寄存器状态。其中加锁指令是让两个线程抢一个互斥对象,谁抢到谁就拥有对指定内存的改写权(就是创建一个变量,把它赋值为被锁的地址,每次遇到线程关于内存操作的时候就判断操作对象是不是被锁的地址,如果是就去判断此线程是否拿到了互斥对象,如果拥有互斥对象则可以对该内存进行读写,否则不可以)。相对应得解锁指令就是释放互斥对象就可以了。跳转指令是通过改变ip这个寄存器得值来实现的,ip=ip+立即数,因为立即数为补码,有正有负,所以用加。
  4. 指令读取完后,结束两个线程,关闭所有句柄,输出代码段内存和数据段内存即可,需注意两个线程的代码段内存起始地址不同。

网站公告

今日签到

点亮在社区的每一天
去签到