microcomputer_principle_05_算术运算和逻辑运算
Carpe Tu Black Whistle

算术运算类指令

  • 加法运算指令
  • 减法运算指令
  • 乘法指令
  • 除法指令

不同于数据数据传送类指令
算术运算类指令,执行大多对状态标志位会产生影响


加法指令

  • 普通加法指令 ADD
  • 带进位位的加法指令ADC
  • 加1指令INC

ADD

  • format:
    • ADD OPRD1, OPRD2
  • manipulation:
    • OPRD1+OPRD2 –> OPRD1
  • e.g.
    • MOV AL, 78H
    • ADD AL, 99H

ADD指令的执行对全部6个状态标志位都产生影响

ADC

  • 指令格式、对操作数对要求、对标志位对影响与ADD完全一致
  • manipulation:
    • OPRD1+OPRD2+CF –> OPRD1
    • 这里的CF,是指低位运算的进位。

ADC指令多用于多字节数相加,使用前要先将CF清零

INC指令

  • format:
    • INC OPRD(不能是段寄存器,不能是立即数)
  • manipulation:
    • OPRD+1 –> OPRD

INC指令的执行不影响CF,但会影响其余5个状态标志位
常用与在程序中修改地址指针

加法指令例

按字节运算程序设计

addition

求内存数据段中M1为首和M2为首的两个20字节数之和,并将结果写入M2为首的区域中。

1
2
3
4
5
6
7
8
9
10
11
      LEA SI, M1
LEA DI, M2
MOV CX, 20
CLC ;--> make CF=0
NEXT: MOV AL, [SI]
ADC [DI], AL ; 若CF不进行初始化,首次运算可能会出现+1误操作
INC SI
INC DI
DEC CX
JNZ NEXT
HLT

按”字”运算
double-bytes

1
2
3
4
5
6
7
8
9
10
11
      LEA SI, M1
LEA DI, M2
MOV CX, 10
CLC
NEXT: MOV AX, [SI] ;使用`16bit`的AX
ADC [DI], AX
ADD SI, 2 ;间址寄存器移动两位
ADD DI, 2 ;间址寄存器移动两位
DEC CX
JNZ NEXT
HLT

减法指令

  • 普通减法指令SUB
  • 考虑借位的减法指令SBB
  • 减1指令DEC
    (以上3条与加法指令都一一对应)
  • 比较指令CMP
  • 求补指令NEG

    减法指令对操作数的要求与对应的加法指令相同


SUB指令

  • format:
    • SUB OPRD1, OPRD2
  • manipulation:
    • OPRD1-OPRD2 —-> OPRD1
    • dest-src –> dest

对标志位的影响与ADD指令相同
但是,这里涉及减数与被减数关系

SBB指令

  • 指令格式、对操作数的要求、对标志位的影响与SUB指令完全一样
  • 指令的操作:
    • OPRD1-OPRD2-CF —-> OPRD1

      SBB指令多用于两个多字节数的相减运算
      使用前,请CLEAR CARRY FLAGS–> CLC make CF=0

DEC指令

  • format:
    • DEC OPRD
  • manipulation:
    • OPRD-1 –> OPRD

指令对操作数的要求及对标志位的影响与INC相同
指令常用于在程序中修改技术值

应用程序例

1
2
3
4
5
6
7
      MOV BL, 2
NEXT1:MOV CX, 0FFFFH;当立即数的最高位为符号(A-F)
NEXT2:DEC CX ;/前面必须加上0
JNZ NEXT2 ;ZF=0转NEXT2
DEC BL
JNZ NEXT1 ;ZF=0转NEXT1
HLT ;暂停执行

NEG指令

又名为 求补指令

  • format:
    • NEG OPRD
    • OPRD (8/16bit寄存器或存储器操作数)
  • manipulation:
    • 0 - OPRD –> OPRD

对一个负数取补,就相当于用零减取次数

  • 执行NEG指令后,一般情况下都会使CF=1,除非给定的操作数为零才会使CF=0;
  • 当指定的操作数为80H(-128)或为8000H(-32768),则执行NEG指令后,结果不变,但OF置1,其它情况下OF均为0

CMP指令

  • format:
    • CMP OPRD1, OPRD2
  • manipulation:
    • OPRD1-OPRD2

指令执行的结果不影响目标操作数,仅影响标志位!

  • use to:
    • 用于比较两个数的大小,可作为条件转移指令转移的条件
    • 指令对操作数的要求及对标志位的影响与SUB指令相同

比较大小时,有符号数和无符号数,在 表述范围和数的表达形式上都不太一样,比较大小的时候,两个判定条件都不太一样。

  • 无符号数比较:
    • CMP AX, BX
    • if AXBX –> CF=0
    • if AX < BX –> CF=1
    • if AX=BX –> CF=0, ZF=1
  • 两个带符号数的比较
    • CMP AX, BX

两个数的大小由OF和SF共同决定

  • OF=SF –> AXBX
  • OFSF –> AX<BX

CMP指令例

1
2
3
4
5
6
7
8
9
10
11
12
      LEA BX, MAX
LEA SI, BUF
MOV CL, 20
MOV AL, [SI]
NEXT: INC SI
CMP AL, [SI]
JNC GOON ; CF=0 转移
XCHG [SI], AL
GOON: DEC CL
JNZ NEXT
MOV [BX], AL
HLT

maxnimum

乘法运算指令

  • 由分别针对无符号数和有符号数运算指令
    • 有不同的指令助记符
  • 乘、除运算指令均采用隐含寻址方式
  • 请注意该类指令对操作数对要求

乘法指令分为:

  • 无符号的乘法指令 MUL
  • 带符号的乘法指令 IMUL

NOTE:

乘法指令采用隐含寻址,隐含了存放被乘数的累加器AL或AX,以及存放结果的AX或AX,DX;

二进制中,两个8bit二进制数相乘,无论大小,结果一律为16bit字长
两个16bit相乘,结果为32bit字长,32bit字长要存储只能再借助DX存储器(高16位

无符号数乘法指令

  • format:
    • MUL OPRD
    • 不能是立即数
  • manipulation
    • OPRD为字节数 –> ALOPRD –> AX
    • OPRD为16bit数 –> AXOPRD –> DXAX
  • e.g.
    • MUL BYTE PTR[BX]

PTR也是指令,用BYTE来指明[BX]内容长度位1字节

MUL

有符号数乘法指令

  • format:
    • IMUL OPRD
  • 指令格式及对操作数的要求与MUL指令相同。
  • 指令执行原理:
    1. 将两个操作数取补码(对负数按位取反加1,正数不变);
    2. 做乘法运算;
    3. 将乘积取补码。

除法指令

无符号除法指令

  • format:
    • DIV OPRD

有符号除法指令

  • format:
    • IDIV OPRD

若OPRD是字节数

  • execute: AX/OPRD
  • result:
    • AL = 商 AH = 余数

若OPRD是双字节数

  • execute: DXAX/OPRD
  • result:
    • AX = 商 DX = 余数

除法运算中,被除数的长度为除数的两倍

算术运算指令小结

  • 指令执行影响状态标志位
  • 乘法指令执行结果为相乘数的双倍字长;除法指令要求被除数的双倍字长。
  • e.g.
1
2
3
4
5
MOV SI, 1200H
MOV WORD PTR[SI], 8765H
MOV AL, [SI]
INC SI
MUL BYTE PTR[SI]

以上示例代码,实现了将8765H存入1200H所指的一个字WORD的内存单元
并且实现了87H65H

  • e.g. 在上例基础上修改末3位指令
    • MOV AX, [SI]
    • MUL WORD PTR[SI]

实现了字与字的乘法8765H8765H


  • 算术运算累指令的执行会影响状态标志位。其中:

    • INC和DEC指令的执行不会影响CF
  • 该类指令中,全部双操作数指令对操作数的要求与MOV指令完全相同;所有单操作数指令都要求操作数:

    • 不能是立即数
    • 如果是存储器操作数,需要声明操作数的字长(用PTR运算符
  • 乘法运算中: 乘积是乘数的双倍字长

  • 除法指令要求被除数是除法数的双倍字长

逻辑运算

  • 基本逻辑运算:

    • 与、或、非
    • 异或
  • 逻辑运算指令 –> 实现逻辑操作的指令

  • 对操作数的要求:

    • 大多与MOV指令相同。
    • ‘非’运算指令要求操作数不能是立即数;(存储器操作数,需要声明字长)
  • 对标志位的影响

    • 除’非’运算指令,其余指令的执行都会影响除AF外的5个标志;
    • 无论结果如何,都会使标志位OF=CF=0
    • ‘非’运算指令的执行不影响标志位。

AND

  • format:
    • AND OPRD1, OPRD2
  • manipulation:
    • 两操作数相”与”,结果送目标地址。
    • AND OPRD1, OPRD2 –> OPRD1
  • use to
    • 实现两操作数按位相与的运算
      • AND BL, [SI]
    • 使目标操作数的某些位不变,某些位清零
      • AND AL, 0FH
    • 在操作数不变的情况下使CF和OF清零
      • AND AX, AX

指令应用例

  • 从地址为3F8H端口中读入一个字节数,如果该数bit1位为1,则可从38FH端口将DATA为首地址的1个字输出,否则就不能进行数据传送。
  • 要求:编写相应的程序段。
1
2
3
4
5
6
7
      MOV DX, 3F8H
WATT: IN AL, DX
AND AL, 02H
JZ WATT ;--> ZF=1 转移
MOV DX, 38FH
MOV AX, DATA
OUT DX, AX

思路:
and e.g.

OR

  • format:
    • OR OPRD1, OPRD2
  • manipulation:
    • 两操作数相‘或’,结果送目标地址
  • use to:
    • 实现两操作数相’或‘的运算
      • OR AX, [DI]
    • 使某些位不变,某些位置‘1’
      • OR CL, 0FH
    • 在不改变操作数的情况下使OF=CF=0
      • OR AX, AX

将一个二进制数9转化为字符’9’

1
2
3
4
5
MOV AL, 9
OR AL, 30H

MOV AL, 9
ADD AL, 30H

NOT

  • format:
    • NOT OPRD
  • manipulation:
    • 操作数按位取反再送回原地址
  • NOTE:
    • 指令的执行对标志位无影响
  • e.g.
    • NOT BYTE PTR[BX]

XOR

  • format:
    • XOR OPRD1, OPRD2
  • manipulation:
    • 两操作数相“异或”,结果送目标地址
  • e.g.
    • XOR BL, 80H (高位取反)
    • XOR, AX, AX

逻辑运算指令总体比算术运算指令的性能略微高,
XOR运算清零,比算术清零更快

TEST

TEST 指令和ADD指令基本相同,除了:
TEST 运算结果不送回目标地址

  • format:
    • TEST OPRD1, OPRD2
  • manipulation:
    • 执行“与”运算,但运算结果不送回目标地址。
  • 应用:
    • 常用于测试某些位的状态

从地址位3F8H的端口中读入一个字节数,当该数的bit1,bit3,bit5位同时为1时,可从38FH端口将DATA为首地址的一个字输出,否则就不能进行数据传送。
(编写相应的程序段)

1
2
3
4
5
6
7
8
9
10
11
12
13
      LEA SI, DATA
MOV DX, 3F8H
WATT: IN AL, DX
TEST AL, 02H
JZ WATT ; ZF=1转移
TEST AL, 08H
JZ WATT
TEST AL, 20H
JZ WATT

MOV DX, 38FH
MOV AX, [SI]
OUT DX, AX

更好的解法

1
2
3
4
5
6
7
8
9
10
      LEA SI, DATA
MOV DX, 3F8H
WATT: IN AL, DX
AND AL, 2AH
CMP AL, 2AH ; XOR AL, 2AH
JNZ WATT

MOV DX, 38FH
MOV AX, [SI]
OUT DX, AX