📄 os.cs
字号:
}
/// <summary>
/// Outputs a view of memory from the Process's point of view
/// </summary>
/// <param name="p">The Process to Dump</param>
public void DumpProcessMemory(Process p)
{
int address = 0; byte b;
for (uint i = 0; i < p.PCB.processMemorySize; i++)
{
b = this.memoryMgr[p.PCB.pid,i];
if (address == 0 || address%16==0)
Console.Write(System.Environment.NewLine + "{0,-4:000} ", address);
address++;
if (b == 0)
Console.Write("{0,3}","-");
else
Console.Write("{0,3}",(int)b);
if (address%4==0 && address%16!=0) Console.Write(" :");
}
Console.WriteLine();
}
/// <summary>
/// Called on a context switch. Copy the CPU's <see cref="CPU.registers"/> to the <see cref="currentProcess"/>'s <see cref="CPU.registers"/>
/// </summary>
private void SaveCPUState()
{
CPU.registers.CopyTo(currentProcess.PCB.registers,0);
currentProcess.PCB.zf = CPU.zf;
currentProcess.PCB.sf = CPU.sf;
currentProcess.PCB.ip = CPU.ip;
}
/// <summary>
/// Called on a context switch. Copy the <see cref="currentProcess"/>'s <see cref="Process.ProcessControlBlock.registers"/> to the CPU's <see cref="CPU.registers"/>
/// </summary>
private void LoadCPUState()
{
currentProcess.PCB.registers.CopyTo(CPU.registers,0);
CPU.zf = currentProcess.PCB.zf;
CPU.sf = currentProcess.PCB.sf;
CPU.ip = currentProcess.PCB.ip;
}
/// <summary>
/// Take as a <see cref="Program"/> and creates a Process object, adding it to the <see cref="runningProcesses"/>
/// </summary>
/// <param name="prog">Program to load</param>
/// <param name="memorySize">Size of memory in bytes to assign to this Process</param>
/// <returns>The newly created Process</returns>
public Process createProcess(Program prog, uint memorySize)
{
// Get an array represting the code block
byte[] processCode = prog.GetMemoryImage();
// Create a process with a unique id and fixed memory size
Process p = new Process(++processIdPool, memorySize);
// Map memory to the Process (if available, otherwise freak out)
this.memoryMgr.MapMemoryToProcess(p.PCB.processMemorySize,p.PCB.pid);
// Set the initial IP to 0 (that's where exectution will begin)
p.PCB.ip = 0;
//
// SETUP CODE SECTION
//
// Copy the code in one byte at a time
uint index = 0;
foreach (byte b in processCode)
memoryMgr[p.PCB.pid, index++] = b;
//
// SETUP STACK SECTION
//
// Set stack pointer at the end of memory
//
p.PCB.sp = memorySize-1;
p.PCB.stackSize = uint.Parse(ConfigurationSettings.AppSettings["StackSize"]);
//
// SETUP CODE SECTION
//
// Set the length of the Code section
//
uint roundedCodeLength = CPU.UtilRoundToBoundary((uint)processCode.Length, CPU.pageSize);
//uint roundedCodeLength = (uint)(CPU.pageSize * ((processCode.Length / CPU.pageSize) + ((processCode.Length % CPU.pageSize > 0) ? 1: 0)));
p.PCB.codeSize = roundedCodeLength;
//
// SETUP DATA SECTION
//
// Point Global Data just after the Code for now...
//
p.PCB.registers[9] = (uint)roundedCodeLength;
p.PCB.dataSize = uint.Parse(ConfigurationSettings.AppSettings["DataSize"]);
//
// SETUP HEAP SECTION
//
p.PCB.heapAddrStart = p.PCB.codeSize + p.PCB.dataSize;
p.PCB.heapAddrEnd = p.PCB.processMemorySize - p.PCB.stackSize;
this.memoryMgr.CreateHeapTableForProcess(p);
// Add ourselves to the runningProcesses table
runningProcesses.Add(p);
return p;
}
/// <summary>
/// Releases any locks held by this process.
/// This function is called when the process exits.
/// </summary>
/// <param name="pid">Process ID</param>
public void ReleaseLocksOfProccess(uint pid)
{
for (int i = 0; i < this.locks.Length; i++)
if (this.locks[i] == pid)
this.locks[i] = 0;
}
/// <summary>
/// Utility function to fetch a 4 byte unsigned int from Process Memory based on the current <see cref="CPU.ip"/>
/// </summary>
/// <returns>a new uint</returns>
public unsafe uint FetchUIntAndMove()
{
uint retVal = memoryMgr.getUIntFrom(currentProcess.PCB.pid,CPU.ip);
CPU.ip += sizeof(uint);
return retVal;
}
/// <summary>
/// Increments register
/// <pre>1 r1</pre>
/// </summary>
public void Incr()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Incr == instruction);
//move to the param
CPU.ip++;
uint register = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2}",currentProcess.PCB.pid, instruction, register);
//increment the register pointed to by this memory
CPU.registers[register]++;
}
/// <summary>
/// Adds constant 1 to register 1
/// <pre>
/// 2 r1, $1
/// </pre>
/// </summary>
public void Addi()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Addi == instruction);
//move to the param containing the register
CPU.ip++;
uint register = FetchUIntAndMove();
uint param1 = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2} {3}",currentProcess.PCB.pid, instruction, register, param1);
//increment the register pointed to by this memory by the const next to it
CPU.registers[register]+= param1;
}
/// <summary>
/// Adds r2 to r1 and stores the value in r1
/// <pre>
/// 3 r1, r2
/// </pre>
/// </summary>
public void Addr()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Addr == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register = FetchUIntAndMove();
uint param1 = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2} {3}",currentProcess.PCB.pid, instruction, register, param1);
//add 1st register and 2nd register and put the result in 1st register
CPU.registers[register] = CPU.registers[register] + CPU.registers[param1];
}
/// <summary>
/// Compare contents of r1 with 1. If r1 < 9 set sign flag. If r1 > 9 clear sign flag.
/// If r1 == 9 set zero flag.
/// <pre>
/// 14 r1, $9
/// </pre>
/// </summary>
public void Cmpi()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Cmpi == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register = FetchUIntAndMove();
uint param1 = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2} {3}",currentProcess.PCB.pid, instruction, register, param1);
//compare register and const
CPU.zf = false;
if (CPU.registers[register] < param1)
CPU.sf = true;
if (CPU.registers[register] > param1)
CPU.sf = false;
if (CPU.registers[register] == param1)
CPU.zf = true;
}
/// <summary>
/// Compare contents of r1 with r2. If r1 < r2 set sign flag. If r1 > r2 clear sign flag.
/// If r1 == r2 set zero flag.
/// <pre>
/// 15 r1, r2
/// </pre>
/// </summary>
public void Cmpr()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Cmpr == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register1 = FetchUIntAndMove();
uint register2 = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2} r{3}",currentProcess.PCB.pid, instruction, register1, register2);
//compare register and const
CPU.zf = false;
if (CPU.registers[register1] < CPU.registers[register2])
CPU.sf = true;
if (CPU.registers[register1] > CPU.registers[register2])
CPU.sf = false;
if (CPU.registers[register1] == CPU.registers[register2])
CPU.zf = true;
}
/// <summary>
/// Call the procedure at offset r1 bytes from the current instrucion.
/// The address of the next instruction to excetute after a return is pushed on the stack
/// <pre>
/// 19 r1
/// </pre>
/// </summary>
public void Call()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Call == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2}",currentProcess.PCB.pid, instruction, register);
StackPush(currentProcess.PCB.pid, CPU.ip);
CPU.ip+= CPU.registers[register];
}
/// <summary>
/// Call the procedure at offset of the bytes in memory pointed by r1 from the current instrucion.
/// The address of the next instruction to excetute after a return is pushed on the stack
/// <pre>
/// 20 r1
/// </pre>
/// </summary>
public void Callm()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Callm == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register = FetchUIntAndMove();
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1} r{2}",currentProcess.PCB.pid, instruction, register);
StackPush(currentProcess.PCB.pid, CPU.ip);
CPU.ip+= this.memoryMgr[currentProcess.PCB.pid,CPU.registers[register]];
}
/// <summary>
/// Pop the return address from the stack and transfer control to this instruction
/// <pre>
/// 21
/// </pre>
/// </summary>
public void Ret()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Ret == instruction);
CPU.ip++;
if (bDumpInstructions) Console.WriteLine(" Pid:{0} {1}",currentProcess.PCB.pid, instruction);
CPU.ip = StackPop(currentProcess.PCB.pid);
}
/// <summary>
/// Control transfers to the instruction whose address is r1 bytes relative to the current instruction.
/// r1 may be negative.
/// <pre>
/// 13 r1
/// </pre>
/// </summary>
public void Jmp()
{
//get the instruction and make sure we should be here
InstructionType instruction = (InstructionType)memoryMgr[currentProcess.PCB.pid,CPU.ip];
Debug.Assert(InstructionType.Jmp == instruction);
//move to the param containing the 1st register
CPU.ip++;
uint register = FetchUIntAndMove();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -