Java - Создание справки по компилятору - PullRequest
0 голосов
/ 02 апреля 2010

Итак, для моего класса программирования у нас был проект по созданию виртуальной машины, включающей модуль памяти, процессор, ввод, вывод, регистр команд, счетчик программ, MAR, MDR и так далее. Теперь нам нужно создать компилятор, использующий код Java, который возьмет файл .exe, написанный в каком-то текстовом редакторе, преобразует его в код байта java и запустит код. Код, который мы будем писать в .exe-файле, - это машинный код следующего содержания:

IN X
IN Y
ADD X
STO Y
OUT Y
STOP
DC X 0
DC Y 0

Я только начинающий, и у меня есть только 2 дня, чтобы написать это, и я очень растерян и не знаю, с чего начать .... Любая помощь будет высоко оценена. Спасибо

Хорошо, никто не понимает, по-настоящему, я уточню ...... Я на первом курсе по программированию, и мой учитель велел нам создать виртуальную машину, которую я сделал, и я опубликую код для процессора и компьютера Классы, но мой учитель очень неорганизован, и у нас не хватило времени для последнего проекта, который является компилятором ..... Приведенный выше код является просто примером кода, который будет превращен в байт-код ... вот код для процессора и компьютера в моем пакете виртуальной машины ...

class Cpu{
    private MemEl acc;
    private InstReg ir;
    private ProgCount pc;
    private Input in;
    private OutPut out;
    private MemEl mdr;
    private MemEl mar;
    public Cpu()
    {
        pc = new ProgCount();
        ir = new InstReg();
        acc = new MemEl();
    }
    public Boolean stop()
    {
        return ir.getOpcode() == 0;
    }
    public int getMAR()
    {
        return ir.getOpcode();
    }
    public int getMDR()
    {
        return mdr.read();
    }
    public void setMDR(int n)
    {
        mdr.write(n);
    }
    public boolean OutFlag()
    {
        return ir.getOpcode() == 8;
    }
    public boolean InFlag()
    {
        return ir.getOpcode() == 7;
    }
    public boolean StoreFlag()
    {
        return ir.getOpcode() == 2;
    }
 public void fetch()
    {
        mar.write(pc.getValue());
        pc.plus();
    }
    public void reset()
    {
        mar.write(0);
        pc.write(0);
        pc.write(1);
    }
    public void fetch2()
    {
        ir.write(mdr.read());
    }
    public void decode()
    {
        mar.write(ir.getOperand());
        mdr.write(acc.read());
    }
 public void execute()
    {

        switch(ir.getOpcode()){
        case 0:
            System.out.println("Complete");
            break;
        case 1:
            acc.write(mdr.read());
            break;
        case 2:
            acc.write(ir.getOperand());
            break;
        case 3:
            acc.write(acc.read() + mdr.read());
            break;
        case 4:
            acc.write(acc.read() - mdr.read());
            break;
 case 5:
            acc.write(acc.read() * mdr.read());
            break;
        case 6:
            acc.write(acc.read() / mdr.read());
            break;
        case 7:
            mar.write(ir.getOperand());
            break;
        case 8:
            System.out.println(getMDR());
            break;
        case 9:
            pc.write(getMDR());
            break;
        case 10:
            if(0 == acc.read())
                pc.write(getMDR());
            else
                fetch();
            break;
        case 11:
            if(0 < acc.read())
                pc.write(getMDR());
            else
                fetch();
            break;
        }

    }

Вот мой компьютерный класс

import java.io.*;
class Computer{
    private Cpu cpu;
    private Input in;
    private OutPut out;
    private Memory mem;
    public Computer() throws IOException
    {
        Memory mem = new Memory(100);
        Input in = new Input();
        OutPut out = new OutPut();
        Cpu cpu = new Cpu();
        System.out.println(in.getInt());
    }
    public void run() throws IOException
    {
        cpu.reset();
        cpu.setMDR(mem.read(cpu.getMAR()));
        cpu.fetch2();
        while (!cpu.stop())
            {
                cpu.decode();
                if (cpu.OutFlag())
                    OutPut.display(mem.read(cpu.getMAR()));
                if (cpu.InFlag())
                    mem.write(cpu.getMDR(),in.getInt());
                if (cpu.StoreFlag())
                    {
                        mem.write(cpu.getMAR(),in.getInt());
                        cpu.getMDR();
                    }
                else
                    {
                        cpu.setMDR(mem.read(cpu.getMAR()));
                        cpu.execute();
                        cpu.fetch();
                        cpu.setMDR(mem.read(cpu.getMAR()));
                        cpu.fetch2();
                    }
            }
    }
public void load()
    {
        mem.write(0,799);
        mem.write(1,199);
        mem.write(2,1009);
        mem.write(3,398);
        mem.write(4,298);
        mem.write(5,199);
        mem.write(6,497);
        mem.write(7,299);
        mem.write(8,902);
        mem.write(9,898);
        mem.write(97,0);
        mem.write(98,0);
        mem.write(99,1);
    }

}

Метод Load - это временный метод, просто чтобы посмотреть, работает ли машина ... то, что он будет загружать, это байт-код, сформированный компилятором.

Ответы [ 5 ]

3 голосов
/ 02 апреля 2010

Это кажется довольно амбициозным, основываясь на вашем вопросе и времени, которое вам нужно сделать, но я постараюсь поставить вас на правильный путь. Очевидно, что поскольку это домашнее задание, никто не даст вам ответ;)

Код в вашем примере будет более точно называться «ассемблерный код». Рассмотрим этот вариант; Вы должны:

  • Читать в каждой строке
  • Посмотрите на первое слово (инструкция или оператор) и сравните его с байт-кодом Java. Смотрите здесь .
  • Выясните, сколько аргументов (операндов) следует прочитать для оператора.
  • Убедитесь, что остальная часть строки содержит соответствующее количество операндов.
  • Запишите байт-код в правильном порядке в соответствии со спецификацией Java.
  • Загрузить байт-код в виртуальную машину и запустить его

Код ассемблера в вашем примере выглядит так, как будто у него есть некоторые явные правила, которые инструктор, вероятно, дал вам. Например, «ДОБАВИТЬ X» означает добавить содержимое местоположения X к - что? «IN» означает «вход» или «приращение»? «СТО Y» означает хранить что-то в месте Y - что? Кажется, что может быть есть неявный регистр, который содержит результаты. Это должно быть частью спецификации инструктора тоже. Удачи! Взломай!

1 голос
/ 03 апреля 2010

Я не думаю, что это байт-код Java, который вы пытаетесь создать, верно? Это на самом деле байт-код для вашего конкретного процессора. Это значительно упрощает ваш проект. Это также выглядит так, как будто это может иметь стековую архитектуру, поэтому у вас есть только один операнд.

Поскольку ваши входные данные - это текст и только язык ассемблера, определенный для вашего пользовательского ЦП, вы должны иметь возможность легко читать и анализировать текст и записывать двоичный файл. Вот некоторый псевдокод, который должен помочь.

initialize Map of instruction names (keys) to instruction op codes (ByteCodeInfo);
initialize empty bytecode-operations list;
open input text file;
while (more to read)
{
    read next line;
    split line by spaces;
    lookup ByteCodeInfo in the Map;
    if (num actual operands != num expected operands - from ByteCodeInfo)
        throw exception(parse failed on line ####);
    add new operation to list of operations (each element in the list is an address)
    if there is a variable reference (e.g. "X") add this to a symbol Map;
    if this is a variable declaration (DC...) update the symbol object with the address;
}
close input text file;

open output binary file (the byte-code file);
for each element in operation list
{
    write address, byte-code, operands (if any);
}
close byte-code file;

Вы должны будете отслеживать адреса хранения и инструкции

Это не невыполнимая задача, поэтому наберитесь мужества, и это можно сделать за день или около того, если у вас есть опыт создания тех других классов, которые вы показываете.

EDIT : добавлен класс ByteCodeInfo, который представляет информацию о ваших байтовых кодах, таких как идентификатор, количество операндов, ожидаемые типы операндов и т. Д. Этот класс также можно использовать для передачи байт-код на основе проанализированной строки информации. Это обеспечит лучшую абстракцию, чем просто сохранение кода операции int в Map, как я и предлагал в оригинале.

1 голос
/ 02 апреля 2010

Вы новичок, и у вас есть два дня, чтобы написать компилятор?

Wow. Надеюсь, ваша фамилия "Кнут".

Вы, безусловно, должны были прочитать это . Одна из его ссылок - список инструкций байт-кода Java .

Вам необходимо знать, как с этим связаны ваши инструкции в файле "машинного кода". «DC» означает «двойное сравнение»? Если да, то dcmpg (hex 98) или dcmpl (hex 98) И так далее.

А серьезно? Удачи.

0 голосов
/ 02 апреля 2010

Если я вас правильно понял, вам следует:

  • создать лексический анализатор. Для данного текста он производит последовательность лексем.
  • создать синтаксический анализатор. Это создаст синтаксическое дерево.
  • создать интерпретатор, который проходит по дереву и генерирует код.
  • создать виртуальную машину для запуска этого сгенерированного кода.
0 голосов
/ 02 апреля 2010

Если вам нужно преобразовать что-либо в байт-коды Java, вам нужно сделать следующее (как минимум!)

  1. Изучите стандарт Java байт-кодов! (разве это не придуманные для класса макеты Java-байт-коды?)
  2. Синтаксический анализ ввода ".exe" (неправильное имя расширения imho) с использованием StringTokenizer или аналогичного класса
  3. Либо используйте лексический анализатор, чтобы определить, что писать для кода.
  4. Отформатируйте вывод, используя то, что вы узнали из прочтения о стандарте байт-кодов Java

И "это все" - но, похоже, ваш проект может занять немного больше времени, если вы не обладаете большим опытом в этой теме ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...