【问题标题】:how does AAA work in 8086 instruction set?AAA 在 8086 指令集中如何工作?
【发布时间】:2013-09-22 15:06:48
【问题描述】:

有一些关于该指令如何工作的算法的信息:

if low nibble of AL > 9 or AF = 1 then:
    AL = AL + 6
    AH = AH + 1
    AF = 1
    CF = 1
else
    AF = 0
    CF = 0
in both cases:
    clear the high nibble of AL. 

Example:
  MOV AX, 15   ; AH = 00, AL = 0Fh
  AAA          ; AH = 01, AL = 05
  RET

但我面临的问题是,当我将上面示例中的 15 替换为 00FF 和 00FA 之类的数字时,AH 中的值会增加 02 而不是 01 !!

为什么会有这些变化??

【问题讨论】:

  • 您应该在添加后使用它。 35 年前使用 BCD 算术是有意义的,那些日子已经一去不复返了。
  • 值 00FF 和 00FA 不是 AAA 指令的合法输入。 AL 的最高法定值为 18 小时。
  • 我相信 AAA 的目的是一次添加 2 个 BCD 数字(这就是 AF 或半进位的用途),FF 是合法的输入值(例如 99 + 66 的结果)。
  • AAA 指令不会添加 BCD 数字,但会在 之后进行任何需要的数字溢出调整。如果您仔细阅读了AAA 指令描述,它会说,AAA 指令仅在它遵循添加(二进制加法)两个解压缩 BCD 值并将字节结果存储在 AL 寄存器中的 ADD 指令时才有用。 在您的00FF00FA 示例中,这些数字不能由BCD ADD 操作生成。

标签: assembly masm


【解决方案1】:

这里是DAA和AAA的详细解释:

aaa(加法后的 ASCII 调整)和 daa(加法的十进制调整)指令支持 BCD 算术。 BCD 值是以二进制形式编码的十进制整数,每个半字节有一个十进制数字 (0..9)。 ASCII(数字)值每个字节包含一个十进制数字,H.O.字节的半字节应包含零。

aaa 和 daa 指令修改二进制加法的结果,以更正 ASCII 或十进制算术。例如,要添加两个 BCD 值,您可以将它们作为二进制数相加,然后执行 daa 指令以更正结果。同样,您可以在执行 add 指令后使用 aaa 指令来调整 ASCII 加法的结果。请注意,这两条指令假定加法操作数是正确的十进制或 ASCII 值。如果将二进制(非十进制或非 ASCII)值相加并尝试按照这些说明调整它们,则不会产生正确的结果。

选择名称“ASCII 算术”是不幸的,因为这些值不是真正的 ASCII 字符。像“unpacked BCD”这样的名称会更合适。但是,英特尔使用名称 ASCII,因此本文也将这样做以避免混淆。但是,您经常会听到术语“解压 BCD”来描述这种数据类型。

Aaa(通常在 add、adc 或 xadd 指令之后执行)检查 al 中的值是否存在 BCD 溢出。它根据以下基本算法工作:

if ( (al and 0Fh) > 9 or (AuxC =1) ) then

    if (8088 or 8086) then 
            al := al + 6
    else 
            ax := ax + 6
    endif

    ah := ah + 1
    AuxC := 1               ;Set auxilliary carry
    Carry := 1              ; and carry flags.

else

    AuxC := 0               ;Clear auxilliary carry
    Carry := 0              ; and carry flags.
endif
al := al and 0Fh

aaa 指令主要用于添加数字字符串,其中一串数字中每个字节恰好有一个十进制数字。此文本不会处理 BCD 或 ASCII 数字字符串,因此您现在可以放心地忽略此指令。当然,您可以在需要使用上述算法的任何时候使用 aaa 指令,但这种情况可能很少见。

daa 指令的功能与 aaa 类似,只是它处理压缩的 BCD(二进制代码十进制)值,而不是 aaa 处理的每字节一个数字的未压缩值。至于 aaa,daa 的主要目的是添加 BCD 数字的字符串(每个字节有两个数字)。 daa的算法是

if ( (AL and 0Fh) > 9 or (AuxC = 1)) then

    al := al + 6
    AuxC := 1               ;Set Auxilliary carry.

endif
if ( (al > 9Fh) or (Carry = 1)) then

    al := al + 60h
    Carry := 1;             ;Set carry flag.

endif

因此,AAA 仅在每个字节有一个十进制数字的情况下才有效,而您上面提到的情况并非如此。

【讨论】:

  • 你不能对实际的 ASCII 数据使用 AAA 吗?它检查(AL AND 0FH) || AF 以检测数字的进位,因此它不应该被设置0x30 位所愚弄。 (ASCII '0' = 0x30 = 48,所以所有十个 ASCII 数字在低半字节都有整数值)。
  • 另外,官方文档的 HTML 摘录:felixcloutier.com/x86/AAA.html
  • 您实际上可以使用 0x30-0x39 范围内的 ASCII 数字。在 AAA 指令之后,如果需要 ASCII 结果,则需要将结果与 0x30 进行 OR 运算。
猜你喜欢
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多