我的大学任务。我需要为z80处理器组装程序。该计划应该做到以下几点。
从0201H开始,有20个数字存储在20个连续存储器地址中。 程序应首先检查存储在0200H中的数字。如果值为0,程序应按升序对数字进行排序,否则按降序排序。最后,在排序结束后,程序应计算这20个数字的平均值。
我知道这个问题不是根据网站规则形成的,但我确实需要帮助。
答案 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;
为了更加奇怪,您可以BC
和B
独立地讨论C
的这些高低部分。但是你不能B = memory[25]
。如果您需要,则需要使用A
作为中介:
A = memory[25];
B = A;
DE
可以D
和E
以及HL
作为H
和L
来解决。但不是IX
和IY
(嗯,不合法,但让我们不进入那个)。
所有变量都可以递增和递减。如果您愿意,请A = A + 1
或A++
。 A = A - 1
。与BC
,DE
,HL
,IX
,B
,C
等相同。
你能D = D + 2
吗?没有!你必须D++; D++;
。谈到数学,A
很特别。您可以向其添加任何无符号字符或常量。或减去。有一些逻辑操作,如&
,|
和^
,但我们不担心这些。您还可以添加或减去我们的unsigned char
变量,例如D
或L
。但是您无法添加或减去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)
Programming Z80 by Rodnay Zaks是必读的。可以在作者许可的情况下下载。
顺便说一句,该书中包含的代码示例之一是冒泡排序,从上到下解释。
the home of the Z80 CPU提供了更多与Z80相关的信息。