当 Addition 高于 15 时,x86 程序集错误中的解压缩十进制格式

Unpacked Decimal Format in x86 Assembly bugs when Addition is above 15

    const char* p = rhs.digits; //temp pointer to rhs.digits.
    char* q = digits;   //temp to just digits
    _asm {
        mov EAX, 0      //clear register for addition
        mov ESI, p      //point to rhs.digits
        mov EDI, q      //point to digits
        add EDI, 4095  //last position of digits
        add ESI, 4095
        mov ECX, 4096   //set up loop
        L1:
            mov AL, [EDI]   //setup for addition
            add AL, [ESI]   //Add
            add AL, AH      //Add carry
            mov AH, 0       //Clear AH register
            AAA             //Adjust after addition
            mov [EDI], AL
            dec ESI
            dec EDI //move pointers
        loop L1
    }

这是一个用 C++ 编写的内联 asm 函数。 Digits 是一个长度为 4096 个字符的字符数组,rhs.digits 是一个单独的数组。 Digits 是目的地,rhs.digits 是要添加到 digits 的数组。

我遇到的问题是关于加法结果大于 15 时的进位。所以 8+8、8+9、9+9。我不是 100% 确定 AAA 是如何工作的,但我相信它会丢弃值的高位并将低位放入 AH。这意味着因为 16、17 和 18 不能用一个十六进制数字表示而需要两个,所以更高阶的位将被丢弃和忽略。

这通过检查输出得到加强。如果 8+8 0 放在那个位置。如果 8+9, 1 和 9+9, 2. 这将对应于它们的十六进制表示。我尝试使用 DAA,但也没有用。

我该如何解决这个问题?是否有解释说明?

感谢大家的帮助。

对于 packed BCD 值,您需要使用 the DAA instruction,例如

clc
L1:
mov AL, [EDI]
adc AL, [ESI]
daa
mov [EDI], AL
; etc

对于unpacked BCD码需要使用the AAA instruction(ASCII Adjust After Addition),例如

clc
L1:
mov AL, [EDI]
adc AL, [ESI]
aaa                ; CF=AF=decimal carry-out from AL.  Also added to AH
mov [EDI], AL
; etc

请注意,进位标志在 decloop 指令后仍然存在。