sup*_*ods 5 x86 assembly bcd x86-16 80286
我正在看伪代码:BCD指令的隐藏能力.以下是该网站内容的片段:
那么,让我们来看看AAA的作用.这是伪代码等价物(来自英特尔):
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
Run Code Online (Sandbox Code Playgroud)
对于像这样的典型英特尔文档兼容用途,这是正确的:
mov al,6
add al,9 ;al=15=0Fh
aaa ;al=21=15h => it's in decimal!
Run Code Online (Sandbox Code Playgroud)
上面的算法似乎没有在代码中给出结果,所以我假设这里省略了一些步骤.评论说明如下:"al = 21 = 15h =>它是十进制的!".
我对代码的解释如下:
但是,在运行"AH =(AH + 1);"行之前,没有提到存储在AH寄存器中的值.如果它被初始化为零,它只适用于20以下的数字.现在我们假设它被初始化为零,我希望结果存储为AH = 1和AL = 5,但评论说"; al = 21 = 15h =>它是十进制的!" 在执行此代码块之前和之后,似乎还有其他事情已经完成.
你能解释一下我在这里失踪了吗?
此外,这里如何使用CF/AF标志?
看起来作者对AAA所做的事情的理解是错误的,他可能将其与DAA混淆(加法后的十进制调整AL),但更糟糕的是,多年来英特尔文档有时不正确2 3,因此增加了困惑.
我不打算直接回答你的问题,但我想给你一些背景信息,可以让你在给出适当的文件的情况下找出你自己问题的答案.您在问题中引用的文档仅适用于早于80286的处理器,即使这样,它也包含有关屏蔽AL 2底部4位的错误
在添加两个有效的解压缩BCD编号(ASCII 到或0x30到0x39)之后,将使用AAA的原始意图,将结果转换为有效的 2位BCD编号.有些人在设计之外滥用AAA.不幸的是,当286宣布时,一些滥用AAA的代码破了.09
该AAA指令最好的定义是这样1:
Run Code Online (Sandbox Code Playgroud)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.
Run Code Online (Sandbox Code Playgroud)
由于此代码使用有效值(0x30至0x39),因此对于支持该指令的所有处理器,它将以相同的方式工作1.更一般地说,只要AL中的值是0x00到0xF9(包括),如果在处理器<286和286或更高版本的处理器上运行,则AAA的结果将是相同的.
如果添加三个或更多BCD编号,您可以使用AH中的值来帮助维持正确溢出的结果.
该AAS指令最好的定义是这样1:
Run Code Online (Sandbox Code Playgroud)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
笔记: