
Написать и отладить программу, которая демонстрирует выполнение операций со стеком Листинг
#include "stdafx.h"
#include <iostream>
#include <string>
#include <windows.h>
#include <conio.h>
using namespace std;
int RSP,RBP,buf,bSP,bBP,pVal;
int *mstack;
class CInfoWindow{
private:
int count;
_COORD Crd;
HANDLE hConsole;
void ASCII(char *Ch)
{//метод перевода символов в дос кодировку
if (Ch == NULL) return;
int Len = strlen(Ch);
char *newCh = new char[Len+1];
for (int i = 0;i<Len;i++)
{
if ((int(Ch[i]) >= -64)&&(int(Ch[i]) <= -1))
{
if (Ch[i]+192 >=176) newCh[i] = Ch[i]+240;
else newCh[i] = Ch[i]+192;
}else newCh[i] = Ch[i];
}
newCh[Len] = '\0';
cout<<newCh;
}
public:
CInfoWindow()
{
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);//получения контекста консоли
HideCursor();
SetTextColor(26);
count = 0;
}
~CInfoWindow()
{
}
void HideCursor()
{//метод выключает отображение курсора консоли
_CONSOLE_CURSOR_INFO MyCurSor;
MyCurSor.dwSize = 20;
MyCurSor.bVisible = FALSE;//курсор становится "не видимым":)
SetConsoleCursorInfo(hConsole,&MyCurSor);
}
void ShowCursor()
{//метод включает отображение курсора консоли
_CONSOLE_CURSOR_INFO MyCurSor;//объявление структуры
MyCurSor.dwSize = 20;//установка параметров курсора - размер (вертикальный)
MyCurSor.bVisible = TRUE;//состояние "Видимость" тру - видимый...
SetConsoleCursorInfo(hConsole,&MyCurSor);//вызов метода установки параметров курсора
}
void SetTextColor(int Color)
{
SetConsoleTextAttribute(hConsole,(WORD)Color);
}
void SetXY(int X,int Y)
{//метод установки курсора в позицию с координатами Х и У
Crd.X = X;
Crd.Y = Y;
SetConsoleCursorPosition(hConsole,Crd);
}
void clrscr(void)
{
system("cls");
}
void DrawRegInfo()
{
SetXY(67,5);
cout<<hex<<RSP;
SetXY(67,6);
cout<<hex<<RBP;
}
void Push(int Value)
{
if (count<17)
{
__asm{
mov bSP,ESP
mov bBP,EBP
mov ESP,RSP
mov EBP,RBP
push pVal
mov RSP,ESP
mov RBP,EBP
mov ESP,bSP
mov EBP,bBP
}
count++;
}else
throw new int(0);
}
int Pop()
{
pVal = 0;
if (count>0)
{
count--;
__asm{
mov bSP,ESP
mov bBP,EBP
mov ESP,RSP
mov EBP,RBP
pop pVal
mov RSP,ESP
mov RBP,EBP
mov ESP,bSP
mov EBP,bBP
}
}
return pVal;
}
void DrawStack()
{
int j,i;
for (i=count-1, j = 0;i>=0;i--,j++)
{
SetXY(5,7+j);
cout<<hex<<&mstack[17-i];
SetXY(29,7+j);
cout<<dec<<mstack[17-i];
}
}
void Draw()
{
clrscr();
SetXY(0,0);
cout<<"|------------------------------------------------------------------------------|";
ASCII("| Программа демонстрации работы стека (push/pop) |");
cout<<"|------------------------------------------------------------------------------|";
ASCII("|1-Push|2-Pop|3-Выход| Выбор: число: | Регистр | Значение |");
cout<<"|------------------------------------------------------------------------------|";
ASCII("| Адрес | Значение | ESP | |");
cout<<"|--------------------------------------------| EBP | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"| | | | |";
cout<<"|------------------------------------------------------------------------------|";
SetXY(0,0);
DrawRegInfo();
DrawStack();
ShowCursor();
SetXY(30,3);
}
};
void main()
{//суть идеи:
// 1 - выделяем 20*4 байт под стек
// 2 - сохраняем во временные переменные стековые регистры ESP и EBP
// 3 - заносим в регистры ESP и EBP адреса конца выделенного участка памяти
// 4 - используя команды ассемблера push и pop выполняем операции со стеком
// 5 - на экран выводим адреса и значения внесенных в стек элементов и отображаем содержимое регистров
mstack = new int[20];//размер памяти для нашего "виртуального" стека
for (int i=0;i<20;i++) mstack[i]=0;
mstack[19]=2;
__asm{
mov EAX,4 //получаем индекс последнего элемента
mov EBX,19 //4 байта для типа данных int
mul EBX //умножаем на 20 элем. - получаем смещение от начала в байтах
mov EBX,mstack //получаем адрес начала сегм памяти стека
add EBX,EAX //адрес последнего элемента mstack
mov EAX,EBX
sub EBX,4
mov dword ptr [EAX],EBX
mov RSP,EBX
sub EAX,4
mov dword ptr [EAX],EBX
mov RBP,EBX
}
CInfoWindow Wnd;
int i;
Wnd.Draw();
cin>>i;
while (i!=3)
{
switch(i){
case 1:{
Wnd.SetXY(40,3);
cin>>pVal;
Wnd.Push(i);
};break;
case 2:{Wnd.Pop();};break;
default:break;
}
Wnd.Draw();
cin>>i;
}
delete mstack;
return;
}