z80的装配冒泡排序

时间:2015-09-17 18:00:35

标签: assembly bubble-sort z80

我的大学任务。我需要为z80处理器组装程序。该计划应该做到以下几点。

从0201H开始,有20个数字存储在20个连续存储器地址中。 程序应首先检查存储在0200H中的数字。如果值为0,程序应按升序对数字进行排序,否则按降序排序。最后,在排序结束后,程序应计算这20个数字的平均值。

我知道这个问题不是根据网站规则形成的,但我确实需要帮助。

2 个答案:

答案 0 :(得分:6)

这是Z-80汇编语言的快速指南。可以把它想象成C,但删除了大部分功能。从根本上说,您只需要使用一些变量:

unsigned char A;
unsigned short BC, DE, HL, IX, IY;
unsigned char memory[65536];

没有结构,没有块,没有for或while循环以及一种受损的if。有goto会跳转到标签。或者你可以call一个类似于子程序的标签,但它不带参数并返回void。我们总是可以从这些部分构建更多功能,但对于简单程序,我们拥有的变量和一些memory[]就足够了。

您可以使用=进行分配,但有很多规则。例如,所有这些都是合法的:

A = memory[26];
memory[738] = A;
A = memory[BC];
memory[DE] = A;

但你不能使用任何旧表达式,如:

A = memory[BC + DE];

可以为short分配memory[]变量,但由于它们大于char,因此会自动拆分。当您说memory[15] = BC;时,它会认出它不适合并代表您执行此操作:

memory[15] = BC % 256;
memory[16] = BC / 256;

为了有用,当你说BC = memory[15]

时会发生相反的情况
BC = memory[15] + memory[16] * 256;

为了更加奇怪,您可以BCB独立地讨论C的这些高低部分。但是你不能B = memory[25]。如果您需要,则需要使用A作为中介:

A = memory[25];
B = A;

DE可以DE以及HL作为HL来解决。但不是IXIY(嗯,不合法,但让我们不进入那个)。

所有变量都可以递增和递减。如果您愿意,请A = A + 1A++A = A - 1。与BCDEHLIXBC等相同。

你能D = D + 2吗?没有!你必须D++; D++;。谈到数学,A很特别。您可以向其添加任何无符号字符或常量。或减去。有一些逻辑操作,如&|^,但我们不担心这些。您还可以添加或减去我们的unsigned char变量,例如DL。但是您无法添加或减去memory[]。这也必须分段完成。假设您需要A = A + memory[84]

B = A; // save A
A = memory[84];
A = A + B;

是的,它可能会变得单调乏味。人们开始欣赏编译器。你也可以在HL,IX和IY中加减,但在更有限的情况下:

HL = HL + BC;
HL = HL + DE;
HL = HL + HL;  // Same as HL = 2 * HL.
IX = IX + BC;
IX = IX + DE;
IX = IX + IX;
// And follow the same pattern for IY

乘法和除法怎么样?不,不支持。但是,通过循环和位移操作符,您可以设法模拟它们。或者效率较低,你可以通过重复加法和重复减法除法来进行乘法运算。

但是循环怎么样呢?好吧,你可以用这样的东西填充内存:

HL = 9; // You can assign constants to all your variables, thankfully.
A = 0;
loop:
  memory[HL] = A;
  HL = HL + 1;
  goto loop;

我是否提到您的计划位于memory[]?没有?嗯,这确实是一个问题。如果你只想清除memory[]中的10个,你会怎么做?这里是疯狂的if进来的地方。你想写这样的东西:

HL = 9;
A = 0;
B = 10;
loop:
  memory[HL] = A;
  HL++;
  B = B - 1;
  if (B == 0) goto loop

[哎呀,那是一个错误。应该是!= 0,但假装它是正确的;我懒得重新输入这一切。 ] 但if (B == 0)并不是支持的内容。太复杂。但有一个goto loop if zero;这是什么意思?好吧,每次进行数学处理时,处理器都会记住一些关于结果的事情。一个是如果结果等于零。事实证明,我们可以简单地将if替换为:

goto loop if zero;

我们将循环10次。我们甚至可以将代码概括为清除memory[]给出的一些C条目。怎么样?通过B计数并循环返回,只要它还不等于C。我们无法if (B == C),但我们可以从B中减去C并检查零结果,这是相同的。好吧,我们不能C = C - B,只有A可以做到。循环看起来像这样:

loop:
  memory[HL] = 0; // turns out we can do this
  HL = HL + 1;
  B = B + 1;
  A = C;
  A = A - B;
  goto done if zero;
  goto loop;
done:

尴尬,但它会起作用。设计师有一些怜悯。如果结果不为零,您可以goto

A = A - B;
goto loop if not zero;

如果结果小于或大于零,则允许其他一些测试。但是对零的简单测试可能会让我们走得很远。

特殊情况比比皆是。如果我们不小心写了这个怎么办:

loop:
  memory[HL] = 0;
  B = B - 1;
  HL = HL + 1;
  goto loop if not-zero;

看起来像一个错误,不是它。我们不会进行B次迭代,而是继续前进,直到HL回绕到0为止。但事实并非如此。当我们添加或减去像HL这样的短值时,它不会影响zero/not-zero条件。代码将起作用。事实上,这被Z-80的设计师认为是一个特色。

关于我唯一提到的另一件事是函数调用或子例程,如果你愿意的话。考虑到每个小东西必须拼写出来,你可以看到即使一个简单的函数将数字乘以4也会很好。但是没有参数也没有返回值。不能说B = mult4(B);之类的东西而是我们只设置约定,我们决定使用哪些变量或内存位置来传递参数以及结果的位置。然后打电话来计算出来。我们可以定义一个子例程,将B乘以4并返回A中的结果:

mult4:
  A = B;
  A = A + A; // that is, B * 2
  A = A + A; // B * 4, we're don!
  return;

如果我们不想将D乘以4,我们就这样做:

B = D;
mult4();
D = A;

足够公平。我们还必须记住mult4()消除了A中的值,因此如果需要,我们最好保存它。就此而言,我们自己不得不用B来打电话。如果我们需要这些变量,那么我们只需要在memory[]中找到将它们存放的地方。

memory[20] = A; // can't forget A
B = D;
mult4();
D = A;
A = memory[20]; // back to what it was.

这就是Z-80汇编语言编程。哦,还有其他一些东西。并且您已经用口音说出了所有内容,但如果您查找有关Z-80汇编语言的信息,我相信您会明白这一点。以下是一些例子:

A = memory[4];               LD A,(4)
A = 3;                       LD A,3
memory[2] = A;               LD (2),A
A = A + B;                   ADD A,B
B = B + 1;                   INC B

祝你好运。

答案 1 :(得分:1)

对于使用Z80汇编程序代码的任何人来说,

Programming Z80 by Rodnay Zaks是必读的。可以在作者许可的情况下下载。

顺便说一句,该书中包含的代码示例之一是冒泡排序,从上到下解释。

the home of the Z80 CPU提供了更多与Z80相关的信息。