【新书推荐】8.2节 算术运算加减法指令

本节内容:算术运算加法和减法指令。

加法指令:ADD、ADC、INC指令,示例代码inc.asm、add.asm。

减法指令:SUB、SBB、DEC指令,示例代码dec.asm、sub.asm。

8086计算机提供了加减乘除四种基本算术运算操作指令。可以用于字节或字的运算。操作数可以是无符号整数也可以是有符号整数。有符号数以补码形式表示。加减指令不分有符号数指令和无符号数指令。乘除指令分有符号数指令和无符号数指令。

此外,我们在第十八章学习十进制算术运算调整指令。

加减运算指令的说明

(1)有符号整数和无符号整数处理一视同仁,影响标志位:CF、AF、OF、SF、ZF、PF。

(2)可参与加减运算的操作数只有通用寄存器和存储单元可以存放运算结果,如果参与运算的操作数有2个,只有一个用于存放结果。

(3)操作数如果有两个,它们的类型必须一致,即同时为字节或字。

(4)如图8-5所示,存储器操作数可采用四种存储器操作数寻址方式。[BX+SI+位移量]4种组合,即[BX+SI]、[BX+位移量]、[SI]、[位移量]。

图8-5 参与加减运算的操作数

8.2.1 加法指令

普通加法指令ADD

指令格式:ADD OPRD1,OPRD2 OPRD1=OPRD1+OPRD2

动手实验25 :普通加法指令ADD

如图8-6所示,在debug调试器内输入:

MOV AX,7896H ;AX=7896H,AH=78H,AL=96H ;mov指令不影响标志位

ADD AL,AH ;AL=0EH,AH=78H,AX=780EH ;CF=1,ZF=0,SF=0,OF=0,AF=0,PF=0

ADD AH,AL ;AH=86H,AL=0EH,AX=860EH ;CF=0,ZF=0,SF=1,OF=1,AF=1,PF=0

ADD AL,0F2H ;AL=00H,AH=86H,AX=8600H ;CF=1,ZF=1,SF=0,OF=0,AF=1,PF=1

ADD AX,1234H ;AX=9834H,AH=98H,AL=34H ;CF=0,ZF=0,SF=1,OF=0,AF=0,PF=0

a命令输入上述指令后,输入t命令单步执行,观察加法运算的结果,并注意观察flag标志寄存器各个状态标志位的变化。

提示

FLAG标志寄存器的状态标志位(CF、AF、PF、ZF、SF、OF)用于记录算术逻辑运算指令的结果。这些状态标志位不仅关系到算术逻辑运算结果的正确性,而且还是我们作为条件判断的依据。我们将在"8.6 节程序控制指令"中详细讲解。

图8-6 ADD加法指令

带进位加法指令ADC

指令格式:ADC OPRD1,OPRD2 ; OPRD1=OPRD1+OPRD2+CF

例如: mov ax,2 mov ax,1 mov al,98h

mov bx,1 add ax,ax add al,al

sub bx,ax adc ax,3 adc al,3

adc ax,1

动手实验26 :带进位加法指令ADC

如图8-7所示,在debug调试器内输入第一组汇编指令:

图8-7 ADC指令

剩余两组指令留给读者独立完成。

举例

ADC 指令用于多字节运算中。

编程计算:1ef000h+201000h,结果存放在AX高16位和BX低16位。

mov ax,001eh

mov bx,0f000h

add bx,1000h

adc ax,0020h

加1 指令INC

指令格式:INC OPRD ; OPRD=OPRD+1

该指令主要用于调整地址指针和计数器,INC 指令不影响CF 标志位。

动手实验27 :INC 指令

按照下列要求,编写一个inc.asm源程序,并完成编译链接,生成inc.exe可执行程序,并在debug调试器中单步跟踪执行。

假设有100个16位无符号数存放在1234:5678H开始的内存中,现需要求它们的和。设把32位的和保存在DX(高位)和AX寄存器中。

示例代码3

;程序名inc.asm

;演示inc指令的使用方法

;==============================================

assume cs:code

code segment

start:

mov ax,1234h

mov ds,ax ;置数据段寄存器

mov si,5678h ;置指针初值

mov ax,0 ;清32位累加和,ax保存低16位值

xor dx,dx ;dx保存高16位值

mov cx,100 ;置数据个数计数器

next:

add ax,[si] ;求和

adc dx,0 ;加上可能的进位值

inc si ;调整指针

inc si

dec cx ;计数器减1

jnz next ;如果不为0,继续累加下一个数据

;退出程序

mov ax,4c00h

int 21h

code ends

end start

请读者参阅第五章16位汇编学习环境,在Notepade++中抄写此程序。如图8-8所示,编译链接生成可以执行文件inc.exe。然后在调试器中调试,单步跟踪,完成程序的运行。

图8-8 INC指令

动手实验28 :加法运算

按照下列要求,编写一个add.asm源程序,并完成编译链接,生成add.exe可执行程序,并在debug调试器中单步跟踪执行。

假设有100个16位无符号数存放在1234:5678H开始的内存中,现需要求它们的和。设把32位的和保存在result变量中。

示例代码4

;程序名:add.asm

;功能:计算1234:5678H开始的内存中100个16位无符号整数的和

;注意有进位值,结果保存到result变量中

;======================================================

assume cs:code,ds:data

data segment

result dd ?

data ends

code segment

start:

mov ax,1234h ;取段值

mov ds,ax

;

mov si,5678h ;取偏移

;dx:ax 清零,保存32位累加和

mov ax,0

xor dx,dx ;CF位清零

;

mov cx,100 ;循环次数

next:

add ax,word ptr [si];取一个字

adc dx,0 ;带进位的加法运算

;inc si

;inc si

add si,2 ;si指向下一个字,等同于上面两条语句

dec cx

jnz next ;跳转到next地址处

;切换数据段

mov bx,data

mov ds,bx

;保存结果

mov word ptr result,ax

mov word ptr result+2,dx

;退出程序

mov ax,4c00h

int 21h

code ends

end start

注意示例代码4中的ADC指令,带进位的加法运算时需要注意提前将CF位清零。"xor dx,dx"语句中的xor指令为常用的清CF位指令,将dx清零的同时,CF清零。除了xor指令之外,请读者思考还有哪些指令可以将CF位清零。

8.2.2 减法指令

普通减法指令SUB

指令格式:SUB OPRD1,OPRD2 OPRD1=OPRD1-OPRD2

动手实验29 :普通减法指令SUB

如图8-9所示,在debug调试器内输入:

MOV BX,1048H ;BX=1048H,BH=10H,BL=48H ;mov指令不影响标志位

SUB BH,BL ;BH=C8H,BL=48H,BX=C848H ;CF=1,ZF=0,SF=1,OF=0,AF=1,PF=0

SUB BL,BH ;BL=80H,BH=C8H,BX=C880H ;CF=1,ZF=0,SF=1,OF=1,AF=0,PF=0

SUB BL,9 ;BL=77H,BH=C8H,BX=C877H ;CF=0,ZF=0,SF=0,OF=1,AF=1,PF=1

SUB BX,1234H ;BX=B643H,BH=B6H,BL=43H ;CF=0,ZF=0,SF=1,OF=0,AF=0,PF=0

图8-9 SUB指令

带进位减法指令SBB

指令格式:SBB OPRD1,OPRD2 ; OPRD1=OPRD1-OPRD2-CF

动手实验30 :带进位减法指令SBB

计算003E1000H-00202000H,结果放在AX,BX中:

如图8-10所示,在debug调试器内输入:

mov bx,1000h

mov ax,003eh

sub bx,2000h

sbb ax,0020h

图8-10 SBB指令

减1 指令DEC

指令格式:DEC OPRD ;OPRD=OPRD-1

该指令主要用于调整地址指针和计数器,DEC 指令不影响CF 标志位。

动手实验31 :DEC 指令

按照下列要求,编写一个dec.asm源程序,并完成编译链接,生成dec.exe可执行程序,并在debug调试器中单步跟踪执行。

假设有两个64位数按高高低低原则存放同一个段的两个缓冲区DATA1和DATA2,现计算DATA1-DATA2。结果存放在RESULT中,可能发生的借位保留在CF中:

示例代码5

;程序名dec.asm

;演示dec指令的使用方法

;==============================================

assume cs:code,ds:data

data segment

DATA1 dq 0FEDCBA9876543210h ;16进制数字符A~F开头需添加前缀0

DATA2 dq 123456789ABCDEFh

RESULT dq ?

data ends

code segment

start:

mov ax,data

mov ds,ax

mov cx,4 ;64位分成4个字

sub bx,bx ;清指针,同时清CF

next:

mov ax,word ptr data1[bx] ;取减数

sbb ax,word ptr data2[bx] ;带进位减

mov word ptr RESULT[bx],ax ;保存结果

inc bx ;调整指针,指向下一个字节

inc bx

dec cx ;计数器减1

jnz next ;没完,继续

;退出程序

mov ax,4c00h

int 21h

code ends

end start

请读者参阅第五章 16 位汇编学习环境,在Notepade++中抄写此程序。如图8-11所示,编译链接生成可以执行文件dec.exe。然后在调试器中调试,单步跟踪,完成程序的运行。

图8-11 DEC指令

动手实验32 :长整数减法运算

按照下列要求,编写一个sub.asm源程序,并完成编译链接,生成sub.exe可执行程序,并在debug调试器中单步跟踪执行。

假设有两个64位数按高高低低原则存放同一个段的两个缓冲区DATA1和DATA2,现计算DATA1-DATA2。结果存放在RESULT中,可能发生的借位保留在CF中:

示例代码6

;程序名:sub.asm

;功能:两个64位数按照高高低低的原则分别存放在DATA1和DATA2两个缓冲区

;计算DATA1-DATA2

;DATA1 = 2000156781234

;DATA2 = 1000212345678

;=================================

assume cs:code,ds:data

data segment

data1 dw 6AB2H,0B2A2H,01D1H,0

data2 dw 334EH,0E14DH,00E8H,0

result dw ?,?,?,?

data ends

code segment

start:

mov ax,data

mov ds,ax

;

xor si,si ;si清零

mov cx,4 ;循环次数

next:

mov ax,data1[si] ;data1取一个字

sbb ax,data2[si] ;减去data2一个字

mov result[si],ax ;保存结果

inc si ;指向下一个字节

inc si ;指向下一个字节

dec cx ;循环次数减一

jnz next ;ZF为0,跳转到next地址处继续循环

;退出程序

mov ax,4c00h

int 21h

code ends

end start

注意

上述示例代码中,长整数data1和data2给出的是十进制数。在数据段的数据定义中,长整数的存储顺序为低地址存储低位数,高地址存储高位数。

请读者将长整数按照低地址存储高位数,高地址存储低位数的方式重写sub.asm程序,并在debug调试器中验证结果的正确性。

求补指令NEG

指令格式:NEG OPRD ;OPRD==0-OPRD

该指令用于对操作数取补,就是用零减去操作数OPRD,在把结果送回OPRD。

例:NEG AL NEG [SI]

如在字节操作时对-128取补,或字操作时对-32768取补,则操作数没有变化,但OF被置位。操作数可以是8位或16位寄存器或存储单元。影响CF、ZF、SF、OF、AF、PF,一般总使CF置1,除非操作数为0。

动手实验33 :取补指令NEG

如图8-12所示,在debug调试器内输入如下指令,注意观察状态标志位的变化:

mov ax,0ffffh

neg ax

mov ax,1h

neg ax

mov ax,8000h

neg ax OF=1,CF=1

图8-12 NEG指令

比较指令CMP

指令格式:CMP OPRD1,OPRD2

该指令完成操作数OPRD1减去操作数OPRD2,运算结果不保存,但影响标志CF、ZF、OF、AF、SF、PF。

主要用于比较两个数的关系,是否相等,根据ZF是否置位,判断是否相等;

如果两个操作数是无符号数,则根据CF判断大小;

如果两个操作数是有符号数,则根据OF位判断大小;

动手实验34 :比较指令CMP

如图8-13所示,在debug调试器内输入如下汇编指令,注意观察状态标志位的变化:

mov ax,8

mov bx,3

cmp ax,bx

执行后,(ax)=8,zf=0,pf=1,sf=0,cf=0,0f=0。

图8-13 CMP指令

相关推荐
一只特立独行的程序猿17 分钟前
关于GCC内联汇编(也可以叫内嵌汇编)的简单学习
汇编·学习·gcc
染指11101 天前
45.第二阶段x86游戏实战2-hook监控实时抓取游戏lua
汇编·c++·windows·反游戏外挂·游戏逆向
ARM&开发(Haidong)1 天前
ARM 汇编指令
汇编
CYRUS STUDIO2 天前
Android 下内联汇编,Android Studio 汇编开发
android·汇编·arm开发·android studio·arm
我不是程序猿儿3 天前
【数据结构】汇编 、机器语言 高级语言 简析。
汇编·机器语言·高级语言
zhuqiyua3 天前
c文件的编译,汇编,基础知识
c语言·汇编·算法
CYRUS STUDIO4 天前
Android下的系统调用 (syscall),内联汇编syscall
android·linux·汇编·arm开发·arm·内联汇编
linhhanpy5 天前
自制操作系统(九、操作系统完整实现)
c语言·开发语言·汇编·c++·操作系统·自制操作系统
CYRUS STUDIO6 天前
ARM64汇编寻址、汇编指令、指令编码方式
android·汇编·arm开发·arm·arm64
xiaozhiwise7 天前
ARM base instruction -- ccmp (immediate)
汇编