Assigment2复盘
写在开始:
1.刚开始时有大致思路,没有头绪。沉淀大概一个星期后,又看到别人代码思路自己试着理解形成大致思路。
2.将思路要求等付诸纸面,看一看自己需要解决那些问题,将一个大问题进行肢解。直到肢解到自己可以解决的大小为止。
3.每次重构自己的Shit Mountion都是在理顺思路和逻辑。重构未必是坏事。
程序要求:
Write a C++ program that simulates the MASSEY machine. The program must receive input in the form of a text file consisting of MASSEY machine code instructions. Your program then simulates the machine running, i.e. it works through the machine code instructions (in the correct sequence) changing values of registers and memory locations as required. You must design appropriate output that assists a machine code programmer to see what is going on with the machine code instructions. You shoulddisplay items such as program counter, instructions register, values of recently changed registers, and values of recently changed memory locations.
译:
编写一个模拟MASSEY机器的C++程序。程序必须接收由Massey机器代码指令组成的文本文件形式 的输入。然后,您的程序将模拟机器的运行,即。它通过机器代码指令(按正确的顺序)根据需 要改变寄存器和内存位置的值。您必须设计适当的输出,帮助机器代码程序员查看机器代码指令 发生了什么。您应该显示诸如程序计数器、指令寄存器、最近更改的寄存器的值和最近更改的内 存位置的值等项目。
Section A - input
The input to your program is a single text file containing a MASSEY machine code program.For example, here is a typical input file where each line is a machine code instruction:
1102
1203
6012
40FF
E000
Notes about the input:
- The programmer using the simulation can give the file whatever name they like. It is best to read
in the file name when you start. A typical file name would be “prog1.txt”. - Each line of the file is one machine code instruction. There is no other text in the file.
- Make several (at least five) different files, each with a different machine code program. Test your
program on a variety of machine code programs. - Do not attempt to check for invalid input. Assume every program contains correct machine code
instructions although a program may have logic errors, e.g. instructions in the incorrect order.
译:
程序的输入是一个包含Massey机器代码程序的单个文本文件。例如,这里是一个典型的输入文件,其中每一行都是一个机器代码指令:
1102
1203
6012
40FF
E000
注意:
1.使用该模拟的程序员可以给该文件提供任何他们喜欢的名称。最好在启动时读取文件名。一个典型的文件名应该是“prog1”。txt" .2.该文件的每一行都是一条机器代码指令。该文件中没有其他文本。 3.制作几个(至少五个)不同的文件,每个文件都有不同的机器代码程序。在各种机器代码程序 上测试您的程序。 4.不要尝试检查是否有无效的输入。假设每个程序都包含正确的机器代码指令,尽管一个程序可能有逻辑错误,例如指令的顺序不正确。
Section B – program design
Your program must use the following global variables:
int memory[256];
int reg[16]; // note: “register” is a reserved word
int pc, ir;
The array “memory” represents the memory of the MASSEY machine.
The array “registers” represents the registers of the MASSEY machine.
The variable “pc” is the Program Counter and “ir” is the instruction register.
The basic algorithm for your program is:
• read instructions from the file and load them into memory
• run through the instructions and execute each instruction correctly
Notes about the program design:
5. Study the MASSEY machine code instructions in the notes.
6. Ensure that your program correctly executes and valid machine code instruction.
7. You do not have to execute instruction 5 (floating point addition) – ignore instruction 5.
8. Do not check for invalid instructions. Only deal with valid instructions.
9. You must have at least two functions in your program.
10. Test extensively. Ensure that you have tested every instruction (except 5). Use machine code
programs from the notes as test data.
译:
您的程序必须使用以下全局变量:
int memory[256];
int reg[16];//注意:“寄存器”是一个保留的词
int pc, ir;
数组“内存”表示Massey机器的内存。 数组“寄存器”表示Massey机器的寄存器。 变量“pc”是程序计数器,“ir”是指令寄存器。
您的程序的基本算法是: 从文件中读取指令,并将其加载到内存中 运行这些指令并正确地执行每个指令 记下 关于 那 程序 设计 5.研究注释中的MASSEY机器代码说明。 6.确保您的程序正确地执行和有效的机器代码指令。 7.您不必执行指令5(浮点加法)-忽略指令5。 8.不要检查是否无效的指令。只处理有效的指令。 9.您的程序中必须至少有两个函数。 10.测试广泛。确保您已经测试了每条指令(5条除外)。使用注释中的机器代码程序作为测试数据。
Section C - output
The output must meet the following requirements:
- display the full program (showing the memory locations) before executing the program
- identify the important items to display during execution of the instructions
- display one line for every machine code instruction (showing any changes)
For example, your display could look like this:
Enter the file name of the MASSEY machine code: program1.txt
Memory[0] = 1102
Memory[1] = 1203
Memory[2] = 6012
Memory[3] = 40FF
Memory[4] = E000
1102 R1 = 0002 PC = 1
1203 R2 = 0003 PC = 2
6012 R0 = 0005 PC = 3
40FF Memory[FF] = 0005 PC = 4
Halt
Notes about the output:
- Display one line of output for each machine code instruction – just after it has been executed.
- On each line, display the current instruction and the Program Counter (which is loaded with the address of the next instruction).
- On each line, display any registers that have changed. E.g. the first instruction above loads R1 so the value in R1 is displayed.
- On each line, display any memory locations that have changed. E.g. the fourth instruction above loads a value into memory location FF so the value in memory[FF] is displayed.
译:
输出值必须满足以下要求: 在执行程序之前显示完整的程序(显示内存位置) 识别在执行指令期间要显示的重要项目 -为每条机器代码指令显示一行(显示任何更改) 例如,您的显示器可能是这样的: 输入MASSEY机器代码的文件名: program1.txt 记下 关于 那 产量 11.为每个机器代码指令显示一行输出-就在它被执行之后。 12.在每一行上,显示当前指令和程序计数器(加载下一条指令的地址)。 13.在每一行上,显示所有已更改的所有寄存器。E.g.上面的第一个指令加载R1,因此显示R1中 的值。 14.在每一行上,显示任何已更改的内存位置。E.g.上面的第四条指令将值加载到内存位置FF, 从而显示内存位置FF中的值。
以下是机器指令所代表含义:
1RXY Load register R with the value XY.
e.g. 1213 means load register R2 with the hexadecimal number 13 (19 in decimal).
20RS Load register R with the number in register S.
e.g. 20A7 means load register R10 with the number in register R7.
3RXY Load register R with the number in the memory location at address XY.
e.g. 34AB means load register R4 with the contents from memory location AB
4RXY Store the number in register R in the memory location at address XY.
e.g. 45B1 means store the contents of register R5 in the memory location B1
5RST Add the numbers in registers S and T and load the result into register R.
Note: this is floating point addition.
e.g. 534E means add the numbers in R4 and R14 and load the result into R3.
6RST Add the numbers in registers S and T and load the result into register R.
Note: this is integer addition using 2’s complement arithmetic.
e.g. 6823 means add the contents of R2 and R3 and load the result into R8.
70R0 Negate register R. (Carry out complement and add 1 – in effect, multiply R with -1)
e.g. 70A0 means multiply the number in R10 by -1.
8R0X Shift the number in register R to the right X times.
e.g. 8403 means that the number in R4 must be shifted 3 bits to the right.
9R0X Shift the number in register R to the left X times.
e.g. 9602 means that the number in R6 must be shifted 2 bits to the left.
ARST AND the numbers in registers S and T and load the result into register R.
e.g. A045 means AND the numbers in R4 and R5 and load the result into R0.
BRST OR the numbers in registers S and T and load the result into register R.
e.g. BC74 means OR the numbers in R7 and R4 and load the result into R12.
CRST XOR the numbers in registers S and T and load the result into register R.
e.g. C5F3 means XOR the numbers in R15 and R3 and load the result into R5.
DRXY Jump to the instruction at address XY if the value in register R is equal
to the value in register R0.
e.g. D43C means the following:
(a) compare the contents of R4 with R0.
(b) if they are equal load 3C into the program counter.
E000 Halt
题主遇到的问题:
一.文件问题:1.对指定名称文件进行读取 2. 根据文件内容选择读取方式 3.对文件操作函数不熟悉
二.函数问题:1.函数如何操作函数之外的变量 2.引用调用不可对数组进行操作?
三.流输入输出格式化问题
四.计算机操作的实质问题、二进制、十进制、十六进制的操作、逻辑操作问题
五.官方文档的阅读能力问题
Show Something you want
能动手就别bb
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
//-----------Must to be used Var------------------
int memory[256];
int reg[16];
int pc , ir;
//--------------Own var---------------------------
int CodeNum;//the number of MasseyCode
int OperateNum,SecondNum,ThirdNum,FourthNum;
ifstream file;
//--------------Some Function---------------------
//这个函数就是以4位宽度输出不足位数用0补齐,但只对最近的一个cout有作用,题主犯懒所以写个函数调用它俩
void Output_with0_in4()
{
cout.width(4);
cout.fill('0');
}
//将文本中的机器码写入memory,并按格式输出
void Loading()
{
for(int i = 0; i <256; i++){
file>>hex>>memory[i];
cout<<"Memory["<<i<<"] = ";
Output_with0_in4();//NOTE!OutPut also should be in Patten
cout<<hex<<uppercase<<memory[i]<<endl;
CodeNum = i + 1;
if(file.eof()){
break;
}
}
cout<<endl;
}
//得到机器指令的每一位数字,注意这里用到的十六进制逻辑操作方法
void GetEveryPostionNumber(int Messycode)
{
OperateNum = Messycode >> 12;
SecondNum = (Messycode & 0X0f00) >> 8;
ThirdNum = (Messycode & 0x00f0) >> 4;
FourthNum = Messycode & 0X000f;
}
//输出函数
void Display(int RegChangedPostion,int RegChangedValue,int MemChangedPostion,int MemChangedValue,int choice)
{
if(choice > 0)
{
cout<<"R";
cout<<hex<<uppercase<<RegChangedPostion<<" = ";
Output_with0_in4();
cout<<hex<<uppercase<<RegChangedValue<<" ";
}
else
{
cout<<"Memory[";
cout<<hex<<uppercase<<MemChangedPostion<<"] = ";
Output_with0_in4();
cout<<hex<<uppercase<<MemChangedValue<<" ";
}
}
int main(){
//--------------------------------------------
//printf all the MasseyCode in Memory
string FileName;
cout<<"Enter the file name of the MASSEY machine code: ";
cin>>FileName;
cout<<endl;
file.open(FileName.c_str(),ios::in);
if(!file.is_open()){
cout<<"File Open Was Wrong!"<<endl;
return 0;
}
Loading();
//---------------------------------------------
//Execute the MasseyCoed in ir
for(int i = 0; i < CodeNum ; i++)
{
//-----------------------------------------
//Load ir with MeassyCode in Memory
labs:
ir = memory[i];
//printf currently executed MeassyCode
if(ir == 0xE000)
{
cout<<"Halt";
}
else
{
cout<<ir<<" ";
}
//--------------------Executing----------------------------
GetEveryPostionNumber(ir);
switch (OperateNum)
{
case 1:
reg[SecondNum] = ThirdNum * 16 + FourthNum;
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 2:
reg[ThirdNum] = reg[FourthNum];
Display(ThirdNum,reg[ThirdNum],0,0,1);
break;
case 3:
reg[SecondNum] = memory[ThirdNum * 16 + FourthNum];
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 4:
memory[ThirdNum * 16 + FourthNum] = reg[SecondNum];
Display(0,0,(ThirdNum *16 + FourthNum),memory[ThirdNum * 16 + FourthNum],-1);
break;
case 5:
//Needn't to be considered
case 6:
reg[SecondNum] = reg[ThirdNum] + reg[FourthNum];
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 7:
reg[ThirdNum] = -1 * reg[ThirdNum];
Display(ThirdNum,reg[ThirdNum],0,0,1);
break;
case 8:
reg[SecondNum] = reg[SecondNum] >> FourthNum;
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 9:
reg[SecondNum] = reg[SecondNum] << FourthNum;
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 10:
reg[SecondNum] = reg[ThirdNum] & reg[FourthNum];
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 11:
reg[SecondNum] = reg[ThirdNum] | reg[FourthNum];
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 12:
reg[SecondNum] = reg[ThirdNum] ^ reg[FourthNum];
Display(SecondNum,reg[SecondNum],0,0,1);
break;
case 13:
//特殊处理pc
if(reg[SecondNum] == reg[0])
{
cout<<" "<<"PC = ";
i = ThirdNum * 16 + FourthNum;
cout<< i <<endl;
goto labs;
}
else
{
cout<<" ";
}
break;
case 14:
return 0;//Note!when it equal E menas over.
}
//---------------------Output PC-----------------------------------
//注意pc的处理,跳转和不跳转分开处理,还是要理解pc的实质:指向将要处理的指令地址
pc = i + 1 ;
if( ir != 0xE000 ){
cout<<"PC = "<<pc<<endl;
}
}
}
//
// .::::.
// .::::::::.
// :::::::::::
// ..:::::::::::'
// '::::::::::::'
// .::::::::::
// '::::::::::::::..
// ..::::::::::::.
// ``::::::::::::::::
// ::::``:::::::::' .:::.
// ::::' ':::::' .::::::::.
// .::::' :::: .:::::::'::::.
// .:::' ::::: .:::::::::' ':::::.
// .::' :::::.:::::::::' ':::::.
// .::' ::::::::::::::' ``::::.
// ...::: ::::::::::::' ``::.
// ````':. ':::::::::' ::::..
// '.:::::' ':'````..
给出几个测试案例:
题干中给出的
//此txt文本文件名称: prog1.txt
1102
1203
6012
40FF
E000
本代码结果:
Enter the file name of the MASSEY machine code: prog1.txt
Memory[0] = 1102
Memory[1] = 1203
Memory[2] = 6012
Memory[3] = 40FF
Memory[4] = E000
1102 R1 = 0002 PC = 1
1203 R2 = 0003 PC = 2
6012 R0 = 0005 PC = 3
40FF Memory[FF] = 0005 PC = 4
Halt
测试DRXY(题主自测)
案例一:
//此txt文本文件名称: prog7.txt
1012
1112
1212
D105
1312
D208
1412
1512
1612
Enter the file name of the MASSEY machine code: prog7.txt
Memory[0] = 1012
Memory[1] = 1112
Memory[2] = 1212
Memory[3] = D105
Memory[4] = 1312
Memory[5] = D208
Memory[6] = 1412
Memory[7] = 1512
Memory[8] = 1612
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
1212 R2 = 0012 PC = 3
D105 PC = 5
D208 PC = 8
1612 R6 = 0012 PC = 9
案例二:
//此txt文本文件名称: prog6.txt
1012
1112
D104
1513
1212
Enter the file name of the MASSEY machine code: prog6.txt
Memory[0] = 1012
Memory[1] = 1112
Memory[2] = D104
Memory[3] = 1513
Memory[4] = 1212
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D104 PC = 4
1212 R2 = 0012 PC = 5
案例三:
//此txt文本文件名称: prog8.txt
//等价于
/* i = 9;
while (i >= 0) {
i--;
}
*/
1080
9008
1209
4247
1A01
70A0
3347
A230
D20C
633A
4347
D006
E000
Enter the file name of the MASSEY machine code: prog8.txt
Memory[0] = 1080
Memory[1] = 9008
Memory[2] = 1209
Memory[3] = 4247
Memory[4] = 1A01
Memory[5] = 70A0
Memory[6] = 3347
Memory[7] = A230
Memory[8] = D20C
Memory[9] = 633A
Memory[A] = 4347
Memory[B] = D006
Memory[C] = E000
1080 R0 = 0080 PC = 1
9008 R0 = 8000 PC = 2
1209 R2 = 0009 PC = 3
4247 Memory[47] = 0009 PC = 4
1A01 RA = 0001 PC = 5
70A0 RA = FFFFFFFF PC = 6
3347 R3 = 0009 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0008 PC = A
4347 Memory[47] = 0008 PC = B
D006 PC = 6
3347 R3 = 0008 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0007 PC = A
4347 Memory[47] = 0007 PC = B
D006 PC = 6
3347 R3 = 0007 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0006 PC = A
4347 Memory[47] = 0006 PC = B
D006 PC = 6
3347 R3 = 0006 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0005 PC = A
4347 Memory[47] = 0005 PC = B
D006 PC = 6
3347 R3 = 0005 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0004 PC = A
4347 Memory[47] = 0004 PC = B
D006 PC = 6
3347 R3 = 0004 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0003 PC = A
4347 Memory[47] = 0003 PC = B
D006 PC = 6
3347 R3 = 0003 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0002 PC = A
4347 Memory[47] = 0002 PC = B
D006 PC = 6
3347 R3 = 0002 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0001 PC = A
4347 Memory[47] = 0001 PC = B
D006 PC = 6
3347 R3 = 0001 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = 0000 PC = A
4347 Memory[47] = 0000 PC = B
D006 PC = 6
3347 R3 = 0000 PC = 7
A230 R2 = 0000 PC = 8
D20C PC = 9
633A R3 = FFFFFFFF PC = A
4347 Memory[47] = FFFFFFFF PC = B
D006 PC = 6
3347 R3 = FFFFFFFF PC = 7
A230 R2 = 8000 PC = 8
D20C PC = C
Halt
案例四:
//此txt文本文件名称: endlessloop.txt
1012
1112
D100
Enter the file name of the MASSEY machine code: endlessloop.txt
Memory[0] = 1012
Memory[1] = 1112
Memory[2] = D100
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D100 PC = 0
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D100 PC = 0
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D100 PC = 0
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D100 PC = 0
........
........
........
1012 R0 = 0012 PC = 1
1112 R1 = 0012 PC = 2
D100 PC = 0
.........
.........
其余测试案例均可轻易想到,不再赘述。如有其他本代码不可跑过的测试案例欢迎留言!
写在最后
1.题主曾多次使用goto语句(但单个程序中不超过1次),确实因为能力有限或其他因素,只能想到这样的处理办法,如有其它好方法欢迎留言交流。