Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Архив2 / курсовая docx200 / Kursovaya_rabota(23).docx
Скачиваний:
54
Добавлен:
07.08.2013
Размер:
190.22 Кб
Скачать

2.4 Генератор кода.

LIT const – поместить константу в вершину стека.

LOAD n – поместить переменную, размещенную по адресу n в вершину

стека.

STO n – запись значения из вершины стека по адресу n (присваивание).

JMP k – безусловный переход к команде, расположенной по адресу k.

JEQ k – переход к команде, расположенной по адресу k в случае

равенства двух верхних элементов стека.

JLT k – переход к команде, расположенной по адресу k, если число в вершине стека меньше следующего за ним числа стека.

JLE k – переход к команде, расположенной по адресу k, если число в вершине стека меньше или равно следующему за ним числу стека.

JGT k – переход к команде, расположенной по адресу k, если число в вершине стека больше следующего за ним числа стека.

JGE k – переход к команде, расположенной по адресу k, если число в вершине стека больше или равно следующему за ним числу стека.

JNE k – переход к команде, расположенной по адресу k в случае неравенства двух верхних элементов стека.

ADR – содержимое регистра адреса данных помещается в вершину стека.

STAD – содержимое вершины стека помещается в регистр адреса данных.

ADD – сложение двух верхних элементов стека, результат помещается в вершину стека.

MUL – умножение двух верхних элементов стека, результат помещается в вершину стека.

SUB – вычитание элемента в вершине стека из следующего за ним элемента стека, результат помещается в вершину стека.

DIV – деление на элемент в вершине стека следующего за ним

элемента стека, результат помещается в вершину стека.

AND

– логическое

"И"

(логическое

умножение)

двух

верхних

элементов стека, результат помещается в вершину стека.

OR

– логическое

"ИЛИ"

(логическое

сложение)

двух

верхних

элементов стека, результат помещается в вершину стека.

DIV – деление на элемент в вершине стека следующего за ним

XOR – сложение по модулю 2 двух верхних элементов стека, результат помещается в вершину стека. NOT – знаковая инверсия элемента в вершине стека

NOL – поразрядная логическая инверсия элемента в вершине стека. NOP – пустая операция .

Так как наш транслятор является однопроходным, методы генератора кода будут вызываться из методов синтаксического анализатора. По мере выполнения синтаксического разбора будет генерироваться и ассемблерный код. Для удобства будем хранить его в массиве строк.

/// <summary>

/// Генератор кода

/// </summary>

public static class CodeGenerator

{

private const int MAX_NUMBER_STRINGS = 1000;

private static string[] code = new string[MAX_NUMBER_STRINGS];

private static int codePointer = 0;

private static int countLabels = 0;

/// <summary>

/// Добавить инструкцию

/// </summary>

/// <param name="instraction"></param>

public static void AddInstruction(string instraction)

{

code[codePointer++] = instraction;

}

/// <summary>

/// Добавить метку

/// </summary>

public static void AddLabel()

{

countLabels++;

}

/// <summary>

/// Вернуть текущую метку

/// </summary>

/// <returns></returns>

public static string GetCurrentLabel()

{

return "label" + countLabels.ToString();

}

/// <summary>

/// Описать сегмент данных

/// </summary>

public static void DeclairDataSegment()

{

AddInstruction("data segment para public \"data\"");

}

/// <summary>

/// Описать сегмент стэка и кода

/// </summary>

public static void DeclairSegmentOfStackAndCode()

{

AddInstruction("PRINT_BUF DB ' ' DUP(10)");

AddInstruction("BUFEND DB '$'");

AddInstruction("data ends");

AddInstruction("stk segment stack");

AddInstruction("db 256 dup (\"?\")");

AddInstruction("stk ends");

AddInstruction("code segment para public \"code\"");

AddInstruction("main proc");

AddInstruction("assume cs:code,ds:data,ss:stk");

AddInstruction("mov ax,data");

AddInstruction("mov ds,ax");

}

/// <summary>

/// Описать конец главной процедуры

/// </summary>

public static void DeclairEndMainProc()

{

AddInstruction("mov ax,4c00h");

AddInstruction("int 21h");

AddInstruction("main endp");

}

/// <summary>

/// Описать коней сегмента кода

/// </summary>

public static void DeclairCodeEnd()

{

AddInstruction("code ends");

AddInstruction("end main");

}

/// <summary>

/// Описать переменные

/// </summary>

public static void DeclairVariables()

{

LinkedListNode<Identificator> node = NameTable.GetIdentificators.First;

while (node != null)

{

if (SyntaxAnalyzer.Type == tType.Int)

AddInstruction(node.Value.name + " dw 1");

if (SyntaxAnalyzer.Type == tType.LInt)

AddInstruction(node.Value.name + " dl 1");

node = node.Next;

}

}

/// <summary>

/// Опичать процедуру вывода на печать

/// </summary>

public static void DeclairPrint()

{

AddInstruction("PRINT PROC NEAR");

AddInstruction("MOV CX, 10");

AddInstruction("MOV DI, BUFEND - PRINT_BUF");

AddInstruction("PRINT_LOOP:");

AddInstruction("MOV DX, 0");

AddInstruction("DIV CX");

AddInstruction("ADD DL, '0'");

AddInstruction("MOV [PRINT_BUF + DI - 1], DL");

AddInstruction("DEC DI");

AddInstruction("CMP AL, 0");

AddInstruction("JNE PRINT_LOOP");

AddInstruction("LEA DX, PRINT_BUF");

AddInstruction("ADD DX, DI");

AddInstruction("MOV AH, 09H");

AddInstruction("INT 21H");

AddInstruction("RET");

AddInstruction("PRINT ENDP");

}

Для реализации арифметических (и не только) операций в языке ассемблер используется работа с регистровой памятью. Так, чтобы поместить значение (числовую константу или переменную) в регистр, используется инструкция mov. Команды для арифметических операций приведены в таблице ниже.

Операция

Инструкция ассемблера

+

add

-

sub

*

mul

/

div

Таким образом, код для выражения a + b будет выглядеть следующим образом:

mov ax, a

mov bx b

add ax, bx

Результат этой последовательности команд будет сохранен в регистре ax. Но в ситуации со сложными выражениями необходимо где-то сохранять промежуточные результаты. Для этих целей мы будем использовать ассемблерный стек: инструкция push - помещение значения регистра на верхушку стека, pop – извлечение из стека в регистр. После каждой атомарной операции мы будем сохранять результат в стек, чтобы не потерять его.

Соседние файлы в папке курсовая docx200