压缩十进制数的每个字节存放两个十进制数字,每个数字用 4 位表示。
- bcd1 QWORD 2345673928737285h ;十进制数 2345673928737285
- bcd2 DWORD 12345678h ;十进制数 12345678
- bcd3 DWORD 08723654h ;十进制数 8723654
- bcd4 WORD 9345h ;十进制数 9345
- bcd5 WORD 0237h ;十进制数 237
- bcd6 BYTE 34h ;十进制数 34
虽然声明的是16进制数,但是在压缩BCD码的的标准下,16进制的0~9与10进制的0~9刚好是相同的。压缩十进制存储至少有两个优势:1) 数据几乎可以包含任何个数的有效数字。这使得以很高的精度执行计算成为可能。2) 实现压缩十进制数与 ASCII 码之间的相互转换相对简单。
压缩BCD码有对应的加减法指令,但目前还没有乘除法指令,所以当使用乘除法时两个操作数必须是非压缩BCD码。
DAA (Decimal Adjust after Addition)加法后的十进制调整,32 位模式下,先用ADD 或 ADC 指令在 AL 中生成二进制和数,再用DAA指令将和数转换为压缩十进制格式。比如,下述指令执行压缩十进制数 35 加 48。如果视为16进制数相加,那么35h+48h=7Dh,但是通过DAA指令转化后结果变成83(35+48=83)。
- .386
- .model flat, stdcall
- .stack 4096
- ExitProcess proto, dwExitcode:dword
- Include Irvine32.inc
-
- .data
-
- .code
- main proc
- nop
- mov al, 35h
- add al, 48h
- daa ;AL=83h
- invoke ExitProcess, 0
- main endp
- end main
下面的程序执行两个 16 位压缩十进制整数加法,并将和数保存在一个压缩双字中。
- .386
- .model flat, stdcall
- .stack 4096
- ExitProcess proto, dwExitcode:dword
- Include Irvine32.inc
-
- .data
- num1 WORD 4536h
- num2 WORD 7207h
- sum DWORD ?
-
- .code
- main proc
- clc
- mov esi, 0
- mov ecx, type num1
- L1:
- mov al, byte ptr num1[esi]
- adc al, byte ptr num2[esi] ;此处使用adc而不用add,是因为两数相加有可能进位。
- daa
- mov byte ptr sum[esi], al
- inc esi
- loop L1
- adc byte ptr sum[esi], 0 ;此处再次重复,因为最后一位相加后有可能进位标志位里有内容。
- invoke ExitProcess, 0
- main endp
- end main
Decimal Adjust AL after Subtraction,减法后的十进制调整。先完成SUB或SBB指令在AL中生成二进制结果,然后再用DAS指令将其转换为压缩BCD码。
具体调整规则如下:
比如,下面的语句计算压缩十进制数 85 减 48,并调整结果:
- .386
- .model flat, stdcall
- .stack 4096
- ExitProcess proto, dwExitcode:dword
- Include Irvine32.inc
-
- .data
-
- .code
- main proc
- mov bl,48h
- mov al,83h
- sub al,bl
- das
- invoke ExitProcess, 0
- main endp
- end main