Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Полный отчёт по работе.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.8 Mб
Скачать

6.Схема вызовов функций

7.Резултаты работы программы

Входной файл «1.asm»:

CSEG segment

jmp start

dw 5

dw 40

start:

push sp

pop ax

jmp x

dw 18

x:

push ebx

pop eax

push word ptr [ebx]

push word ptr [ebx]

push dword ptr [ecx+eax]

pop dword ptr [esp+ebp]

pop bx

ret

CSEG ends

DSEG segment

push word ptr [eax+eax]

pop word ptr [edi+ebx]

DSEG ends

BSEG segment

push ebx

pop dword ptr [esp+ebp]

BSEG ends

end start

В ыходной файл «1.lst»:

Выходной объектный файл

Разница в файлах обусловлена тем, что TASM вставляет комментарии, а так же разным способом установки MODEND.

Р езультат работы отладчика

Разница в коде обусловлена разными способами кодирования перехода jmp. TASM после перехода вставляет команду nop. В конечном итоге обе команды безусловного перехода ссылаются на один и тот же адрес в коде.

8.Вывод

Результатом работы программы являются 2 файла – листинг и объектный файлы.

После сравнения данных файлов с файлами, полученными при помощи ассемблера tasm32, а так же проверки полученного exe файла в td.exe можно сделать вывод, что программа работает верно.

9.Текст программы

9.1.AssemblerObject.cs

abstract class AssemblerObject

{

public string mnem;

public int length;

public int numberString;

public int location;

public string orig;

protected AssemblerObject()

{

mnem = orig = String.Empty;

length = -1;

numberString = -1;

location = -1;

}

/// <summary>

/// Определяет для всех потомка класса AssemblerObject метод получения листинга

/// </summary>

public virtual string GetListing()

{

return string.Format("{0:X4} {1}", 0, this.orig);

}

}

9.2.Operation.cs

/// <summary>

/// Объект Операции

/// </summary>

class Operator : AssemblerObject

{

public int kop;

public int modRm;

public int sib;

/// <summary>

/// Флаги

/// </summary>

public bool memory = false, use32Reg = false, useDw = false, useSib = false, error = false; //Флаги

public Operator(bool error = false)

{

kop = -1;

modRm = -1;

this.error = error;

if (error) length = 0;

}

/// <summary>

/// Получение строки листинга

/// </summary>

public override string GetListing()

{

if (!error)

{

int countSpace = 20;

string tmp = String.Empty;

tmp += string.Format("{0:X4} ", location);

countSpace -= 4;

if (!memory)

{

if (use32Reg)

{

tmp += "66| ";

countSpace -= 4;

}

tmp += string.Format("{0:X2} ", this.kop);

countSpace -= 3;

}

else

{

if (useDw)

{

tmp += "66| ";

countSpace -= 4;

}

if (use32Reg)

{

tmp += "67| ";

countSpace -= 4;

}

tmp += string.Format("{0:X2} ", this.kop);

countSpace -= 3;

tmp += string.Format("{0:X2} ", this.modRm);

countSpace -= 3;

if (useSib)

{

tmp += string.Format("{0:X2} ", this.sib);

countSpace -= 3;

}

}

while (countSpace > 0)

{

tmp += " ";

countSpace--;

}

tmp += this.orig;

return tmp;

}

else

{

return "ошибка в ассемблерном коде " + this.orig;

}

}

/// <summary>

/// Задаёт для всех потомков класса Operatоr метод получения машинной операции

/// </summary>

/// <returns></returns>

public virtual int[] GetMOP()

{

List<int> tmp = new List<int>();

if (!error)

{

if (!memory)

{

if (use32Reg)

{

tmp.Add(0x66);

}

tmp.Add(this.kop);

}

else

{

if (useDw)

{

tmp.Add(0x66);

}

if (use32Reg)

{

tmp.Add(0x67);

}

tmp.Add(this.kop);

tmp.Add(this.modRm);

if (useSib)

{

tmp.Add(this.sib);

}

}

}

return tmp.ToArray();

}

9.1.PopOperation.cs

/// <summary>

/// Операция Pop

/// </summary>

class PopOperation:Operator

{

public PopOperation()

:base()

{

this.mnem = "pop";

}

public PopOperation(bool memory, bool use32reg, bool useDW, bool useSIB, bool error = false, int sib = 0, int inctement = 0)

{

this.mnem = "pop";

if (memory)

{

this.kop = 0x8f;

this.length = 2;

}

else

{

this.kop = 0x58;

this.length = 1;

}

if (useSIB)

{

this.modRm = 0x04;

this.sib = sib;

this.length = 3;

}

else if(memory)

{

this.modRm = 0x00 + inctement;

}

if(memory && useDW)

this.length++;

if(use32reg)

this.length++;

if (error) length = 0;

this.memory = memory;

this.use32Reg = use32reg;

this.useDw = useDW;

this.useSib = useSIB;

this.error = error;

}

}

9.2.PushOperation.cs

class PushOperation : Operator

{

public PushOperation()

:base()

{

this.mnem = "push";

}

public PushOperation(bool memory, bool use32reg, bool useDW, bool useSIB, bool error = false, int sib = 0, int increment = 0)

{

this.mnem = "push";

if (memory)

{

this.kop = 0xff;

this.length = 2;

}

else

{

this.kop = 0x50;

this.length = 1;

}

if (useSIB)

{

this.modRm = 0x34;

this.sib = sib;

this.length = 3;

}

else if(memory)

{

this.modRm = 0x30 + increment;

}

if(memory && useDW)

this.length++;

if(use32reg)

this.length++;

this.memory = memory;

this.use32Reg = use32reg;

this.useDw = useDW;

this.useSib = useSIB;

this.error = error;

}

9.1.DwOperatioin.cs

/// <summary>

/// Операция dw

/// </summary>

internal class DwOperation : Operator

{

public string data;

public DwOperation(string Data = "")

: base()

{

mnem = "dw";

this.length = 2;

this.data = Data;

}

public override int[] GetMOP()

{

List<int> tmp = new List<int>(2)

{

(int.Parse(data)%0xFF),

(int.Parse(data)/0xFF)

};

return tmp.ToArray();

}

public override string GetListing()

{

string tmp = String.Format("{0:X4} ", this.location);

tmp += String.Format("{0:X4}", int.Parse(data));

tmp += " " + this.orig;

return tmp;

}

9.1.JmpOperation.cs

/// <summary>

/// Операция Jmp

/// </summary>

class JmpOperation : Operator

{

public Marker marker;

public string markerName;

public int step;

public JmpOperation(string markerName = "")

:base()

{

this.mnem = "jmp";

this.kop = 0xeb;

this.step = 0;

this.length = 2;

this.markerName = markerName;

}

public override int[] GetMOP()

{

List<int> tmp = new List<int>();

tmp.Add(this.kop);

tmp.Add(step);

return tmp.ToArray();

}

public override string GetListing()

{

return string.Format("{0:X4} {1:X2} {2:X2} {3}", this.location, this.kop, this.step, this.orig);

}

}

9.2.RetOperation.cs

class RetOperation : Operator

{

public RetOperation()

: base()

{

this.mnem = "ret";

this.kop = 0xC3;

this.length = 1;

this.orig = "ret";

}

public override int[] GetMOP()

{

return new int[] {this.kop};

}

public override string GetListing()

{

return String.Format("{0:X4} {1:X2} {2}", this.location, this.kop, this.orig);

}

9.1. Marker.cs

/// <summary>

/// Метка

/// </summary>

class Marker : Operator

{

public Marker(string name, int location = -1)

{

this.mnem = name;

this.location = location;

}

public override string GetListing()

{

return string.Format("{0:X4} {1}", this.location, this.orig);

}

}

9.2.Segment.cs

/// <summary>

/// Сегмент

/// </summary>

internal class Segment : AssemblerObject

{

public List<Operator> output = new List<Operator>();

public List<Marker> markers = new List<Marker>();

public int[] bytes = new int[1000];

public int endLocation;

public Segment()

{

this.mnem = "";

}

/// <summary>

/// Конструктор

/// </summary>

/// <param name="name">Имя сегмента</param>

/// <param name="count">Индекс сегмента</param>

public Segment(string name, int count)

{

location = 0;

this.mnem = name;

bytes[0] = 0xA0;

bytes[3] = count;

bytes[4] = 0;

bytes[5] = 0;

}

/// <summary>

/// Ставит в соответствие оператору JMP метку

/// </summary>

private void initJMP()

{

foreach (var element in output)

{

if (element is JmpOperation)

{

(element as JmpOperation).marker = findMarker((element as JmpOperation).markerName);

}

}

}

/// <summary>

/// Поиск метки по имени

/// </summary>

/// <param name="name">Имя</param>

/// <returns>Метка</returns>

private Marker findMarker(string name)

{

for (int i = 0; i < markers.Count; i++)

if (markers[i].mnem == name)

{

return markers[i];

}

return null;

}

/// <summary>

/// Инициализирует байты сенгмента

/// </summary>

public void getSegmentBytes()

{

int i = 6;

initJMP();

foreach (var element in output)

{

if(element is Marker)

{

continue;

}

if (element is JmpOperation)

{

(element as JmpOperation).step = (element as JmpOperation).marker.location - element.location - 2;

}

var tmp = element.GetMOP();

foreach (var x in tmp)

{

bytes[i] = x;

i++;

}

}

}

}

9.3.RegClass.cs

static class RegClass

{

public static readonly string[] RegTable =

{

"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"

};

public static readonly string[] ModRM32Table =

{

"eax", "ecx", "edx", "ebx", "0", "0", "esi", "edi"

};

public static readonly string[] ModRM3232Table =

{

"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"

};

}

9.4.Generator.cs

/// <summary>

/// Основной класс программы

/// </summary>

internal class Generator

{

private const string fileName = "1.asm";

private static StreamReader inputStream;

private static FileStream outputStream;

private static int checkSum = 0;

private static List<Segment> segments = new List<Segment>();

#region Method

/// <summary>

/// Запись в файл

/// </summary>

/// <param name="comand">байт для записи</param>

private static void WriteInFile(int comand)

{

if (comand == -1)

{

comand = 256 - (checkSum & 0xff);

checkSum = 0;

}

else

{

checkSum += comand;

}

outputStream.WriteByte((byte) comand);

}

/// <summary>

/// Запись структуры THEADR

/// </summary>

private static void WriteTheadr()

{

outputStream = new FileStream("1.obj", FileMode.Create);

int len = fileName.Length;

WriteInFile(0x80);

WriteInFile((len + 2)%0xff);

WriteInFile((len + 2)/0xff);

WriteInFile(len);

for (int i = 0; i < fileName.Length; i++)

{

WriteInFile(fileName[i]);

}

WriteInFile(-1);

}

/// <summary>

/// Запись структуры MODEND

/// </summary>

private static void WriteModEnd()

{

WriteInFile(0x8a);

WriteInFile(7);

WriteInFile(0);

WriteInFile(0xC1);

WriteInFile(0);

WriteInFile(1);

WriteInFile(1);

WriteInFile(4);

WriteInFile(0);

WriteInFile(-1);

}

/// <summary>

/// Запись структуры LNAMES и SEGDEF

/// </summary>

private static void WriteLNames()

{

for (int i = 0; i < segments.Count;i++)

{

int len = 0;

WriteInFile(0x96);

len += segments[i].mnem.Length + 2;

WriteInFile((len) % 0xff);

WriteInFile((len) / 0xff);

WriteInFile(segments[i].mnem.Length);

for (len = 0; len < (segments[i]).mnem.Length; len++)

WriteInFile((segments[i]).mnem[len]);

WriteInFile(-1);

if (i > 0)

{

WriteInFile(0x98);

WriteInFile(7); //vivod dlini zapisi 7

WriteInFile(0); //vivod dlini zapisi

WriteInFile(0x60); //vivod atributa segmenta

WriteInFile(segments[i].length%0xff); //vivod dlini segmenta

WriteInFile(segments[i].length/0xff); //vivod dlini segmenta

WriteInFile(i + 1); //segment name index МОЖЕТ БЫТЬ +1

WriteInFile(01); //class name index

WriteInFile(01); //class name index (ignoriruetsya sborschikom)

WriteInFile(-1);

}

}

}

/// <summary>

/// Запись структуры LEDATA

/// </summary>

private static void WriteLeData()

{

for (int i = 1; i < segments.Count; i++)

{

segments[i].getSegmentBytes();

// zapolnenie baitov dliny zapisi

segments[i].bytes[1] = (segments[i].length + 4)%0xff;

segments[i].bytes[2] = (segments[i].length + 4)/0xff;

for (int len = 0; len < segments[i].length + 6; len++)

WriteInFile(segments[i].bytes[len]);

WriteInFile(-1);

}

}

/// <summary>

/// Запись листинга в файл

/// </summary>

private static void PrintListing()

{

foreach (var segment in segments)

{

if (segment.mnem == "")

{

continue;

}

Console.WriteLine(segment.GetListing());

foreach (var kop in segment.output)

{

Console.WriteLine(kop.GetListing());

}

Console.WriteLine(String.Format("{0:X4} ends {1}", segment.endLocation, segment.mnem));

}

Console.WriteLine("end");

}

/// <summary>

/// Вывод листинга на экран

/// </summary>

private static void WriteListing()

{

var writer = new StreamWriter("1.lst", false);

foreach (var segment in segments)

{

if (segment.mnem == "")

{

continue;

}

writer.WriteLine(segment.GetListing());

foreach (var kop in segment.output)

{

writer.WriteLine(kop.GetListing());

}

writer.WriteLine("{0:X4} ends {1}", segment.endLocation, segment.mnem);

}

writer.WriteLine("end");

writer.Close();

}

/// <summary>

/// Запуск формирования файлов

/// </summary>

private static void RunGenerate()

{

string origString;

string[] array;

string reg1, reg2;

int numberString = 0, location = 0, lastLocation, sib = 0;

bool memory = false, use32reg = false, useDW = false, useSIB = false, error = false;

try

{

inputStream = new StreamReader(fileName);

WriteTheadr();

segments.Add(new Segment());

while (!inputStream.EndOfStream)

#region основной цикл

{

memory = false;

use32reg = false;

useDW = false;

useSIB = false;

error = false;

lastLocation = location;

string inString = origString = (inputStream.ReadLine()).Trim();

switch ((array = origString.Split(' ')).Length)

{

case (1):

{

if (array[0].Contains("ret"))

{

segments.Last().output.Add(new RetOperation());

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

}

else if (array[0].Contains(":"))

{

array[0] = array[0].Replace(":", "");

segments.Last().markers.Add(new Marker(array[0], segments.Last().location){orig = origString.Replace(":", "")});

segments.Last().output.Add(segments.Last().markers.Last());

segments.Last().markers.Last().numberString = numberString;

segments.Last().markers.Last().location = segments.Last().location;

}

break;

}

case (2):

{

if (array[0].Contains("end"))

{

continue;

}

else if (array[1].Contains("segment"))

{

segments.Add(new Segment(array[0], segments.Count));

segments.Last().orig = origString;

segments.Last().numberString = numberString;

}

else if (array[1].Contains("ends"))

{

segments.Last().length = segments.Last().location;

segments.Last().endLocation = segments.Last().location;

}

else

{

switch (array[0])

{

case ("dw"):

{

segments.Last().output.Add(new DwOperation(array[1]));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

break;

}

case ("jmp"):

{

segments.Last().output.Add(new JmpOperation(array[1]));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

break;

}

default:

{

memory = false;

if (array[1].Contains('e'))

{

use32reg = true;

}

if (array[0] == "pop")

{

segments.Last().output.Add(new PopOperation(memory, use32reg, useDW, useSIB));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

}

else

{

segments.Last().output.Add(new PushOperation(memory, use32reg, useDW, useSIB));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

}

for (int i = 0; i < RegClass.RegTable.Length; i++)

{

if (array[1].Contains(RegClass.RegTable[i]))

{

segments.Last().output.Last().kop += i;

break;

}

}

numberString++;

break;

}

}

}

break;

}

case (4):

{

memory = true;

array[3] = array[3].Replace("[", "");

array[3] = array[3].Replace("]", "");

int increment = 0;

if (array[3].Contains('e'))

{

use32reg = true;

if (array[3].Contains('+'))

{

useSIB = true;

sib = 0;

reg2 = array[3].Split('+')[0];

reg1 = array[3].Split('+')[1];

int i = 0;

while (!reg1.Contains(RegClass.ModRM3232Table[i]))

{

sib += 8;

i++;

}

i = 0;

while (!reg2.Contains(RegClass.ModRM3232Table[i]))

{

sib++;

i++;

}

}

else

{

for (increment = 0; increment < 8; increment++)

if (array[3].Contains(RegClass.ModRM32Table[increment]))

break;

}

if (array[1].Contains("dword"))

{

useDW = true;

}

if (array[0] == "pop")

{

segments.Last().output.Add(new PopOperation(memory, use32reg, useDW, useSIB, error, sib,

increment));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

}

else

{

segments.Last().output.Add(new PushOperation(memory, use32reg, useDW, useSIB, error,

sib, increment));

segments.Last().output.Last().location = segments.Last().location;

segments.Last().output.Last().numberString = numberString;

segments.Last().location += segments.Last().output.Last().length;

segments.Last().output.Last().orig = origString;

}

}

else

{

segments.Last().output.Add(new Operator(true));

segments.Last().output.Last().orig = origString;

}

numberString++;

break;

}

}

}

#endregion

WriteLNames();

WriteLeData();

WriteModEnd();

PrintListing();

WriteListing();

}

catch (Exception e)

{

Console.WriteLine("File not find");

Console.WriteLine(e);

Console.ReadKey();

return;

}

outputStream.Close();

inputStream.Close();

}

#endregion

/// <summary>

/// Основная программа

/// </summary>

/// <param name="args"></param>

static void Main(string[] args)

{

RunGenerate();

Console.ReadKey();

}

}

37