将十六进制数字转换为相应的十进制数字

Converting hex digits to corresponding decimal digits

所以我在作业中有这个问题,我不知道我是否理解正确。 它说: *编写汇编代码将 AL 中的打包 BCD 字节转换为二进制。例子:假设 Al = 35H 表示十进制数35,应转换为00100011 = 23H = 2*16+3 =35d.* 据我了解,它需要我将十六进制数字中的数字转换为十进制数字中的数字。 即35H到35d。 有人可以确认这是否是它要问的吗? 如果是这样,有人可以帮我做一个算法吗?

正如@Michael 评论的那样,您只需要计算 (al >> 4) * 10 + (al & 0Fh)

你显然可以假设输入是正确的 BCD,字节的两个半字节都在 0 到 9 之间,存储单独的十进制数字。

请注意,它不是任意的十六进制字符串,甚至不与 ASCII 中的数字一起存储。所以你不必做任何事情来处理 ASCII '0'..'9' 在 'A'..'F' 之前有一个间隙的事实,就像你实际上将数字字符串视为非标准化基数 10,位值为 0..15,位值为 10^n.

您刚刚打包了BCD。是的,这些位的 base-16 解释会给你 0x35.

但是你想要一个二进制整数,它表示与将这些半字节视为十进制数字相同的值,位值为 10^n。因此,您将半字节分开并将高位乘以 10。


如果您不关心性能,可以使用 x86 的遗留 ASCII/BCD 指令。它们在 16 位和 32 位模式下可用。 (x86-64 删除了 BCD 指令)。这里唯一的优势是代码大小:两个 2 字节的指令可以慢慢完成工作。

    aam 16          ; split AL into AH = AL/16; AL = AL%16
    aad             ; AL = AH*10 + AL;  AH=0

aam 使用除法,因此它可以用于任何立即数;以 2 的幂使用它对于性能来说效率非常低,只对代码大小有好处。预期用途是将二进制整数拆分为 2 个未压缩的十进制数字(ASCII Adjust AX After Multiply),默认立即除数为 10.

AAD 的默认立即数也是我们想要的 10

https://www.felixcloutier.com/x86/aam and https://www.felixcloutier.com/x86/aad.

没有 dad 指令在 AL 中对压缩 BCD 执行相同的乘法运算,只有 DAA 和 DAS(在加法/减法之后)。


有效地执行此操作(为了性能而不是代码大小)留作 reader 的练习。 (或者对于编译器;GCC 在乘法部分使用 2x LEA 做得很好:https://godbolt.org/z/K-tjXv