我正在查看伪代码:The Hidden Power of BCD Instructions。这是网站内容的摘要:
因此,让我们看一下AAA的功能。这是等效代码(来自Intel):
IF ((AL AND 0FH) > 9) OR (AF = 1)
THEN
AL = (AL + 6) AND 0FH;
AH = (AH + 1);
AF = 1;
CF = 1;
ELSE
AF = 0;
CF = 0;
FI;enter code here
对于像这样的典型的符合英特尔文档的用法是正确的:
mov al,6
add al,9 ;al=15=0Fh
aaa ;al=21=15h => it's in decimal!
上面的算法似乎没有给出代码中注释的结果,因此我假设这里省略了一些步骤。注释说明如下:“ al = 21 = 15h =>十进制!”。
我对代码的解释如下:
但是,在运行“ AH =(AH + 1);”行之前,没有提到存储在AH寄存器中的值。如果将其初始化为零,则仅适用于20以下的数字。现在让我们假设它已初始化为零,我希望结果存储为AH = 1和AL = 5,但注释中会显示“ ;; al = 21 = 15h =>用十进制表示!”。在执行此代码块之前和之后,似乎还有其他事情要做。
您能告诉我我在这里想念的吗?
此外,这里如何使用CF / AF标志?
答案 0 :(得分:7)
作者对 AAA 的操作的理解似乎被误导了,他可能将其与 DAA (加法后的小数调整AL)相混淆,但使情况变得更糟多年来的英特尔文档有时不正确地是 2 3 ,从而加剧了混乱。
我不会直接回答您的问题,但我想为您提供一些背景知识,如果有适当的文档说明,您可以根据自己的问题找出答案。您在问题中引用的文档仅适用于80286之前的处理器,即使这样,它也包含有关掩盖AL 2
的低4位的错误。在添加两个有效未打包的BCD数字(ASCII 0
至9
或0x30)之后,将使用 AAA 的原始意图(0x39)将结果转换为有效 2位BCD编号。有些人滥用了 AAA 以外的用途。不幸的是,当286宣布时,一些滥用 AAA 的代码就破裂了。
最好以这种方式定义AAA instruction 1 :
IF ((( AL and 0FH ) > 9 ) or (AF==1) IF CPU<286 THEN AL = AL+6 ELSE AX = AX+6 ENDIF AH = AH+1 CF = 1 AF = 1 ELSE CF = 0 AF = 0 ENDIF AL = AL and 0Fh
添加两个个位数的BCD号码时,您需要在 AAA 之前清除AH。将两个数字相加的代码如下所示:
xor ah, ah ; Clear AH
mov al, '6' ; AL=0x36 (0x36 = ASCII '6')
add al, '9' ; AL=0x36+0x39 (0x39 = ASCII '9') = 0x6F
aaa ; AH=0x01, AL=0x05 thus AX=0x0105 . AH has upper digit, AL has the lower.
由于此代码使用有效值(0x30至0x39),因此对于支持该指令的所有处理器,其工作方式均相同 1 。更普遍的是,只要在 AL 中的值为0x00到0xF9(包括0xF9),如果在处理器<286和286上运行的 AAA 的结果将相同。以后的处理器。
如果添加三个或更多BCD编号,则可以使用AH中的值来帮助保持正确的溢出结果。
AAS 指令最好以这种方式定义 1 :
IF ((( AL and 0FH ) > 9 ) or (AF==1) IF CPU<286 THEN AL = AL-6 ELSE AX = AX-6 ENDIF AH = AH-1 CF = 1 AF = 1 ELSE CF = 0 AF = 0 ENDIF AL = AL and 0Fh
注意: