除法(DIVS)在 Jack Crenshaw 上不起作用,让我们构建一个编译器

发布于 2024-12-27 07:05:41 字数 1002 浏览 3 评论 0原文

我正在遵循 Jack Crenshaw 在 http://compilers.iecc.com/crenshaw< 上找到的优秀的让我们构建编译器教程< /a>.我正在使用 Easy68k http://www.easy68k.com/ 68000 编辑器/汇编器测试生成的 68k 程序集/模拟器。我已经进入第 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 模拟器做错了什么 - 不太可能 然而我就是看不到我做错了什么。 请帮忙。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

空袭的梦i 2025-01-03 07:05:41

我想我可能已经破解了它。教程http://compilers.iecc.com/crenshaw/tutor3.txt的第3条略有不同除法程序的版本,尽管它似乎没有解释,所以可能是一个拼写错误。第三篇文章中的修订版本是

{ 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 文档后,我已将其更改为 read

EmitLn('EXG D0,D1');

,现在 Divide 过程可以工作。我不确定这是否是 Easy68k 特有的,或者为什么文章说 EXS.L,但至少现在它可以工作了。欢呼!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文