汇编语言AAA指令:调整ADD或ADC指令的二进制运算结果

广告位

在 32 位模式下,AAA ( 加法后的 ASCII 调整 ) 指令调整 ADD 或 ADC 指令的二进制运算…

在 32 位模式下,AAA ( 加法后的 ASCII 调整 ) 指令调整 ADD 或 ADC 指令的二进制运算结果。设两个 ASCII 数字相加,其二进制结果存放在 AL 中,则 AAA 将 AL 转换为两个非压缩十进制数字存入 AH 和 AL。一旦成为非压缩格式,通过将 AH 和 AL 与 30h 进 OR 运算,很容易就能把它们转换为 ASCII 码。

下例展示了如何用 AAA 指令正确地实现 ASCII 数字 8 加 2。在执行加法之前,必须把 AH 清零,否则它将影响 AAA 执行的结果。最后一条指令将 AH 和 AL 转换为 ASCII 数字:

  mov ah, 0  mov al, '8'                     ; AX = 0038h  add al, '2'                     ; AX = 006Ah  aaa                             ; AX = 0100h (结果进行 ASCII 调整)  or ax, 3030h                    ; AX = 3130h ='10' (转换为 ASCH 码)

使用 AAA 实现多字节加法

现在来查看一个过程,其功能为实现包含了隐含小数点的 ASCII 十进制数值相加。由于每次数字相加的进位标志位都要传递到更高位,因此,过程的实现要比想象的更复杂一些。下面的伪代码中,acc 代表的是一个 8 位的累加寄存器:

esi (index) = length of first_number – 1
edi (index) = length of first_number
ecx = length of first_number
set carry value to 0
Loop
    acc = first_number[esi]     add previous carry to acc
    save carry in carry1
    acc += second_number[esi]     OR the carry with carry1
    sum[edi] = acc
    dec edi
Until ecx == 0
Store last carry digit in sum

进位值必须总是被转换为 ASCII 码。将进位值与第一个操作数相加时,就需要用 AAA 来调整结果。程序清单如下:

  ; ASCII Addition                      (ASCII_add.asm)  ; 对有隐含固定小数点的串执行 ASCII 运算。    INCLUDE Irvine32.inc    DECIMAL_OFFSET = 5                            ; 距离右侧的偏移量  .data  decimal_one BYTE "100123456789765"            ; 1001234567.89765  decimal_two BYTE "900402076502015"            ; 9004020765.02015  sum BYTE (SIZEOF decimal_one + 1) DUP(0),0    .code  main PROC    ; 从最后一个数字开始        mov    esi,SIZEOF decimal_one - 1      mov    edi,SIZEOF decimal_one      mov    ecx,SIZEOF decimal_one      mov    bh,0                       ; 进位值清零    L1:    mov    ah,0                    ; 执行加法前清除AH      mov    al,decimal_one[esi]        ; 取第一个数字      add    al,bh                      ; 加上之前的进位值      aaa                               ; 调整和数 (AH = 进位值)      mov    bh,ah                      ; 将进位保存到 carry1      or    bh,30h                      ; 将其转化为 ASCII 码      add    al,decimal_two[esi]        ; 加第二个数字      aaa                               ; 调整和数 (AH = 进位值)      or    bh,ah                       ; 将进位值 carry1 进行 OR 运算      or    bh,30h                      ; 将其转换为 ASCII 码      or    al,30h                      ; 将 AL 转换为 ASCII 码      mov    sum[edi],al                ; 将 AL 保存到 sum      dec    esi                        ; 后退一个数字      dec    edi      loop    L1      mov    sum[edi],bh                ; 保存最后的进位值    ; 显示和数字符串        mov    edx,OFFSET sum      call    WriteString      call    Crlf           exit  main ENDP  END main

程序输出如下所示,和数没有显示十进制小数点:

1000 5255 3329 1780

关于作者: 汇编语言

为您推荐

广告位

发表评论