Divide (DIVS) не работает на Джек Креншоу давайте построим компилятор - PullRequest
4 голосов
/ 16 января 2012

Я следую прекрасному учебнику Джека Креншоу «Давайте построим компилятор», найденному по адресу http://compilers.iecc.com/crenshaw.. Я тестирую сгенерированную сборку 68k с помощью редактора / ассемблера / симулятора Easy68k http://www.easy68k.com/ 68000.Я попал на часть 2 http://compilers.iecc.com/crenshaw/tutor2.txt, но процедура деления у меня не работает должным образом.

...
{ Recognize and Translate a Divide }
procedure Divide;
begin
  Match('/');
  Factor;
  EmitLn('MOVE (SP)+,D1');
  EmitLn('DIVS D1,D0');
end;
...

Если я введу "8/2" в качестве теста, то компилятор сгенерирует следующееcode:

MOVE #8,D0
MOVE D0,-(SP)
MOVE #2,D0
MOVE (SP)+,D1
DIVS D1,D0

Мне кажется, что на самом деле он вычисляет 2/8 (т. е. неправильно), так как значение, оставленное в D0 после этого, равно 00020000. Я могу это исправить, переписав последнюю строкукак DIVS D0, D1, но это оставляет результат в D1, а не D0, как в других подпрограммах, и мне кажется маловероятным, что такая основополагающая работа будет неправильной.Я искал в Интернете, но я не вижу, чтобы кто-нибудь еще сталкивался с этой проблемой.Означает ли это, что: 1) я сделал это неправильно - скорее всего 2) Джек сделал это неправильно - вряд ли 3) эмулятор Easy68k делает что-то не так - вряд ли Однако я просто не вижу, что я сделал неправильно.Пожалуйста, помогите.

1 Ответ

7 голосов
/ 17 января 2012

Я думаю, что, возможно, взломал это. Статья 3 урока http://compilers.iecc.com/crenshaw/tutor3.txt содержит несколько иную версию процедуры Разделить, хотя, похоже, она не объясняется, так что, возможно, это опечатка. Пересмотренная версия в третьей статье -

{ Recognize and Translate a Divide }
procedure Divide;
begin
  Match('/');
  Factor;
  EmitLn('MOVE (SP)+,D1');
  EmitLn('EXS.L D0');
  EmitLn('DIVS D1,D0');
end;

Обратите внимание на добавление строки

EmitLn('EXS.L D0');

, который, кажется, предназначен для обмена содержимым регистров D0 и D1. Теперь, хотя Easy68k, похоже, не нравится «EXS.L D0», после проверки документации Easy68 я изменил это на

EmitLn('EXG D0,D1');

и теперь процедура Divide работает. Я не уверен, относится ли это к Easy68k или почему в статье написано EXS.L, но, по крайней мере, сейчас это работает. Ура!

...