7.5  扩展加法和减法

扩展精度的假发和减法是指任意尺寸大小数字的加法和减法。例如要求你写一个C++程序,把两个1024位的整数相加,解决方案可不是那么简单!但在汇编语言中,ADC(带进位加)指令和SBB(带进位减)指令非常适合于解决此类问题。

7.5.1  ADC指令

ADC(AddWithCarry)指令把源操作数、目的操作数以及进位标志相加。指令格式与MOV指令是一样的:

ADC  reg ,reg

ADC  mem ,reg

ADC  reg ,mem

ADC  mem ,imm

ADC  reg ,imm

例如,下面的指令把两个8位整数相加(FFh+FFh),16位解雇01FEh被存放在DL:AL中:

mov  dl ,0

mov  al ,0FFh

add   al ,0FFh   ;AL = FE

adc   dl ,0      ;DL = 01

两个32位整数相加(FFFFFFFFh+FFFFFFFFh)相加,在EDX:EAX中存放64位的和0000001FFFFFFFEh:

mov  edx ,0

mov  eax ,0FFFFFFFFh

add   eax ,0FFFFFFFFh

adc   edx ,0


7.5.2  扩展加法的例子

下面的Extended_Add过程把两个任意相同尺寸的整数相加,程序使用一个循环把没对双字相加,保存进位标志,并是仅为标志参与后面的双字的假发运算:

下面摘自ExtAdd.asm的程序片段调用了Extended_Add过程,例子中传递的是两个64位整数。注意特别分配了额外的双字节以保存可能出现的进位值:

果真发生了进位,注意一个问题,就是比如op1 QWORD 0A2B2A40674981234h

eax  =  OFFSET op1

那么[eax] 是74981234h  而[eax+4]是0A2B2A406。一开始我在最后输出的时候没看懂,后台调试的时候想起来了。

 

7.5.3  SBB指令

SBB(subtract with borrow)指令从墓地操作数中减去源操作数和进位标志的值。指令允许你的操作与ADC是相同的。

下面的例子是执行64位的减法,把EDX:EAX设置为0000000100000000h并从中减去1,程序首先减去低32位值,进位标志将被设置,然后再减去高32位和进位标志值:

mov  edx ,1    ;高半部分

mov  eax ,0    ;低半部分

sub   eax , 1   ;减去1

sbb   edx ,0   ;减去1的高半部分(0)

EDX:EAX 中的64位差值是00000000FFFFFFFFh。

7.6  ACCII和未压缩十进制算术指令

到现在为止,本书讲述的整数算术指令都是处理二进制数值的,尽管CPU是以二进制算术方式进行运算的,但是也能处理ASCII十进制数串的算术运算。后者可以方便地有用户输出并在控制台窗口中显示,无需转换成二进制数值。假设程序需要用户输入两个数字并把他们相加,下面是一个输出样例,其中用书输入了3402和1256:

Enter first numbers:    3402

Enter second number:  1256

The sum is:           4658

在计算和显示数字的时候有两种选择:

1.把两个操作数转换成二进制数值并相加,然后把和从二进制数转换成ASCII码数字串的格式化后显示。

2.连续地把没对ASCII数字直接相加,这样就和是ASCII数字串,可以直接在屏幕上显示。

第二种选择要求在对ASCII数字相加后使用特殊指令来调整其和,指令集中有4条指令可以处理这一类的ASCII加法、减法、乘法和除法:

mov    ah ,0

mov    al ,’8’     ;AX = 0038h

add     al,’2’     ;AX = 006Ah

aaa              ;AX = 0100h(结果的ASCII码调整)

or      ax ,3030h ;AX = 3130h=’10’(转换成ACSCII码)

AAS AAM AAD也是如此。

7.7.1  DAA指令

DAA指令把ADD和ADC指令执行后AL中的二进制数转换成压缩的十进制数格式。

mov  al ,35h

add  al ,48h    ;AL = 7Dh

daa            ;AL = 83h(调整结果)

7.7.2  DAS指令

DAS(decimal adjust after subtraction)指令将SUB或SBB指令执行后AL中的二进制转换成压缩的十进制格式。

mov bl ,48h

mov al ,85h

sub al ,bl   ;AL = 3Dh

das       ;AL = 37h(调整结果)

7.8 本章小结

最新文章

  1. [问题2014A04] 解答
  2. 检索 COM 类工厂中 CLSID 为 {13C28AD0-F195-4319-B7D7-A1BDAA329FB8} 的组件时失败,原因是出现以下错误: 80040154
  3. [Java] 字符流 Writer,输出字符数据PrintWriter
  4. 求bat文件创建mysql数据库,并调用一个SQL文件的代码
  5. centos 7搭建vpn(pptpd)服务器 (只限centos 7)
  6. Table of Contents - Redis
  7. c++中类长度解析
  8. Linux以及Android开发中的小技巧和长繁命令记录收集
  9. c# List<string>和List<int>互相转换
  10. javascript模仿块级作用域(第一篇)
  11. 优雅的使用sublime写lua~ sublime lua相关必装插件推荐~~
  12. iOS网络编程笔记——Socket编程
  13. 关于ZendStudio 10.5的破解 包括mac
  14. 几条jQuery代码片段助力Web开发效率提升
  15. android基础-界面开发注意事项
  16. Java3y文章目录导航
  17. Hadoop MapReduce2.0(Yarn)
  18. JSON Support in PostgreSQL and Entity Framework
  19. C# 8中的Async Streams
  20. angular ng-repeat元素swiper无法滑动问题解决

热门文章

  1. 大括号之谜:C++的列表初始化语法解析
  2. 翻译:《实用的Python编程》04_03_Special_methods
  3. [MongoDB知识体系] 一文全面总结MongoDB知识体系
  4. Go语言学习笔记——Go语言的make的理解
  5. Masterwoker模式
  6. JS 字符数组和数字数组转换
  7. unbutu系统扩展磁盘大小
  8. 3、MyBatis教程之CURD操作
  9. ASPOSE.Cells & ASPOSE.Words 操纵Excel和Word文档的 .NET Core 实例
  10. (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)