Разделение (DIVS) не работает на jack Crenshaw, давайте создадим компилятор

Я следую превосходному руководству по созданию компилятора Джека Креншоу, которое можно найти по адресу 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» в качестве теста, компилятор генерирует следующий код:

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 делает что-то неправильно - маловероятно Однако я просто не вижу, что я сделал неправильно. Пожалуйста помоги.


person Caltor    schedule 16.01.2012    source источник


Ответы (1)


Я думаю, что я, возможно, взломал его. Статья 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');

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

person Caltor    schedule 16.01.2012