симулатор на проста микропроцесорна архитектура

Print

ТУ – София

Филиал Пловдив

КУРСОВ ПРОЕКТ

Тема:

Създаване на симулатор на проста микропроцесорна архитектура

На Георги Петров Пашев

Гр. 41, Специалност: КСТ

1. Задание

Да се създаде симулатор на система инструкции на микропроцесорна архитектура. За опростяване, приема се, че няма конвейерна обработка на инструкциите. Трябва да се спазва брой цикли, необходими за изпълнението на всяка една инструкция. След изпълнението на всяка инструкция, симулаторът трябва да може да показва състоянието на регистрите, под формата на двоично или шестнадесетично представяне на съдържанието им, както и колко цикли са изминали от началото на програмата до тук. Симулаторът трябва да приема за вход текстови файлове с програми, написани на асемблерен език, дефиниран по-долу.

Микропроцесорът, трябва да има следният програмен модел:

Регистрите са както следва:

PC – програмен брояч, IR-регистър за инструкции, AR- адресен регистър, AC- акумулатор, DR – даннов регистър

Приема се, че размерът на всяка една инструкция е 16 бита. От тях 4 бита се използват за код на операцията, а останалите 12 – за операнд, който ще е адрес. Това определя размера на адресното пространство да бъде 4 к.  Приема се, че програматорът зарежда програмата за изпълнение в паметта от адрес 0х0. Размерът на думата е 16 бита.

Валидните инструкции, които трябва да поддържа микропроцесорът са следните:

Оставям на студента да избере подходящ мнемоничен код за всяка една от инструкциите, както и да определи колко цикли са необходими за изпълнението и.  Да се напише примерен асемблерен код.

2. Реализация

a. Определяне на мнемоничния код на инструкциите и формата на операндите

КОП

Мнемоничен код

Пример за използване на инструкцията

Необходими цикли

0000

HALT

HALT

1

0001

LD

LD 0x345

2

0010

ST

ST 0x346

2

0011

CAD

CAD

1

0100

CDA

CDA

1

0101

ADA

ADA

1

0110

DMA

(DR Minus AC)

Result stays in AC

DMA

1

0111

DAA

(DR Bitwise And AC)

Result stays in AC

DAA

1

1000

NA

(Not AC)

NA

1

1001

JMP

JMP 0x30f

1

1010

JAZ

(Jump if AC==0)

JAZ 0x305

1

b. Реализация на програмата симулатор

За реализацията на програмата симулатор се използваt Microsoft .NET класове в C++, като продукта от линкване е смесен тип (Native и Managed код), което осигурява по-бързото изпълнение на определени части от програмния код, които са Native, отколкото ако се използваше изцяло .NET Managed код, което е предимство, достъпно само за езика C++.

Функционалността на симулатора може да се раздели на 2 основни части: компилатор и дебъгер.

Компилаторът превежда асемблерният език на машинен, като резултатът се пази в масива prog[], като най младшият байт на всеки четерибайтов елемент в масива съдържа КОП (старша тетрада) и най-старшата тетрада на операнда, ако има такава. Вторият байт съдържа младшите тетради на операнда, ако има такъв. Другите 2 байта не се използват. Понеже адресното пространство се състои от 4096 думи, адресът не трябва да е по-голям от 4095 или 0xfff.

Компилаторът взема нов ред от файл, избран от потребителя и премахва символът за нов ред от него. След това открива последователността за коментар ‘//’ и ако открие такава, замества първия символ ‘/’ с 0, което откъсва всичко след нулевия символ от стринга. След това замества всички малки букви с големи, за да се осигури независимост от малки или големи букви и премахва всички интервали от дясната страна на инструкцията.

След прилагането на горните трансформации върху стринга, той се подава на алгоритъм за намиране на текст по шаблон, като последователно се търсят шаблонни съвпадения за всички инструкции. При намиране на такова съвпадение, това съвпадение се подава на специфичната callback функция за конкретната инструкция, която проверява за валидност на операнд, ако има такъв и евентуално връща съобщение за грешка, а освен това попълва текущия елемент в масива prog[] с валидния код на инструкцията.

Ако не се намери дори и 1 шаблонно съвпадение, това означава, че може да имаме частен случай: празен ред, имащ само интервали. След прилагане на трансформациите, той се преобразува в стринг с нулева дължина. Това означава, че ако дължината на стринга е положителна имаме грешка в кода и това условие се използва за откриването и.

При наличие на поне 1 грешка, компилацията се прекратява, извежда се съобщение за грешка и масива prog[], както и управляващи глобални променливи се преинициализират.

Дебъгера показва състоянието на регистрите след изпълнението на инструкциите, както и колко цикли четене/запис от и в паметта са настъпили сумарно от началото на изпълнението на програмата.

При изпълнението на примерната програма:

LD 0x6

CAD

LD 0x7

ADA

HALT

Което поредставлява програма, която събира 2 думи, намиращи се на адреси 6 и 7 и запазва резултата в AC, изхода след изпълнението на последната инструкция е следния:

А изхода в полето съобщения е следния:

Започнато компилиране....

Успешно компилиране. 5инструкции.

Започване на изпълнението.

Достингата инструкция LD, зареждане на операнд в AC.

Достингата инструкция CAD, копираме AC в DR.

Достингата инструкция LD, зареждане на операнд в AC.

Достингата инструкция ADA, AC=AC+DR.

Достингата инструкция HALT, спиране на изпълнението.

В системата инструкции няма такива, които работят с константи, затова примера показва 0 като резултат, защото на адреси 6 и 7, първоначалните инициализации са с 0.

Следват дефинициите на по-важните методи и членове на класове, както и други променливи и функции в програмата:

#pragma once

namespace processor_sim {

using namespace System;

using namespace System::ComponentModel;

using namespace System::Collections;

using namespace System::Windows::Forms;

using namespace System::Data;

using namespace System::Drawing;

using namespace System::Text;

using namespace System::IO;

using namespace System::Net;

using namespace System::Net::Sockets;

using namespace System::Collections;

using namespace System::Threading;

static FILE *fp_asm;

static FILE *fp_bin;

//регистри

static int PC_reg, IR_reg, AR_reg, AC_reg, DR_reg;

//брояч на циклите

static int cycles_reg;

//копие на двоичната програма

int prog[4096];

//реда до който компилатора е стигнал

static int line_nr;

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

//

//TODO: Add the constructor code here

//

cur_asm_fname=gcnew String("");

cur_bin_fname=gcnew String("");

fp_asm=0;

fp_bin=0;

PC_reg=0;

IR_reg=0;

AR_reg=0;

AC_reg=0;

DR_reg=0;

int i;

for(i=0; i<4096; i++)

prog[i]=0;

line_nr=0;

cycles_reg=0;

timer1->Interval=1000;

timer1->Stop();

}

protected:

/// <summary>

/// Clean up any resources being used.

/// </summary>

~Form1()

{

if (components)

{

delete components;

}

if(cur_asm_fname)

delete cur_asm_fname;

if(cur_bin_fname)

delete cur_bin_fname;

if(fp_asm)

fclose(fp_asm);

if(fp_bin)

fclose(fp_bin);

}

private: System::Windows::Forms::GroupBox^  groupBox1;

public: System::Windows::Forms::Label^  IR;

private:

protected:

private: System::Windows::Forms::Label^  label1;

private: System::Windows::Forms::Label^  label4;

public: System::Windows::Forms::Label^  AR;

private:

private: System::Windows::Forms::Label^  label3;

public: System::Windows::Forms::Label^  PC;

private:

private: System::Windows::Forms::Label^  label2;

public: System::Windows::Forms::Label^  DR;

private:

private: System::Windows::Forms::Label^  label5;

public: System::Windows::Forms::Label^  AC;

private:

private: System::Windows::Forms::MenuStrip^  menuStrip1;

private: System::Windows::Forms::ToolStripMenuItem^  fileToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  отвориToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  aSMFileToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  bINFileToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  запазиКатоToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  bINFileToolStripMenuItem1;

private: System::Windows::Forms::ToolStripMenuItem^  изходToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  дебъгToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  стартToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  паузаToolStripMenuItem;

private: System::Windows::Forms::GroupBox^  groupBox2;

private: System::Windows::Forms::Label^  cycles;

private: System::Windows::Forms::Label^  label6;

private: System::Windows::Forms::OpenFileDialog^  ofd;

private: System::Windows::Forms::SaveFileDialog^  sfd;

private: System::Windows::Forms::GroupBox^  groupBox3;

private: System::Windows::Forms::TextBox^  messages;

String^ cur_asm_fname;

String^ cur_bin_fname;

private: System::Windows::Forms::ToolStripMenuItem^  компиToolStripMenuItem;

private: System::Windows::Forms::ToolStripMenuItem^  compileToolStripMenuItem;

public: System::Windows::Forms::Timer^  timer1;

private:

public:

private: System::ComponentModel::IContainer^  components;

//public: delegate void func_del(char *);

private:

/// <summary>

/// Required designer variable.

/// </summary>

#pragma region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

void InitializeComponent(void)

{

//няколко страници инициализации, които не са интересни

}

#pragma endregion

private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {

}

private: System::Void aSMFileToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

ofd->InitialDirectory = "c:\\";

//Stream^ myStream;

FILE *fp;

ofd->Filter = "ASM files (*.asm)|*.txt|All files (*.*)|*.*";

ofd->FilterIndex = 2;

ofd->RestoreDirectory = true;

if ( ofd->ShowDialog() == System::Windows::Forms::DialogResult::OK )

{

try{

char *fname=new char[612];

ConvertStrToChar(fname, ofd->FileName);

fp_asm=fopen(fname, "r");

delete fname;

}catch(System::Exception ^e){

MessageBox::Show(L"Не мога да отворя файл.", L"Грешка", MessageBoxButtons::OK, MessageBoxIcon::Error);

}

}

}

private: System::Void изходToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

Application::Exit();

}

private: System::Void compileToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

//тука се пише кода за компилирането

if(!(fp_asm)){

ShowError("Няма отворен ASM file.");

return;

}

this->messages->Text=messages->Text+gcnew String("Започнато компилиране.... \r\n");

//буфер, в който се държи 1 прочетен ред от асм файла

char * fbuf=new char[512];

int i;

fbuf[0]=0;

while(1){

//fflush(fp_asm);

//if(fscanf(fp_asm, "%s\r\n", fbuf)<=0)

//    break;

if(!fgets(fbuf, 512, fp_asm))

break;

if(fbuf[strlen(fbuf)-1]==32)

fbuf[strlen(fbuf)-1]=0;

//откриване и изолиране на коментар в кода

for(i=0; i<strlen(fbuf)-1; i++)

if(fbuf[i]=='/'&&fbuf[i+1]=='/'){

fbuf[i]=0;

}

to_upper(fbuf);

remove_intervals(fbuf);

if(line_nr>4095)

{

ShowError("Кодът е по-голям отколкото адресното пространство може да побере.");

for(i=0; i<4096; i++)

prog[i]=0;

line_nr=0;

return;

}

func_del^ del=gcnew func_del(this, &processor_sim::Form1::halt_func);

if(findocccurencesnew("HALT", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::cad_func);

if(findocccurencesnew("CAD", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::cda_func);

if(findocccurencesnew("CDA", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::ada_func);

if(findocccurencesnew("ADA", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::dma_func);

if(findocccurencesnew("DMA", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::daa_func);

if(findocccurencesnew("DAA", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::na_func);

if(findocccurencesnew("NA", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::ld_func);

if(findocccurencesnew("LD *", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::st_func);

if(findocccurencesnew("ST *", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::jmp_func);

if(findocccurencesnew("JMP *", fbuf, del )>0)

continue;

del=gcnew func_del(this, &processor_sim::Form1::jaz_func);

if(findocccurencesnew("JAZ *", fbuf, del )>0)

continue;

if(strlen(fbuf)>1){

messages->Text+="Грешка: На ред "+Int32(line_nr)+" командата не отговаря на нито един от шаблоните. \r\n"+Int32(strlen(fbuf))+gcnew String(fbuf)+"\r\n";

for(i=0; i<4096; i++)

prog[i]=0;

line_nr=0;

return;

}

}

if(line_nr>=0)

messages->Text+="Успешно компилиране. "+Int32(line_nr)+ "инструкции.\r\n";

delete fbuf;

}

void halt_func(char *arg){

int i=0, j;

for(i=4; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след HALT \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x0<<4;

line_nr++;

}

void cad_func(char *arg){

int i=0, j;

for(i=3; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след CAD \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x3<<4;

line_nr++;

}

void cda_func(char *arg){

int i=0, j;

for(i=3; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след CDA \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x4<<4;

line_nr++;

}

void ada_func(char *arg){

int i=0, j;

for(i=3; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след ADA \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x5<<4;

line_nr++;

}

void dma_func(char *arg){

int i=0, j;

for(i=3; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след DMA \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x6<<4;

line_nr++;

}

void daa_func(char *arg){

int i=0, j;

for(i=3; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след DAA \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x7<<4;

line_nr++;

}

void na_func(char *arg){

int i=0, j;

for(i=2; i<strlen(arg); i++)

if(arg[i]!=' ')

{

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след NA \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x8<<4;

line_nr++;

}

void ld_func(char *arg){

int i=0, j;

int k;

try{

sscanf(arg, "LD 0X%X", &k);

}catch(Exception^ e){

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след команда LD \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x1<<4;

if(k>4095||k<0)

{

this->messages->Text+="Грешка на ред "+(gcnew Int32(line_nr))+" след команда LD: невалиден размер на адрес \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

else if(k>255)

{

(*a)^=(char)((k&0xf00)>>8);

}else

*(a+1)=(char)(k&0xff);

line_nr++;

}

void st_func(char *arg){

int i=0, j;

int k;

try{

sscanf(arg, "ST 0X%X", &k);

}catch(Exception^ e){

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след команда ST \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x2<<4;

if(k>4095||k<0)

{

this->messages->Text+="Грешка на ред "+(gcnew Int32(line_nr))+" след команда ST: невалиден размер на адрес \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

else if(k>255)

{

(*a)^=(char)((k&0xf00)>>8);

}else

*(a+1)=(char)(k&0xff);

line_nr++;

}

void jmp_func(char *arg){

int i=0, j;

int k;

try{

sscanf(arg, "JMP 0X%X", &k);

}catch(Exception^ e){

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след команда JMP \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0x9<<4;

if(k>4095||k<0)

{

this->messages->Text+="Грешка на ред "+(gcnew Int32(line_nr))+" след команда JMP: невалиден размер на адрес \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

else if(k>255)

{

(*a)^=(char)((k&0xf00)>>8);

}else

*(a+1)=(char)(k&0xff);

line_nr++;

}

void jaz_func(char *arg){

int i=0, j;

int k;

try{

sscanf(arg, "JAZ 0X%X", &k);

}catch(Exception^ e){

this->messages->Text+="Грешка: Невалиден символ намерен на ред "+(gcnew Int32(line_nr))+" след команда JAZ \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

char *a=(char *)&prog[line_nr];

//кода на операцията

*a=0xA<<4;

if(k>4095||k<0)

{

this->messages->Text+="Грешка на ред "+(gcnew Int32(line_nr))+" след команда JAZ: невалиден размер на адрес \r\n";

for(j=0; j<=line_nr; j++)

prog[j]=0;

line_nr=0;

return;

}

else if(k>255)

{

(*a)^=(char)((k&0xf00)>>8);

}else

*(a+1)=(char)(k&0xff);

line_nr++;

}

private: System::Void bINFileToolStripMenuItem1_Click(System::Object^  sender, System::EventArgs^  e) {

//запазване на файл в BIN формат

if(line_nr<=0)

{

ShowError("Грешка: Преди запазване на bin файл, asm файл трябва да се компилира без грешки");

return;

}

SaveFileDialog^ saveFileDialog1 = gcnew SaveFileDialog;

saveFileDialog1->Filter = "bin files (*.bin)|*.bin|All files (*.*)|*.*";

saveFileDialog1->FilterIndex = 2;

saveFileDialog1->RestoreDirectory = true;

if ( saveFileDialog1->ShowDialog() == ::DialogResult::OK )

{

char *fname=new char[512];

ConvertStrToChar(fname, saveFileDialog1->FileName);

fp_bin=fopen(fname, "wb");

if(!fp_bin)

{

ShowError("Не можа да се отвори файл за запис.");

return;

}

int ln;

try{

for(ln=0; ln<line_nr; ln++){

fwrite( (char *)(prog+ln), 1, 1, fp_bin);

fwrite( ((char *)(prog+ln))+1, 1, 1, fp_bin);

}

}catch(Exception ^e){

ShowError("Грешка при запис на файл."+e->ToString());

}

delete fname;

}

}

private: System::Void bINFileToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

ofd->InitialDirectory = "c:\\";

//Stream^ myStream;

FILE *fp;

ofd->Filter = "ASM files (*.asm)|*.txt|All files (*.*)|*.*";

ofd->FilterIndex = 2;

ofd->RestoreDirectory = true;

if ( ofd->ShowDialog() == System::Windows::Forms::DialogResult::OK )

{

try{

char *fname=new char[612];

ConvertStrToChar(fname, ofd->FileName);

fp_bin=fopen(fname, "r");

for(line_nr=0; line_nr<4096; line_nr++)

{

fread( (prog+line_nr), 1, 1, fp_bin);

fread( ((char *)(prog+line_nr))+1, 1, 1, fp_bin);

}

delete fname;

}catch(System::Exception ^e){

MessageBox::Show(L"Не мога да отворя файл.", L"Грешка", MessageBoxButtons::OK, MessageBoxIcon::Error);

}

}

}

private: System::Void стартToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

messages->Text+="Започване на изпълнението.\r\n";

timer1->Start();

}

private: System::Void паузаToolStripMenuItem_Click(System::Object^  sender, System::EventArgs^  e) {

messages->Text+="Изпълнението спряно от потребител.\r\n";

timer1->Stop();

}

private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {

//общи операции за всички регистри

char *reg_pnt;

char *str_buf=new char[64];

char opcode=((*((char *)(prog+PC_reg)))&(char)0xf0)>>4;

char MST=((*((char *)(prog+PC_reg)))&(char)0x0f);

char second_byte= *(((char *)(prog+PC_reg))+1);

reg_pnt=(char *)&IR_reg;

*reg_pnt=second_byte;

*(reg_pnt+1)=*((char *)(prog+PC_reg));

sprintf(str_buf, "%X", IR_reg);

IR->Text=gcnew String(str_buf);

AR_reg=IR_reg&0xfff;

sprintf(str_buf, "%X", AR_reg);

IR->Text=gcnew String(str_buf);

//PC, AC, DR се променят по различен начин

//от различните инструкции

switch(opcode){

case 0:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//никак

messages->Text+="Достингата инструкция HALT, спиране на изпълнението.\r\n";

timer1->Stop();

break;

case 1:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=2;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//зарежда дума от адреса в AC

AC_reg=((prog[AR_reg]&0xff)<<8)|((prog[AR_reg]&0xff00)>>8);

//приема се че старшия байт от думата се намира в най-младшия байт в prog[], както е и при инструкциите

sprintf(str_buf, "%X", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция LD, зареждане на операнд в AC.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 2:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=2;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//съхраняваме съдържанието на AC в паметта

prog[AR_reg]= ((AC_reg&0xff)<<8)|((AC_reg&0xff00)>>8);

messages->Text+="Достингата инструкция ST, съхраняваме съдържанието на AC в паметта.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 3:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//копираме AC в DR

DR_reg=AC_reg;

sprintf(str_buf, "%d", DR_reg);

DR->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция CAD, копираме AC в DR.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 4:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//копираме DR в AC

AC_reg=DR_reg;

sprintf(str_buf, "%d", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция CDA, копираме DR в AC.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 5:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//add DR to AC

AC_reg+=DR_reg;

sprintf(str_buf, "%d", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция ADA, AC=AC+DR.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 6:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//subtract DR from AC

AC_reg-=DR_reg;

sprintf(str_buf, "%d", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция DMA, AC=AC-DR.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 7:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//AC= DR & AC

AC_reg&=DR_reg;

sprintf(str_buf, "%d", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция DAA, AC=AC&DR.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 8:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//AC= bitwise NOT AC

AC_reg=~AC_reg;

sprintf(str_buf, "%d", AC_reg);

AC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция NA, AC= NOT AC.\r\n";

PC_reg++;

sprintf(str_buf, "%X", PC_reg);

PC->Text=gcnew String(str_buf);

break;

case 9:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//AC= bitwise NOT AC

PC_reg=AR_reg;

sprintf(str_buf, "%d", PC_reg);

PC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция JMP, PC=AR.\r\n";

break;

case 10:

//колко цикли четене-запис от и в паметта са необходими

cycles_reg+=1;

sprintf(str_buf, "%d", cycles_reg);

cycles->Text=gcnew String(str_buf);

//как работи инструкцията с PC, AC, DR

//AC= bitwise NOT AC

if(AC_reg==0)

PC_reg=AR_reg;

else

PC_reg++;

sprintf(str_buf, "%d", PC_reg);

PC->Text=gcnew String(str_buf);

messages->Text+="Достингата инструкция JAZ, Jump if AC==0.\r\n";

break;

default:

messages->Text+="Грешка: КОП на тази инструкция е невалиден. Спираме дебъга.\r\n";

timer1->Stop();

}

//messages->Text+="Спиране на изпълнението.\r\n";

delete str_buf;

}

};

}

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

#pragma once

// TODO: reference additional headers your program requires here

#include<stdlib.h>

#include <stdio.h>

#include <string.h>

#include <malloc.h>

#include <fstream>

using namespace System;

using namespace System::ComponentModel;

using namespace System::Collections;

using namespace System::Windows::Forms;

using namespace System::Data;

using namespace System::Drawing;

using namespace System::Text;

using namespace System::IO;

using namespace System::Net;

using namespace System::Net::Sockets;

using namespace System::Collections;

using namespace System::Threading;

System::String^ GetHttpContent(String^ URL);

int ConvertStrToChar(char *cstring, System::String^ dotnetstring);

void ShowError( System::String ^msg);

void to_upper(char *arg);

void remove_intervals(char *arg);

delegate void func_del(char *);

//делегатът се използва като адрес към функция, която е член на .NET клас и осигурява входни точки от други нишки, които не е задължително да са Managed

int findocccurencesnew(char *tmplate, char *str, func_del ^dowhatwith);

// stdafx.cpp : source file that includes just the standard includes

// processor_sim.pch will be the pre-compiled header

// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

#include<stdlib.h>

#include <stdio.h>

#include <string.h>

#include <malloc.h>

//static int  PC, IR, AR, AC, DR;

using namespace System;

using namespace System::Text;

using namespace System::IO;

using namespace System::Net;

using namespace System::Net::Sockets;

using namespace System::Collections;

using namespace System::Threading;

String^ GetHttpContent(String^ URL){

try{

WebClient ^ wcDownload = gcnew WebClient();

System::IO::Stream ^streamResponse=wcDownload->OpenRead(URL);

int bytesSize=0;

int i=0;

String^ content= gcnew String("");

cli::array<unsigned char, 1>^buffer=gcnew array<unsigned char, 1>(20000);

while((bytesSize=streamResponse->Read(buffer, 0, buffer->Length))>0){

content=System::String::Concat(content, Encoding::GetEncoding(1251)->GetString(buffer));

}

delete buffer;

streamResponse->Close();

return content;

}catch(System::Exception ^e){

return "Exception Error";

}

}

//функция, търсеща съответствие на шаблон в текст

//void (*dowhatwith)(char *)

int findocccurencesnew(char *tmplate, char *str, func_del ^dowhatwith){

if(*str==0)

return 0;

if(*tmplate==0)

return 0;

int retvalue=0;

char *buf=new char[3000];

char **wstek=new char *[3000];

char **lstek=new char *[3000];

char **stek=new char *[3000];

int occ=0;

int i=0, j;

char *k=tmplate;

int len=0;

int top=i+1;

int current=0;

for(j=0; j<3000; j++){

buf[j]=0;

stek[j]=0;

wstek[j]=0;

lstek[j]=0;

}

k=tmplate;

while(1){

if(*k=='*'){

if(k>tmplate){

buf[len]=0;

stek[current++]=new char[len+2];

strcpy(stek[current-1], buf);

len=0;

}

stek[current++]=new char[2];

stek[current-1][0]='*';

stek[current-1][1]=0;

k++;

if(!*k){

//4asten slu4aj kogato imame * nakraya

goto endstage1_find;

///////////////////

}

}

if((!*k)){

if(k>tmplate){

buf[len]=0;

stek[current++]=new char[len+2];

strcpy(stek[current-1], buf);

len=0;

}

break;

}

buf[len++]=*k;

k++;

}

endstage1_find:

k=str;

//current--;

int currrent1=0;

int ws_pnt=0, ls_pnt=0;

char *tt;

int size;

findoccc:

//proverka dali ima smisyl ot tyrsene

if(!k)

goto findoccc1;

//////////////////

currrent1=0;

ws_pnt=0; ls_pnt=0;

char *t;

findoccc_loop:

while(currrent1+1<=current&&(*k)){

if(!(stek[currrent1][0])){

//currrent1++;

break;

}

if(stek[currrent1][0]=='*'){

if(stek[currrent1][0]=='*'&&(currrent1+1==current)){

wstek[ws_pnt++]=k;

lstek[ls_pnt++]=k+strlen(k);

//k=0;

//k++;

currrent1++;

goto findoccc0;

}

wstek[ws_pnt++]=k;

if(stek[currrent1+1]&&(!(k=strstr(k, stek[currrent1+1]))))

goto findoccc1;

lstek[ls_pnt++]=k-1;

currrent1++;

goto findoccc_loop;

}

if(t=strstr(k, stek[currrent1])){

k=t+strlen(stek[currrent1]);

wstek[ws_pnt++]=t;

lstek[ls_pnt++]=k;

currrent1++;

}

if(!t){

retvalue+=0;

goto findoccc1;

}

}

findoccc0:

if(!k)

goto findoccc1;

//printf("\ncurrent=%d, currrent1=%d\n", current, currrent1);

if(*k){

if(currrent1>=current){

retvalue++;

//vyzmojno e da ima o6te syvpadeniya sled namerenite

//zapi6i namerenoto v bufera i go podaj za zapis

size=lstek[ls_pnt-1]-wstek[0];

memcpy(buf, wstek[0], size);

dowhatwith(buf);

//occ++;

//idi da tyrsi6 o6te syvpadeniya

if(stek[current-1][0]!='*')

goto findoccc;

}

}else{

if(currrent1>=current){

retvalue++;

//zapi6i namerenoto v bufera i go podaj za zapis

size=lstek[ls_pnt-1]-wstek[0]+1;

//buf[size++]=0;

memcpy(buf, wstek[0], size);

dowhatwith(buf);

//occ++;

}

}

findoccc1:

//iz4isti heap-a

delete buf;

for(i=0; i<3000; i++){

if(stek[i])

delete stek[i];

}

delete stek;

delete wstek;

delete lstek;

//delete str1;

return retvalue;

}

int ConvertStrToChar(char *cstring, System::String^ dotnetstring){

array<Byte>^bytes=Encoding::GetEncoding(1251)->GetBytes(dotnetstring);

//cstring =(char *)bytes;

int i;

for(i=0; i<bytes->Length; i++){

cstring[i]=bytes[i];

}

cstring[i]=0;

return 1;

}

void ShowError( System::String ^msg){

MessageBox::Show(msg, L"Грешка", MessageBoxButtons::OK, MessageBoxIcon::Error);

}

//общи функции за работа с char *

void to_upper(char *arg){

int i=0;

int k=strlen(arg);

for(i=0; i<k; i++){

if(arg[i]>96&&arg[i]<123)

arg[i]-=32;

}

}

//функция, която маха интервалите отдясно

void remove_intervals(char *arg){

int i=0;

int k=strlen(arg);

for(i=k-1; i>-1; i--){

if(arg[i]==' ')

arg[i]=0;

else

break;

}

}