Z80 DAA指令

时间:2011-11-14 09:34:34

标签: math bcd z80

对这个看似微不足道的问题道歉,但我似乎无法在任何地方找到答案 - 我只是想在我的Z80仿真器中实现DAA指令,我在Zilog手册中注意到它是为了为二进制编码的十进制算术调整累加器的目的。它表示该指令旨在在加法或减法指令后立即运行。

我的问题是:

  • 如果是在另一条指令之后运行会发生什么?
  • 怎么知道它之前的指令是什么?
  • 我意识到有一个N标志 - 但这肯定不会明确表明前一条指令是加法或减法指令?
  • 是否只是根据DAA表中规定的条件修改累加器,无论之前的指令如何?

3 个答案:

答案 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指令规范。如果仔细检查表,您将看到指令的效果仅取决于CH标志以及累加器中的值 - 它不依赖于前面的指令所有。此外,它不会泄露发生的情况,例如C=0H=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