对这个看似微不足道的问题道歉,但我似乎无法在任何地方找到答案 - 我只是想在我的Z80仿真器中实现DAA指令,我在Zilog手册中注意到它是为了为二进制编码的十进制算术调整累加器的目的。它表示该指令旨在在加法或减法指令后立即运行。
我的问题是:
答案 0 :(得分:15)
是否只是根据DAA表中规定的条件修改累加器,无论前一条指令如何?
是。该文档仅告诉您DAA的用途。也许您指的是this link处的表格:
--------------------------------------------------------------------------------
| | C Flag | HEX value in | H Flag | HEX value in | Number | C flag|
| Operation | Before | upper digit | Before | lower digit | added | After |
| | DAA | (bit 7-4) | DAA | (bit 3-0) | to byte | DAA |
|------------------------------------------------------------------------------|
| | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
| ADD | 0 | 0-8 | 0 | A-F | 06 | 0 |
| | 0 | 0-9 | 1 | 0-3 | 06 | 0 |
| ADC | 0 | A-F | 0 | 0-9 | 60 | 1 |
| | 0 | 9-F | 0 | A-F | 66 | 1 |
| INC | 0 | A-F | 1 | 0-3 | 66 | 1 |
| | 1 | 0-2 | 0 | 0-9 | 60 | 1 |
| | 1 | 0-2 | 0 | A-F | 66 | 1 |
| | 1 | 0-3 | 1 | 0-3 | 66 | 1 |
|------------------------------------------------------------------------------|
| SUB | 0 | 0-9 | 0 | 0-9 | 00 | 0 |
| SBC | 0 | 0-8 | 1 | 6-F | FA | 0 |
| DEC | 1 | 7-F | 0 | 0-9 | A0 | 1 |
| NEG | 1 | 6-F | 1 | 6-F | 9A | 1 |
|------------------------------------------------------------------------------|
我必须说,我从未见过dafter指令规范。如果仔细检查表,您将看到指令的效果仅取决于C
和H
标志以及累加器中的值 - 它不依赖于前面的指令所有。此外,它不会泄露发生的情况,例如C=0
,H=1
,累加器中的低位数是4或5.所以你必须执行NOP
在这种情况下,或生成错误消息,或其他什么。
答案 1 :(得分:9)
只是想补充说N标志是他们谈论上一次操作时的意思。增加设置N = 0,减法设置N = 1.因此A寄存器的内容以及C,H和N标志确定结果。
该指令旨在支持BCD算法,但还有其他用途。请考虑以下代码:
and 15
add a,90h
daa
adc a,40h
daa
它结束将A寄存器的低4位转换为ASCII值'0','1',...'9','A','B',...,'F'。换句话说,二进制到十六进制转换器。
答案 2 :(得分:0)
这是生产中的代码,可以正确实现DAA并通过zexall / zexdoc / z80test Z80操作码测试服。
基于The Undocumented Z80 Documented,第17-18页。
void daa()
{
int t;
t=0;
// 4 T states
T(4);
if(flags.H || ((A & 0xF) > 9) )
t++;
if(flags.C || (A > 0x99) )
{
t += 2;
flags.C = 1;
}
// builds final H flag
if (flags.N && !flags.H)
flags.H=0;
else
{
if (flags.N && flags.H)
flags.H = (((A & 0x0F)) < 6);
else
flags.H = ((A & 0x0F) >= 0x0A);
}
switch(t)
{
case 1:
A += (flags.N)?0xFA:0x06; // -6:6
break;
case 2:
A += (flags.N)?0xA0:0x60; // -0x60:0x60
break;
case 3:
A += (flags.N)?0x9A:0x66; // -0x66:0x66
break;
}
flags.S = (A & BIT_7);
flags.Z = !A;
flags.P = parity(A);
flags.X = A & BIT_5;
flags.Y = A & BIT_3;
}
为了可视化DAA交互,出于调试目的,我编写了一个小的Z80汇编程序,该程序可以在实际的ZX Spectrum或准确模拟DAA的仿真中运行:https://github.com/ruyrybeyro/daatable
按照其行为方式,在此汇编程序产生的DAA之前和之后,获得了一个标志N,C,H表并注册了A:https://github.com/ruyrybeyro/daatable/blob/master/daaoutput.txt