简体   繁体   English

如何在汇编中执行 aaa 指令到大于 99 的数字

[英]how to do aaa instruction in assembly to number bigger than 99

i work on assembly for the X86 platform and i got an issue with doing bcd for numbers bigger than 99.我为 X86 平台进行组装工作,但我在为大于 99 的数字做 bcd 时遇到了问题。

i got in 'AX' 123 (decimal) and i added to it 5 (decimal) then i did 'aaa' but instead of the result to be 128 its 0106. i saw the algorithm and understood why but how i do 'aaa' to number over 99我得到了 'AX' 123(十进制)并添加到它 5(十进制)然后我做了 'aaa' 但结果不是 128 而是 0106。我看到了算法并理解了为什么但我如何做 'aaa'编号超过 99
that's my code:那是我的代码:

mov ax,123
add ax,5
aaa

i tried to divide 'AX' in 0ah to separate the number and use 'aad' but i saw that it's forbiden for numbers over 99.我试图将“AX”除以 0ah 以分隔数字并使用“aad”,但我看到它禁止超过 99 的数字。

The 'AAA" instruction ("ASCII Adjust After Addition") only cares about the value in the lowest 4 bits of AL (it's literally " if(AL & 0x0F > 9) AX += (1 << 8) + (1 << 4) - 10; ", or "if the previous addition caused the lowest nibble/digit to overflow; then subtract 10 from the lowest nibble/digit and add 1 to second nibble/digit to fix up the carry that should've happened but didn't, then add 1 plus the carry from second nibble/digit to the third nibble/digit while most people wish this didn't happen"). “AAA”指令(“ASCII Adjust After Addition”)只关心AL的最低 4 位中的值(字面意思是“ if(AL & 0x0F > 9) AX += (1 << 8) + (1 << 4) - 10; ", 或 "如果之前的加法导致最低半字节/数字溢出;然后从最低半字节/数字中减去 10,并将第二个半字节/数字加 1 以修复应该发生的进位但没有,然后将 1 加上从第二个半字节/数字到第三个半字节/数字的进位,而大多数人希望这不会发生”)。

For 8-bit packed BCD addition (eg one digit in the lowest nibble of AL and another digit in the highest nibble of AL) this is a major pain in the neck - you have to store the first nibble somewhere then shift the value in AL to the right and do a second aaa to fix up the second nibble.对于 8 位压缩 BCD 加法(例如 AL 的最低半字节中的一个数字和 AL 的最高半字节中的另一个数字),这是颈部的主要痛苦 - 您必须将第一个半字节存储在某处然后移动 AL 中的值向右并做第二个aaa来修复第二个半字节。 This can be done with rotates - eg aaa then ror ax,4 then aaa then rol ax,4 .这可以通过旋转来完成 - 例如aaa然后ror ax,4然后aaa然后rol ax,4

For 8-bit unpacked BCD addition (eg one digit in the lowest nibble of AL and another digit in the lowest nibble of AH) it's mostly the same major pain in the neck.对于 8 位未压缩 BCD 加法(例如 AL 的最低半字节中的一个数字和 AH 的最低半字节中的另一个数字),颈部的主要疼痛几乎相同。

For "12-bit or larger" packed BCD addition it goes from bad to worse because first aaa causes the third nibble/digit to be potentially corrupted (increased by 1 too many if the first nibble overflowed), the second aaa potentially corrupts the fourth nibble/digit, etc.对于“12 位或更大”的压缩 BCD 加法,它会变得越来越糟,因为第一个aaa会导致第三个半字节/数字可能被破坏(如果第一个半字节溢出,则增加 1 太多),第二个aaa可能会破坏第四个半字节/数字等

For "12-bit or larger" unpacked BCD addition it goes from bad to worse because (for 16-bit code) now your digits have to be spread across multiple registers and you end up shuffling values into/out of AL just to use the aaa instruction.对于“12 位或更大”的未打包 BCD 加法,它会变得越来越糟,因为(对于 16 位代码)现在您的数字必须分布在多个寄存器中,并且您最终将值混入/输出 AL 只是为了使用aaa指令。

The only sane solution is to never use aaa unless you're doing 4-bit addition (which is why it got removed in 64-bit code - nobody used it anyway).唯一明智的解决方案是永远不要使用aaa ,除非您正在执行 4 位加法(这就是它在 64 位代码中被删除的原因 - 反正没人使用它)。

The best alternative is to convert from BCD to normal integer at first sight, then do all the calculations using normal integers, then convert from normal integer back into BCD at the last possible opportunity.最好的选择是乍一看从 BCD 转换为普通 integer,然后使用普通整数进行所有计算,然后在最后可能的机会从普通 integer 转换回 BCD。 This approach can be especially nice if you can use the FPU - eg fbld to load an 18-digit (72 bit) packed BCD value into an FPU register while converting it into a normal floating point value and fbstp to convert a normal floating point value into BCD and store it.如果您可以使用 FPU,这种方法会特别好 - 例如fbld将 18 位(72 位)压缩 BCD 值加载到 FPU 寄存器中,同时将其转换为普通浮点值, fbstp将其转换为普通浮点值成 BCD 并存储。

Anyway...反正...

    mov ax,123        ;This is not valid BCD - it's the value 0x7B or "7(11)" in decimal
    add ax,5          ;ax = 0x7B + 0x05 = 0x80
    aaa               ;This instruction does nothing because the lowest nibble is less than 9
                      ;Result = 0x80 or "80" in decimal

If the original value/s being added were valid BCD, then you might get something like:如果添加的原始值是有效的 BCD,那么您可能会得到如下信息:

    mov ax,121        ;ax = 0x79 or "79" in decimal
    add ax,5          ;ax = 0x79 + 0x05 = 0x7E
    aaa               ;0xE is is larger than 9, so "fix" it by adding 0x0106
                      ;ax = 0x0184
                      ;Result in AL = 0x84 or "84" in decimal

However, it this is a "lucky case" because the result fits in 2 digits.但是,这是一个“幸运的情况”,因为结果适合 2 位数。 It could easily be more like:它可能更像是:

    mov ax,152        ;ax = 0x98 or "98" in decimal
    add ax,5          ;ax = 0x99 + 0x05 = 0x9D
    aaa               ;0xD is is larger than 9, so "fix" it by adding 0x0106
                      ;ax = 0x01A3
                      ;Result in AX is a horribly broken mess (second digit not valid BCD, third digit correct)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM