In a world where weight loss apps are a dime a dozen, a team of Bulgarian researchers has cooked up something different. Meet Pondera, a smart new mobile app that's like having a super-intelligent fitness buddy in your pocket.
Unlike traditional calorie counters or basic workout trackers, Pondera brings artificial intelligence into the weight loss game, learning your habits, preferences, and goals to create a truly personalized path to fitness. Developed by George Pashev and Silvia Gaftandzhieva at the University of Plovdiv, this app goes beyond the usual "eat less, move more" mantra.
What makes Pondera stand out is its ability to juggle multiple factors at once - think of it as a fitness orchestra conductor, harmonizing everything from your diet and exercise to sleep patterns and stress levels. It's not just about shedding pounds; it's about understanding how different aspects of your lifestyle work together.
The app taps into GPT-3.5's artificial intelligence to keep its recommendations fresh and relevant, while maintaining strict healthcare privacy standards. It's like having a personal trainer, nutritionist, and wellness coach all rolled into one, continuously adapting its approach based on your progress and feedback.
But perhaps most intriguingly, Pondera aims to build a community around its users, recognizing that weight loss journeys are often better shared. It's this combination of high-tech smarts and human connection that might just make it a game-changer in the crowded field of wellness apps.
We are currently raising funds to create a production ready software. Fundraiser link will be available shortly.
Bridging Natural Language and Logic Programming: An English to PROLOG Translator
George Pashev 1*, Silvia Gaftandzhieva 2, Stanka Hadzhikoleva3
1, 2, 3 University of Plovdiv “Paisii Hilendarski” (Computer Informatics Department, Plovdiv, Bulgaria)
*corresponding author: georgepashev@uni-plovdiv.bg
This paper presents a comprehensive approach to translating natural language queries into PROLOG queries, enabling effective interaction with knowledge bases implemented in PROLOG. The system is composed of multiple Python scripts that manage various stages of the translation and querying process: input processing, query translation, PROLOG interaction, and answer translation.
Keywords: natural language processing, PROLOG, query translation, logic programming, knowledge base interaction
На Вашето внимание представям един от моите проекти: TinyWf: система за олекотено изпълнение на уеб работни потоци. Тя е базирана на PHP 5. За момента работните потоци се описват в конфигурационни Структури от данни в PHP. Предвижда се допълнително развитие: графичен интерфейс за визуално създаване на работен поток. Парадигмата, която се поддържа е максимално обща: "потоково програмиране", което позволява излизане отвъд прекалено стандартизирани и детерминирани стандарти за работни потоци като BPMN и следователно: по-голяма гъвкавост.
Публикации, свързани с TinyWf:
https://www.dropbox.com/s/zf52gv9ckeqpcsb/TinyWf.pdf?dl=0
https://www.dropbox.com/s/sbp1pomf5w3x6h2/Presentation_student_taxes_08.pdf?dl=0
Some of my cross translators, interpreters and execution environments developed for my Computer Linguistics courses are:
EMS Runtime environment
My participation in the project is in a crucial part: development of the runtime environment, runtime process evaluation, own interpreter development.
Project's website: http://dextro-research.eu/project/
The project builds upon existing EMSG technology- an established Client-Server workflow management platform
The new and improved EMSG platform focuses on improving and expanding the platform, achieving better automation and platform scalability.
The EMSG software platform is suitable for development of highly complex information systems which must remain responsive and operational in intense workload conditions.
EMSG can help overcome problems caused by lack of resources in centralized information systems, especially with regard to multiple similar business organizations or multiple departments in a single business.
EMSG can lower the cost of initial development as well as the cost of ongoing support and further development and expansion.
GDBMS
Project's doxygen: Graph database management system
Main characteristics:
Fuly transactional
Supports formalism called labeled directed attributed hypergraph
Users management, sessions, transactions are separated by the transport system, so that different transport system can be used in future
Its own procedural language for definition of triggers and user scripts
Type definition subsystem, which supports class object-like hierarchy structures, arrays definitions, simple types aliases definitions
GDBMS is designed and implemented to support Graph Database formalism called Directed, labeled hyper-graph, which increases the power of the set of applicable tasks which can be solved by such a system. More efficient disk usage is also achieved by using the formalism: 2 or more edges can be represented as 1 hyper-edge. Another important feature of the system is that each of the nodes and edges can be of different user types. User types can be user defined structures, arrays or simple type aliases for integers or strings. The system is transactional, user authentication and authorization, sessions and transactions management. The transactional subsystem is quite sophisticated unlike the transactional subsystems of other lookalike graph database systems. It insures that only those edges or nodes, which have been added or altered by the transaction are in the transactional folder and/or locked by the transaction. Information about the transaction history is maintained, and when transaction close command is received, some edge/node operations dependencies are resolved and handled: Insert after update, update after insert, update after update, for instance. Data is stored in xml based hash table, which balances the relative complexity of search operations and insert and alter operations and achieves easier transactional lock of files when needed. If binary trees were used, much effort on balancing the trees would be required, when insert and update operations occur.The hybrid data model which has relational and hierarchical characteristics is also easily achieved by using multiple hash tables.
Search and iteration operations support limiting the number of results when too big graphs are iterated.
Extreme path queries support relative path user specification to a valid value in a valid type path in the type hierarchy for a node.
The metric in terms to the extreme path queries is a valid type path to a numeric value in each edge, which is used by Dijkstra algorithms to determine which of the paths is longest or shortest. The metric can be determined in a user trigger, specified in a user defined script by a formula or directly, depending on the user application.
The web service interface remote methods, which directly support call of each operations is obsolete and the user is encouraged to use the methods, which allow script interpretation and user script triggers registration and interpretation.
As a conclusion we can claim that the system has everything needed to serve as a basis of a numerous set of applications, which are graph based or hypergraph oriented: routing protocols simulations; map tasks; social networks graphs; Set oriented tasks (Hyperedges can be viewed as a sets of nodes), etc.
The user is able to define its own event handlers. The language is procedural. It supports its own flow identifier operator for graphflow queries for nodes and edges, which is used in combination with foreach operator.
Робот, търсещ по шаблон текст в уеб страници. Поддържа се откриване на абсолютни адреси към други страници в кода на текущата страница. При евентуално открити нови адреси, те се добавят в списък на предстоящо посещение, който се състои от 2 основни компонента: Компоненти на списъка за предстоящо посещение Опашка за предстоящо посещение, която се използва за определяне на текущата страница, която да бъде посетена Хеш таблица, реализираща бързо търсене в списъка за предстоящо посещение. Поддържа функционалност – запаметяване на тези адреси във файлове, като при евентуално следващо стартиране на програмата с тези настройки, тя не добавя тези адреси наново в списъка за предстоящо посещение. Особености на шаблона за търсене Шаблона за търсене може да съдържа символа * (звезда), който се интерпретира от алгоритъма за търсене, като какъвто и да е текст. Например шаблонът “ *@*.* “ допуска откриването на запис “ georgipashev@mail.bg ”. Поддържат се и частните случаи – търсене на точно съвпадение (без *) и сканиране на целия текст (само със *) Използвана среда за програмиране: Microsoft Visual C++ 9.0 Express Edition
ТУ – София
Филиал Пловдив
КУРСОВ ПРОЕКТ
Тема:
Създаване на симулатор на проста микропроцесорна архитектура
На Георги Петров Пашев
Гр. 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;
}
}