Intel汇编程序设计-整数算术指令(下)
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 本章小结
最新文章
- [问题2014A04] 解答
- 检索 COM 类工厂中 CLSID 为 {13C28AD0-F195-4319-B7D7-A1BDAA329FB8} 的组件时失败,原因是出现以下错误: 80040154
- [Java] 字符流 Writer,输出字符数据PrintWriter
- 求bat文件创建mysql数据库,并调用一个SQL文件的代码
- centos 7搭建vpn(pptpd)服务器 (只限centos 7)
- Table of Contents - Redis
- c++中类长度解析
- Linux以及Android开发中的小技巧和长繁命令记录收集
- c# List<;string>;和List<;int>;互相转换
- javascript模仿块级作用域(第一篇)
- 优雅的使用sublime写lua~ sublime lua相关必装插件推荐~~
- iOS网络编程笔记——Socket编程
- 关于ZendStudio 10.5的破解 包括mac
- 几条jQuery代码片段助力Web开发效率提升
- android基础-界面开发注意事项
- Java3y文章目录导航
- Hadoop MapReduce2.0(Yarn)
- JSON Support in PostgreSQL and Entity Framework
- C# 8中的Async Streams
- angular ng-repeat元素swiper无法滑动问题解决
热门文章
- 大括号之谜:C++的列表初始化语法解析
- 翻译:《实用的Python编程》04_03_Special_methods
- [MongoDB知识体系] 一文全面总结MongoDB知识体系
- Go语言学习笔记——Go语言的make的理解
- Masterwoker模式
- JS 字符数组和数字数组转换
- unbutu系统扩展磁盘大小
- 3、MyBatis教程之CURD操作
- ASPOSE.Cells &; ASPOSE.Words 操纵Excel和Word文档的 .NET Core 实例
- (数据科学学习手札115)Python+Dash快速web应用开发——交互表格篇(上)