汇编语言:adc指令 和 sbb指令

一. abc 指令

        adc (add carry)是带向假想的更高位进位加法指令,它利用了标志寄存器上 CF 标志位记录的进位值。

指令格式:adc 操作对象1, 操作对象2

功能:操作对象1 = 操作对象1 + 操作对象2 + CF

比如,指令:adc ax, bx        ;(ax) = (ax) + (bx) + CF

CPU 提供 adc 指令的目的是用 adc 指令和 add 指令相配合,从而可以对更大的数据进行加法运算。

比如,以下指令实现的效果和 add ax, bx 是一样的

add al, bl        ;

adc ah, bh      ;(ah) = (ah) + bh + CF (CF的值为 add al, bl 指令执行后,设置的值)

比如,ax = 0191h,bx = 0283h

add ax, bx         ;(ax) = (ax) + (bx) = 0191h + 0283h = 0414h

用以下指令进行计算实现的效果是一样的

add al, bl        ;(al) = (al) + (bl) = 91h + 83h = 14h, CF = 1(向更高位进位了,所以 CF = 1)

adc ah, bh      ;(ah) = (ah) + (bh) + CF = 01h + 02h + 1 = 04h

最后,ax = 0414h 

1. 编程,计算 1EF000h + 201000h,结果放在 ax(高16位)和 bx(低16位)中
(1)分析

        因为两个数都大于16位,只用 add 指令无法进行计算,所以,应该用 add 指令和 add 指令配合,进行更大数据的加法运算。

    mov bx, 0F000h   ;低16位
    add bx, 1000h      ;低16位, (bx) = (bx) + 1000h = 0F000h + 1000h = 0000h, CF = 1
    mov ax, 001Eh         ;高16位,mov是传送指令,不会对标志寄存器产生影响
    adc ax, 0020h          ;高16位,(ax) = (ax) + 0020h + CF = 001Eh + 0020h + 1 = 003Fh

(2)代码
;编程,计算 1EF000h + 201000h,结果放在 ax(高16位)和 bx(低16位)中
assume cs:code
code segment
start:
    mov bx, 0F000h      ;低16位
    add bx, 1000h       ;低16位
    mov ax, 001Eh         ;高16位,mov是传送指令,不会对标志寄存器产生影响
    adc ax, 0020h         ;高16位,(ax) = (ax) + 0020h + CF = 001Eh + 0020h + 1 = 003Fh

    mov ax, 4c00h
    int 21h
code ends
end start

2. 写一个子程序,对两个 128 位数据进行相加

名称:add128

功能:两个 128 位数进行相加

参数:ds:si 指向存储第一个数的内存空间,128 位数,需要 8 个字单元,由低地址单元到高地址单元依次存放 128 位数据从低到高的 8 个字单元。运算结果存储在第一个数的存储空间中。ds:di 指向存储第二个数的内存空间。

返回:无

(1)分析

        因为两个数都大于16位,用 add 指令无法进行计算,所以,应该用 adc 指令,进行更大数据的加法运算。

(2)代码
assume cs:code, ds:data
data segment
    dw 8888h,7777h,6666h,5555h,4444h,3333h,2222h,1111h
    dw 8888h,7777h,6666h,5555h,4444h,3333h,2222h,1111h
data ends
code segment
start:
    ;初始化数据段
    mov ax, data
    mov ds, ax

    mov si, 0   ;指向第一个数的首地址
    mov di, 16  ;指向第二个数的首地址
    call add128

    mov ax, 4c00h
    int 21h

;名称:add128
;功能:两个 128 位数进行相加
;参数:ds:si 指向存储第一个数的内存空间,128 位数,需要 8 个字单元,由低地址单元到高地址单元
;     依次存放 128 位数据从低到高的 8 个字单元。运算结果存储在第一个数的存储空间中。ds:di 指向存储第二个数的内存空间。
;返回:无
add128:
    push bp     ;保护原bp状态
    mov bp, sp  ;设置栈帧的栈顶基址
    ;保护子程序用到的原寄存器状态
    push ax
    push cx
    push si
    push di

    sub ax, ax  ;将CF设置为0
    mov cx, 8   ;8个字单元
s:
    mov ax, [si]    ;mov是传送指令,不影响标志寄存器的状态
    adc ax, [di]    ;(ax) = (ax) + ds:[di] + CF
    mov [si], ax
    inc si          ;inc指令不影响标志寄存器的状态,不能用 add si, 2 这条指令替代 inc si; inc si
    inc si
    inc di
    inc di
    loop s

    pop di
    pop si
    pop cx
    pop ax
    pop bp
    ret

code ends
end start

在子程序的循环中

第一个字单元相加时:

mov ax, 8888h

adc ax, 8888h        ;ax = 8888h + 8888h + CF = 1110h + 0 = 1110h,CF = 1

第二个字单元相加时:

mov ax, 7777h

adc ax, 7777h        ;ax = 7777h + 7777h + CF = 7777h + 7777h + 1 = EEEFh, CF = 0

第三个字单元相加后:ax = CCCCh, CF = 0

第四个字单元相加后:ax = AAAAh, CF = 0

第五个字单元相加后:ax = 8888h, CF = 0

第六个字单元相加后:ax = 6666h, CF = 0

第七个字单元相加后:ax = 4444h, CF = 0

第八个字单元相加后:ax = 2222h, CF = 0

所以,结果为:2222 4444 6666 8888 AAAA CCCC EEEF 1110h,跟截图中的子程序执行后的结果一致。

二. sbb 指令

        sbb (sub borrow)是带向假想的更高位借位减法指令,它利用了标志寄存器上 CF 标志位记录的进位值。

指令格式:sbb 操作对象1, 操作对象2

功能:操作对象1 = 操作对象1 - 操作对象2 - CF

比如,指令:sbb ax, bx        ;(ax) = (ax) - (bx) - CF

CPU 提供 sbb 指令的目的是用 sbb 指令和 sub 指令相配合,从而可以对更大的数据进行减法运算。

比如,以下指令实现的效果和 sub ax, bx 是一样的

sub al, bl        ;

sbb ah, bh      ;(ah) = (ah) - bh - CF (CF的值为 sub al, bl 指令执行后,设置的值)

比如,ax = 0001h,bx = 0002h

sub ax, bx         ;(ax) = (ax) - (bx) = 0001h - 0002h = FFFFh,CF = 1

用以下指令进行计算实现的效果是一样的

sub al, bl        ;(al) = (al) - (bl) = 01h - 02h = FFh, CF = 1(向假想的更高位借位了,所以 CF = 1)

sbb ah, bh      ;(ah) = (ah) - (bh) - CF = 00h - 00h - 1 = FFh,CF = 1

最后,ax = FFFFh 

1. 编程,计算 201000h - 1EF000h,结果放在 ax(高16位)和 bx(低16位)中
(1)分析

        因为两个数都大于16位,只用 sub 指令无法进行计算,所以,应该用 sub 指令和 sbb 指令配合,进行更大数据的减法运算。

    mov bx, 1000h       ;低16位
    sub bx, 0F000h      ;低16位, (bx) = (bx) - 0F000h = 1000h - 0F000h = 2000h, CF = 1
    mov ax, 0020h       ;高16位,mov是传送指令,不会对标志寄存器产生影响
    sbb ax, 001Eh        ;高16位,(ax) = (ax) - 001Eh - CF = 0020h - 001Eh - 1 = 0001h,CF = 0

(2)代码
;编程,计算 201000h - 1EF000h,结果放在 ax(高16位)和 bx(低16位)中
assume cs:code
code segment
start:
    mov bx, 1000h       ;低16位
    sub bx, 0F000h      ;低16位, (bx) = (bx) - 0F000h = 1000h - 0F000h = 2000h, CF = 1
    mov ax, 0020h       ;高16位,mov是传送指令,不会对标志寄存器产生影响
    sbb ax, 001Eh       ;高16位,(ax) = (ax) - 001Eh - CF = 0020h - 001Eh - 1 = 0001h,CF = 0

    mov ax, 4c00h
    int 21h
code ends
end start

        

tips:

CF(Carry Flag):进位标志位,它一般记录了在做加法运算时,从最高有效位向更高位进位了,或做减法运算时,最高有效位向更高位借位了。

CY(Carried Yes)= 1:有进位或有借位

NC(Not Carried)= 0:没进位或没借位

2. 写一个子程序,对两个 128 位数据进行相减

名称:sub128

功能:两个 128 位数进行相减

参数:ds:si 指向存储第一个数的内存空间,128 位数,需要 8 个字单元,由低地址单元到高地址单元依次存放 128 位数据从低到高的 8 个字单元。运算结果存储在第一个数的存储空间中。ds:di 指向存储第二个数的内存空间。

返回:无

(1)分析

        因为两个数都大于16位,用 sub 指令无法进行计算,所以,应该用 sbb 指令,进行更大数据的减法运算。

(2)代码
assume cs:code, ds:data
data segment
    dw 8888h,7777h,6666h,5555h,4444h,3333h,2222h,1111h
    dw 9999h,7777h,6666h,5555h,4444h,3333h,2222h,1111h
data ends
code segment
start:
    ;初始化数据段
    mov ax, data
    mov ds, ax

    mov si, 0   ;指向第一个数的首地址
    mov di, 16  ;指向第二个数的首地址
    call sub128

    mov ax, 4c00h
    int 21h

;名称:sub128
;功能:两个 128 位数进行相减
;参数:ds:si 指向存储第一个数的内存空间,128 位数,需要 8 个字单元,由低地址单元到高地址单元
;     依次存放 128 位数据从低到高的 8 个字单元。运算结果存储在第一个数的存储空间中。ds:di 指向存储第二个数的内存空间。
;返回:无
sub128:
    push bp     ;保护原bp状态
    mov bp, sp  ;设置栈帧的栈顶基址
    ;保护子程序用到的原寄存器状态
    push ax
    push cx
    push si
    push di

    sub ax, ax  ;将CF设置为0
    mov cx, 8   ;8个字单元
s:
    mov ax, [si]    ;mov是传送指令,不影响标志寄存器的状态
    sbb ax, [di]    ;(ax) = (ax) - ds:[di] - CF
    mov [si], ax
    inc si          ;inc指令不影响标志寄存器的状态,不能用 add si, 2 这条指令替代 inc si; inc si
    inc si
    inc di
    inc di
    loop s

    pop di
    pop si
    pop cx
    pop ax
    pop bp
    ret

code ends
end start

在子程序的循环中

第一个字单元相减时:

mov ax, 8888h

sbb ax, 9999h        ;ax = 8888h - 9999h - CF = EEEFh - 0 = EEEFh,CF = 1

第二个字单元相减时:

mov ax, 7777h

sbb ax, 7777h        ;ax = 7777h - 7777h - CF = 0h - 1 = FFFFh,CF = 1

。。。

。。。

第八个字单元相减时:

mov ax, 1111h

sbb ax, 1111h        ;ax = 1111h - 1111h - CF = 0h - 1 = FFFFh, CF = 1

所以,结果为:0FFFF FFFF FFFF FFFF FFFF FFFF FFFF EEEFh,跟截图中的子程序执行后的结果一致。

参考书籍:

《汇编语言(第4版)》- 王爽

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值