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

news2024/11/16 7:28:29

一. 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版)》- 王爽

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2067421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2升级Vue3填坑笔记

背景 前段时间使用Vue2完成一个流量回放的前端开发,实现了流量回放的基本功能。开发过程中,发现现主流的插件都在适配Vue3,奈何为了赶进度,只能先用自己熟悉的Vue2先顶上。恰巧最近有些许空余时间,就把项目代码逐步变…

基于单片机的人体健康监测系统的设计

本设计以STM32F103C8T6单片机作为主控,通过MAX30102采集心率、血氧值,通过MSP20血压采集模块检测血压值,通过MLX90614红外体温采集模块检测体温值。OLED屏可以显示以上检测的信息,并可以通过蓝牙模块将信息发送给手机APP。当检测值…

【QAMISRA】解决永久license文件替换后未生效的问题

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决浮动版永久license文件替换后未生效的问题。 2、 问题场景 客户替换永久版license文件且重启lserv服务后,license信息还是原来临时license的信息。 3、软硬件环境 1、软件版本: QA-MIS…

Android车载蓝牙音乐实例(附Demo源码):实现手机播放音乐后车机应用显示音乐名称,歌手,专辑名。且可控制上一曲下一曲,暂停播放功能

一、功能需求 功能需求是在Android10以上设备上实现蓝牙音乐功能,细分为两个功能点: 1、手机和车载设备实现蓝牙连接 (本Demo文只做监听蓝牙连接状态,需手动到设置中连接蓝牙) 2、连接蓝牙成功后手机播放音乐时车载…

【python报错已解决】“IndexError: list index out of range”

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 你是否在处理Python列表时遇到了“IndexError: list index out of range”的错误?这个错误可能会让你的程序中…

51单片机最快能生成多高频率的方波?

前言 在嵌入式系统开发中,51 单片机作为一种非常非常非常经典,贯穿上下几十年的微控制器,被广泛应用于各种电子项目中。其中,生成特定频率的方波信号是一项常见的需求。 那么,51 单片机究竟能以多快的速度生成方波呢&…

STM32——GPS模块(GY-NEO-6M)

1连接 1-1 使用 USB-TTL 工具,安装好驱动,可以在”设备管理器看到对应COM”按照如下链接测试模块: USB-TTL GPS 模块 3.3V--------------------------------->VCC GND------------------------------>GND RXD--------------------…

应用程自定义协议与序列化反序列化

本篇将主要介绍在应用层中自定义的协议,自定义协议的同时还需要将我们的数据继续序列化和反序列化,所以本篇的重点为序列化、反序列化的原因以及如何自定义协议,接着探讨了关于为什么 tcp 协议可以支持全双工协议。还根据用户自定义协议结合 …

⼆⼿⻋交易系统前景分析

二手车交易系统开发小程序在当前市场中具有显著的优势和潜力。以下是对二手车交易系统小程序功能的综合分析: 车辆信息展示:小程序应提供详细的车辆信息展示,包括车辆的图片、品牌、型号、年份、里程数、价格等关键信息,方便用户…

Python爬虫—常用的网络爬虫工具推荐

以下列举几个常用的网络爬虫工具 1. 八爪鱼(Bazhuayu) 简介: 八爪鱼是一款面向非技术用户的桌面端爬虫软件,以其可视化操作和强大的模板库而受到青睐。它支持从各种网站上抓取数据,包括文本、图片、文档等&#xff…

特殊类设计和类型转换

前言 这一篇博客我们讲特殊类设计和类型转换 1. 特殊类设计 1.1 请设计一个类,不能被拷贝 这个比较简单 第一种方法就是将赋值和拷贝构造只定义不声明然后设置为私有就可以了 第二种方法就是直接令它为delete 1.2 请设计一个类,只能在堆上创建对象 …

自学成才:通过自学成为软件开发者——之入行成为软件开发者

一些优秀的程序员,可能以前从事的是其他职业,他们大都发现工作中的很多固定化的流程内容,如果可以实现自动化,不仅效率能够得到提高和保证,提高自己的生成力,同时自己也会从中释放出来,有更多的…

Go使用MongoDB应用指南

Go使用MongoDB应用指南 MongoDB 是一种高性能、开源、文档型的 NoSQL 数据库,广泛应用于 Web 应用、大数据以及云计算领域。Go 语言则以其快速、开发效率高、代码可维护性强著称。本指南将详细介绍如何在 Go 语言中使用 MongoDB 进行数据库操作,包括连接…

鸿蒙HarmonyOS开发知识:命令行工具Command Line Tools

该命令行工具集合了HarmonyOS应用开发所用到的系列工具,包括代码检查codelinter、三方库的包管理ohpm、命令行解析hstack、编译构建hvigorw。 命令行工具获取 请前往下载中心获取并下载命令行工具Command Line Tools。 配置环境变量 Windows 将解压后command-l…

英语四六级有多重要你不知道

卷出天际 IT业内卷严重大家都知道 因此也就打击了很多想入行的新人 到底什么是核心竞争力 放在十年前 稍微会Spring, CRUD 就能达到入门的台阶 那也是培训机构最繁荣的一段时期 而今顶峰已经过去 IT业从含金量上 已经大不如前 在野蛮发展期 如果不太挑的话 大专也是…

云轴科技ZStack AIOS平台智塔亮相FDS金融领袖峰会

人工智能(AI)正以前所未有的速度渗透到金融系统,推动着金融服务的创新和变革。这种深度融合不仅可以提高金融服务的效率和准确性,未来还可催生全新的金融产品和服务模式。尤其是生成式人工智能(GenAI)的出现…

算法的学习笔记—复杂链表的复制(牛客JZ35)

😀前言 在许多实际应用中,我们会遇到复杂链表的复制问题。复杂链表不同于一般的单链表,不仅每个节点有指向下一个节点的指针,还有一个特殊的指针 random,可以指向链表中的任意节点或 null。如何高效地复制这样一个复杂…

CACTER直播预告:聚焦EDLP邮件数据防泄露实战重点

在信息高速流通的今天,邮件作为商务沟通的桥梁,不仅承载着日常沟通,更是企业机密和知识产权的重要载体。然而,邮件系统的开放性也使其成为网络攻击的主要目标。数据泄露不仅会导致商业损失,还可能对企业声誉造成不可逆…

【请安全下载】黑神话:悟空 单机游戏 它是如何保证安全的 怎样防破解的?安全措施:D加密,反外挂,代码加密,资源保护

单机 《黑神话:悟空》是一款单机游戏,由游戏科学开发,并于2024年8月20日全球同步上线。游戏以其独特的暗黑国风、深度的故事背景以及精致的游戏画面,重塑了西游题材,为玩家呈现了一个前所未有的悟空传奇。 黑神话&…

[Linux]在Ubuntu中安装samba并且正确配置(详细)

一、我们为什么需要samba服务 samba是一种实现windows和linux包括macos文件共享的套件。它能让我们像访问自己的磁盘一样去访问别的系统的文件。可以看得出来这种一种快速并且高效的文件传输协议。看到这里,大家可能会有些疑问。向linux传输文件,我们可以…