7

我一直在努力理解来自 x86 汇编语言的 ASCII 调整指令。

我在互联网上看到所有信息告诉我不同​​的事情,但我想这只是以不同的形式解释的同一件事,我仍然不明白。

谁能解释为什么在 AL 的伪代码中AAAAAS我们必须从 AL 的低位半字节中加减 6?

有人可以解释一下AAM英特尔指令集手册中AAD的十进制调整指令伪代码也是如此,它们为什么会这样,它们背后的逻辑是什么?

最后,有人可以举例说明这些说明何时有用,或者至少在过去它们在哪些应用中有用。

我知道现在这些指令没有使用,但我仍然想知道这些指令是如何工作的,很高兴知道。

4

2 回答 2

10

为什么在 AAA 的伪代码中,AAS 我们必须从 AL 的低位半字节中加减 6

因为在十六进制中,每个字符都有 16 个不同的值,而 BCD 只有 10 个。当你用十进制进行数学运算时,如果一个数字大于 10,你需要取 10 的模数并进位到下一行。同样,在 BCD 数学中,当加法的结果大于 9 时,您加 6 以跳过剩余的 6 个“无效”值并进位到下一位。相反,您在减法中减去 6。

例如:27 + 36

  27: 0010 0111
+ 36: 0011 0110
───────────────
5_13: 0101 1101 (13 >= 10)
+  6:      0110
───────────────
  63: 0110 0011 (13 + 6 = 19 = 0x13, where 0x3 is the units digit and 0x10 is the carry)

解压加法是一样的,只是你直接从个位进位到十位,丢弃每个字节的前半字节

有关更多信息,您可以阅读


有人能解释一下英特尔指令集手册中的 AAM、AAD 和小数调整指令伪代码吗,它们为什么会这样,它们背后的逻辑是什么?

AAM 只是从二进制到 BCD 的转换。您通常以二进制进行乘法运算,然后调用 AAM 将结果除以 10 并将商余数对存储在两个未压缩的 BCD 字符中

例如:

13*6 = 78 = 0100 1110
78/10 = 7 remains 8 => result = 0x78

AAD 是相反的:在除法之前,您调用 AAD 将其从 BCD 转换为二进制,并像其他二进制除法一样进行除法

例如:87/5

0x8*10 + 0x7 = 0x57
0x57/5 = 0x11 remains 0x7

这些指令的原因是因为过去,内存很昂贵,您必须尽可能减少内存使用量。因此,在那个时代,CISC CPU 非常普遍。他们使用大量复杂的指令来最小化用于执行任务的指令。现在内存要便宜得多,现代架构几乎是 RISCy,需要权衡 CPU 复杂性和代码密度

于 2014-06-07T02:28:09.613 回答
0

我写了一个程序来帮助理解 AAA After Addition。

.model small
.data
a db '1234'
len1 db $-a
b db '9876'
len2 db $-b
result db 05 dup(?)
len3 db $-result  

.code
main proc near
mov ax,@data
mov ds,ax
                    
lea bx,a
add bl,len1
mov si,bx

lea bx,b
add bl,len2
mov di,bx

dec si
dec di
dec len3
           
lea bx,result
add bl,len3
             
mov cl,len1  
mov ax,0h

l1:                            
mov al,[si]
mov dl,[di]
cmp ah,00h
je skip 
mov ah,0h
inc al                
skip:
    add al,dl
    aaa    
    or al,30h
    mov [bx],al
    dec bx 
    dec si
    dec di
    loop l1 
cmp ah,00h
je over
mov [bx],31h
jmp finish
over:
mov [bx],30h

finish:
        
mov ax,04ch
int 21h
endp 
end

现在正如您在“add”指令之后的程序中看到的那样,我们使用“aaa”将数字转换为 ASCII(30-39 对应于 0-9)。所以写出真正的输出,我们实际上需要将它恢复为十六进制,因为我们正在接受答案的“或”。现在使用“si”和“di”,我们将一个一个地加载数字并检查是否有进位,当我们执行“aaa”时我们会知道,因为当 digit 大于 9 时它将生成 digit ah,所以我们将“inc一个接一个。看看下面的“aaa”是如何工作的。

  AAA (ASCII Adjust after Addition)
  if low nibble of AL > 9 or AF = 1 then:
  AL = AL + 6  
  AH = AH + 1  
  AF = 1  
  CF = 1  
  else 
  AF = 0  
  CF = 0  
  in both cases: 
  clear the high nibble of AL. 

有关更多与 ASCII 加法、减法、乘法和除法相关的程序,请查看此链接。GitHub

于 2020-10-08T17:05:59.113 回答