Divide (DIVS) not working on jack crenshaw's l

2019-05-08 02:47发布

I am following the excellent Let's Build a Compiler tutorial by Jack Crenshaw found at http://compilers.iecc.com/crenshaw. I am testing the generated 68k assembly with the Easy68k http://www.easy68k.com/ 68000 editor/assembler/simulator. I have got onto part 2 http://compilers.iecc.com/crenshaw/tutor2.txt but the Divide procedure is not working properly for me.

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

If I input "8/2" as a test, then the compiler generates the following code:

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

This seems to me that it is actually calculating 2/8 (ie it's the wrong way round) as the value left in D0 afterwards is 00020000. I can fix this by rewriting the last line as DIVS D0,D1 but this leaves the result in D1 rather than D0 as per the other routines and it seems unlikely to me that such a seminal work would be incorrect. I have searched the internet but I can't see anyone else has come across this problem. So does that mean: 1) I have done it wrong - likely 2) Jack did it wrong - unlikely 3) The Easy68k emulator is doing something wrong - unlikely However I just can't see what I have done wrong. Please help.

1条回答
再贱就再见
2楼-- · 2019-05-08 03:41

I think I may have cracked it. Article 3 of the tutorial http://compilers.iecc.com/crenshaw/tutor3.txt has a slightly different version of the Divide procedure, although it doesn't seem to be explained so perhaps it is a typo.. The revised version in the third article is

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

Note the addition of the line

EmitLn('EXS.L D0');

which seems intended to swap the contents of registers D0 and D1. Now whilst Easy68k doesn't seem to like "EXS.L D0", after checking the Easy68 documentation I have changed this to read

EmitLn('EXG D0,D1');

and now the Divide procedure works. I'm not sure if this is specific to Easy68k or why the article says EXS.L but at least it works now. Hurray!

查看更多
登录 后发表回答