Z80 DAA指令

Phi*_*987 18 math z80 bcd

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

我的问题是:

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

Ton*_*nyK 16

它是否只是根据DAA表中设置的条件修改累加器,而不管之前的指令是什么?

是.该文档仅告诉您DAA的用途.也许你指的是这个链接的表格:

--------------------------------------------------------------------------------
|           | 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   |
|------------------------------------------------------------------------------|
Run Code Online (Sandbox Code Playgroud)

我必须说,我从未见过dafter指令规范.如果仔细检查表,您将看到指令的效果仅取决于CH标志以及累加器中的值 - 它完全不依赖于前一条指令.此外,它不会透露,如果,例如,会发生什么C=0,H=1以及在累加器的低位为4或5.所以,你必须执行NOP在这种情况下,或产生错误信息,或什么的.

  • Z80 的 DAA 应该等同于 x86 的 DAA 和 DAS,因为它们具有相同的用途。查看两者的 x86 描述。许多 CPU 上都提供了某种 DAA。 (2认同)
  • @Alex:x86 芯片有两个十进制调整指令:DAA(加法后十进制调整)和 DAS(减法后十进制调整)。Z80 DAA 指令假设最近的加/减操作数是有效的 BCD 数,从而将它们合二为一。 (2认同)
  • 如果将ADD,ADC,INC 替换为N=0,并将SUB,SBC,DEC,NEG 替换为N=1,则可以大大改进该表。DAA 不知道最后执行的是哪条指令。 (2认同)

Geo*_*ips 10

只是想补充说N标志是他们谈论上一次操作时的意思.加法设置N = 0,减法设置N = 1.因此,A寄存器的内容以及C,H和N标志确定结果.

该指令旨在支持BCD算法,但还有其他用途.考虑以下代码:

    and  15
    add  a,90h
    daa
    adc  a,40h
    daa
Run Code Online (Sandbox Code Playgroud)

它结束将A寄存器的低4位转换为ASCII值'0','1',......'9','A','B',...,'F'.换句话说,二进制到十六进制转换器.


小智 8

我发现这条指令也很混乱,但我发现从z80-天堂这种行为的描述最有帮助.

执行该指令时,使用标志的内容对A寄存器进行BCD校正.具体过程如下:如果A的最低有效4位包含非BCD数字(即大于9)或H标志置位,则将06美元添加到寄存器中.然后检查四个最高有效位.如果这个更重要的数字也恰好大于9或者设置了C标志,则增加60美元.

这为指令提供了一个简单的模式:

  • 如果低4位形成大于9的数字或H置位,则向累加器添加$ 06
  • 如果高4位形成大于9的数字或设置了C,则向累加器添加60美元

此外,虽然DAA 旨在在加法或减法后运行,但它可以随时运行.

  • @Salgat当"N = 1"时适用相同的规则.唯一的是你必须在"N = 1"时减去校正. (3认同)

Rui*_*iro 5

这是生产中的代码,正确实现了 DAA 并通过了 zexall/zexdoc/z80test Z80 操作码测试套件。

基于未记录的 Z80 记录,第 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;
}
Run Code Online (Sandbox Code Playgroud)

为了可视化 DAA 交互,出于调试目的,我编写了一个小型 Z80 汇编程序,可以在实际 ZX Spectrum 或准确模拟 DAA 的仿真中运行:https : //github.com/ruyrybeyro/daatable

至于它的行为方式,在使用上述汇编程序生成的 DAA 之前和之后,得到了一个标志 N、C、H 和寄存器 A 的表:https : //github.com/ruyrybeyro/daatable/blob/master/daaoutput.txt