adc 是带进位加法指令,它利用了 CF 位上记录的进位值。
指令格式:adc 操作对象 1, 操作对象 2
功能:操作对象 1 = 操作对象 1 + 操作对象 2 + CF
比如指令 adc ax,bx,实现的功能是: (ax) = (ax) + (bx) + CF
例:
mov ax,2 mov bx,1 sub bx,ax adc ax,1
执行后,(ax)=4。adc 执行时,相当于计算:(ax) = (ax) + 1 + CF = 2 + 1 + 1 = 4。
mo ax,1 add ax,ax adc ax,3
执行后,(ax)=5 adc执行时,相当于计算:(ax)+3+Cf=2+3+0=5
mov al,98h add al,al adc al,3
执行后,(al)=34H adc执行时,相当于计算:(al)+3+CF=30H+3+1=34H
可以看出,adc指令比add指令多加了一个CF位的值
为什么要加上CF的值呢?CPU为什么要提供这样一条指令呢?
先来看一下CF的值的含义。在执行adc指令的时候加上的CF的值的含义,是由adc指令前面的指令决定的,也就是说,关键在于所加上的CF值是被什么指令设置的。显然,如果CF的值是被sub指令设置的,那么它的含义就是借位值;如果是被add指令设置的,那么它的含义就是进位值。我们来看一下两个数据:0198H和0183H如何相加的:
01 98 + 01 83 1 ———————————— 03 1B
可以看出,加法可以分两步来进行:
①低位相加:
②高位相加再加上低位相加产生的进位值。
下面的指令和add ax, bx具有相同的结果:
add al,bl adc ah,bh
看来CPU提供adc指令的目的,就是来进行加法的第二步运算的。adc指令和add指令相配合就可以对更大的数据进行加法运算。我们来看一个例子:
编程,计算1 EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。
因为两个数据的位数都大于16,用add指令无法进行计算。我们将计算分两步进行,
先将低16位相加,
然后将高16位和进位值相加。
程序如下:
mov ax,001EH mov bx,0F000H add bx,1000H adc ax,0020H
adc 指令执行后,也可能产生进位值,所以也会对 CF 位进行设置。由于有这样的功能,我们就可以对任意大的数据进行加法运算。看一个例子:
编程,计算1EF0001000H+2010001EFOH,结果放在ax(最高16位),bx(次高16位),cx(低16位)中。
计算分3步进行:
(1)先将低16位相加,完成后,CF中记录本次相加的进位值;
(2)再将次高16位和CF(来自低16位的进位值)相加,完成后,CF中记录本次相加的进位值;
(3)最后高16位和CF(来自次高16位的进位值)相加,完成后,CF中记录本次相加的进位值。
程序如下:
mov ax,001EH mov bx,OF000H mov cx,1000H add cx,lEFOH adc bx,1000H adc ax,0020H
编写一个子程序,对两个 128 位数据进行相加。
名称:add128
功能:两个 128 位数据进行相加。
参数:ds:si 指向存储第一个数的内存空间,因数据为 128 位,所以需要 8 个字单元,由低地址单元到高地址单元依次存放 128 位由低到高的各个字。运算结果存储在第一个数的存储空间中。
ds:di 指向存储第二个数的内存空间。
程序如下:
add128: push ax push cx push si push di sub ax,ax ;将 CF 设置为 0 mov cx,8 s:mov ax,[si] adc ax,[di] mov [si],ax inc si inc si inc di inc di loop s pop di pop si pop cx pop ax ret
inc和loop指令不影响CF位,思考一下,上面的程序中,能不能将4个inc指令,用
add si ,2 add di,2
来取代?