Создание собственного машинного кода с нуля - PullRequest
1 голос
/ 09 июня 2011

Я недавно начал работать с дизайном логического уровня как любитель-любитель, но теперь столкнулся с программным обеспечением, где я гораздо менее компетентен. Я завершил проектирование собственного 4-битного процессора в Logisim на основе статьи Этьена Сикара «Очень простой микропроцессор». Теперь, когда он выполняет очень ограниченные встроенные в него функции (сложение, логическое И, ИЛИ и XOR) без каких-либо обнаруживаемых ошибок (скрещивание пальцев), я столкнулся с проблемой написания программ для него. В Logisim есть функция импорта скрипта шестнадцатеричных чисел в модуль RAM или ROM, чтобы я мог писать программы для него, используя свой собственный код микроинструкции, но с чего мне начать? Я буквально на самом базовом уровне разработки программного обеспечения и не знаю, куда идти дальше. Любые хорошие предложения по ресурсам для изучения этого низкого уровня программирования или предложения о том, что я должен попробовать отсюда? Большое спасибо заранее, я знаю, что это, вероятно, не самый применимый вопрос, когда-либо задаваемый на этом форуме.

Ответы [ 3 ]

0 голосов
/ 15 июня 2011

Поскольку ваш набор инструкций очень мал и основан на потоке из ответа mguica, я бы сказал, что следующий шаг - продолжить и / или полностью протестировать ваш набор инструкций. у тебя есть флаги? У вас есть инструкции для филиалов? Пока просто вручную сгенерируйте машинный код. Флаги хитры, в частности бит переполнения (V). Вы должны проверить перенос и выполнить на сумматоре msbit, чтобы понять это правильно. Поскольку набор инструкций достаточно мал, вы можете попробовать различные комбинации последовательных инструкций, после которых следуют или, и затем следует xor, и затем add, или после, и / или затем xor, и т. Д. И смешивать в ветвях. вернуться к флажкам, если xor и / или, например, не касаются переноса и переполнения, убедитесь, что вы видите перенос и переполнение как ноль и не затронуты логическими инструкциями, а перенос и переполнение равны единице и не затрагиваются, а также независимо показывают перенос и переполнение является отдельным, один на один выключенным, не затронутым логическим и т. д. убедитесь, что все условные ветви работают только с этим одним условием, ведут к различным условным ветвям с битами флага, которые игнорируются в обоих состояниях, гарантируя, что условная ветвь игнорирует их. Также убедитесь, что если условная ветвь не должна изменять их, она этого не делает. аналогично, если условие не вызывает ответвление, что условные флаги не затрагиваются ...

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

возвращаемся к тестированию отдельных команд, и флаги проходят все угловые случаи 0xFFFF + 0x0000 0xFFFF + 1, подобные вещи располагаются по обе стороны от операндов и справа от них, а результаты находятся на расстоянии одного отсчета от места, где флаг изменяется точка, где флаг меняется и просто другая сторона этого. для логики, например, если они используют нулевой флаг, то имеют различные шаблоны данных, которые проверяют результаты, которые находятся по обе стороны от нуля и равны 0x0000, 0xFFFF 0xFFFE 0x0001 0x0002 и т.д. и т. д.

надеюсь, я понял ваш вопрос и не указал на очевидное или на то, что вы уже сделали до сих пор.

0 голосов
/ 06 июля 2019

Я сделал нечто подобное, что может показаться вам интересным. Я также создал с нуля свой собственный дизайн процессора. Это 8-разрядный многоцикловый ЦПИ RISC на основе гарвардской архитектуры с инструкциями переменной длины.

Я начал в Logisim, затем закодировал все в Verilog, и я синтезировал его в FPGA.

Чтобы ответить на ваш вопрос, я сделал простой и элементарный ассемблер, который переводит программу (инструкции, т.е. мнемонику + данные) на соответствующий машинный язык, который затем может быть загружен в память PROG. Я написал это в сценарии оболочки и использую awk, с чем мне было удобно.

Я в основном делаю два прохода: сначала переводю мнемонику в соответствующий ей код операции и транслирую данные (операнды) в шестнадцатеричный код, здесь я отслеживаю все адреса меток. второй проход заменит все метки с соответствующим адресом. (метки и адреса для прыжков)

Вы можете увидеть весь проект, включая ассемблер, документированный здесь: https://github.com/adumont/hrm-cpu

0 голосов
/ 09 июня 2011

Я не в курсе упомянутой вами бумаги.Но если вы спроектировали свой собственный ЦП, то если вы хотите написать программное обеспечение для него, у вас есть два варианта: а) написать его в машинном коде или б) написать свой собственный ассемблер.

Очевидно, я 'буду идти с б.Это потребует, чтобы вы немного переключили передачу и занялись программированием на высоком уровне.То, что вы намереваетесь написать, это программа на ассемблере, которая работает на ПК и преобразует простой язык ассемблера в ваш машинный код.Сам ассемблер будет программой высокого уровня, и поэтому я бы порекомендовал написать ее на языке программирования высокого уровня, который хорош как для работы со строками, так и для двоичной обработки.Я бы порекомендовал Python.

По сути, вы хотите, чтобы ваш ассемблер мог читать текстовый файл, подобный следующему:

    mov a, 7
foo:
    mov b, 20
    add a, b
    cmp a, b
    jg foo

(я только что создал эту программу; это чепуха.)

И преобразовать каждую строку кода в двоичный шаблон для этой инструкции, выводя двоичный файл (или, возможно, шестнадцатеричный файл, поскольку вы сказали, что ваш микроконтроллер может читать в шестнадцатеричных значениях).Оттуда вы сможете загрузить программу в CPU.

Итак, я предлагаю вам:

  1. Придумайте (на бумаге) язык ассемблера, который являетсяпростое письменное представление для каждого из операционных кодов, которые поддерживает ваша машина (возможно, вы уже сделали это),
  2. Изучите простой Python,
  3. Напишите скрипт Python, который читает по одной строке за раз (sys.stdin.readline()), выясняет, какой это код операции и какие значения он принимает, и выводит соответствующий машинный код в стандартный вывод.
  4. Напишите некоторый код сборки на вашем языке ассемблера, который будет работать на вашем процессоре.

Звучит как забавный проект.

...