microcomputer_principle_06_位移操作与串操作
Carpe Tu Black Whistle

移位操作指令

  • 控制二进制位向左或向右移动的指令
    • 非循环移位指令(线性)
    • 循环移位指令
  • 指令格式在形式上为双操作数,本质上为 单操作数
  • 指令的目的操作数为被动移动对象,源操作数为移动次数
    • 当目标为存储器操作数时,需要说明其字长
  • 移动1位时由指令直接给出;移动两位以及以上时,移位次数必须由CL指定。
    指令源操作数只能是1或CL

非循环移位指令

  • 逻辑左移
  • 算术左移
  • 逻辑右移
  • 算术右移

非循环移位指令是一种破坏性的移位,发生操作后,就不再可以还原了。

算术左移和逻辑左移

算术左移指令:(针对有符号数)

1
2
SAL OPRD, 1
SAL OPRD, CL

逻辑左移指令:(针对无符号数)

1
2
SHL OPRD, 1
SHL OPRD, CL

对于左移来讲,无论是算术还是逻辑层面操作都是一样的
将最高位移动到CF,最低位补零

逻辑右移

无符号数右移操作

  • format:
    1
    2
    SHR OPRD, 1
    SHR OPRD, CL

原理: 最低位–> CF, 最高位补0,其余右移。

算术右移

针对有符号数右移操作

  • format:
    1
    2
    SAR OPRD, 1
    SAR OPRD, CL

SAR

算术右移的高位会用最高位的数值补全

非循环移位指令应用

  • 左移可以实现乘法运算
  • 右移可以实现除法运算

循环移位指令

  • 不带进位位的循环移位
    • 左移 ROL
    • 右移 ROR

cycle

  • 带进位位的循环移位
    • 左移 RCL
    • 右移 RCR

image

指令格式、对操作数的要求与非循环移位指令相同

循环移位应用

  • 用于对某些位状态的测试;
  • 高位部分和低位部分的交换;
  • 与非循环移位指令一起组成32bit或更长字长数的移位

image

  • 题目分析:
    • 压缩BCD码是用4位二进制码表示1位十进制数—->1字节表示2位压缩BCD
    • 转换ASCII码时需要分别转换高4位(十位数)和低4位(个位数)
    • 0~9的ASCII码的高4位均为0011(03H)
    • 转换低4位时应先使高4位清零,转换高四位时须先将高4位移动到低4位的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
      LEA SI, M1
LEA DI, M2
MOV CH, 4 ; CL用于移位,CH用于存储循环数
NEXT: MOV AL, [SI]
MOV BL, AL ; BL备份原数据, AL的操作会破坏源数据
AND AL, 0FH ; 高位清零
OR AL, 30H ; 高位设为3, X对应3XH
MOV [DI], AL
INC DI
MOV AL, BL
MOV CL, 4
SHR AL, CL
OR AL, 30H
MOV [DI], AL
INC DI
INC SI
DEC CH
JNZ NEXT
HLT

串操作

  • 针对数据块或字符串的操作
  • 可实现存储器到存储器的数据传送;(双操作数指令,有时候,必须要求,两个操作数都是存储器操作)
  • 待操作的数据串称为源串,目标地址称为目标串。

串操作指令说明

  • 串操作指令的操作对象是多个字节数(一串字符或数据),因此,指令的执行需要确定:
    • 串所在区域
    • 串首地址(原串、目标串起始地址)
    • 串长度(大小)
    • 串的操作方向

串操作指令的要求

  • 串所在区域及首地址:
    • 源串一般存放在数据段,偏移地址由SI指定。允许段重设。
    • 目标串必须在附加段,偏移地址由DI指定。
  • 串长度:
    • 串长度值由CX指定
  • 串的操作方向:
    • 由DF标志位决定。指令根据DF状态自动修改地址指针
      • DF=0 –> 增地址方向
      • DF=1 –> 减地址方向

会有专门的指令设置DF值
通过增加重复前缀,可以实现对CX值对自动修改

重复前缀

  • 无条件重复
    • REP(repeat)
      • 当CX0时,REP后的指令将继续重复执行
      • 常用于传送类指令前 -> 未传完则继续传送
  • 条件重复
    • 相等(为零)重复:REPE(REPZ)
      • CX0ZF=1, 则前缀后的指令将继续重复执行
    • 不相等(不为零)重复:REPNE(REPNZ)
      • CX0ZF=0, 则前缀后的指令将继续重复执行

条件前缀常用于运算累指令前,当:

  1. 操作未结束 AND 结果=0 or
  2. 操作未结束 AND 结果0
    使其后的指令继续重复执行。

串操作指令

  • 串传送MOVS
  • 串比较CMPS
  • 串扫描SCAS
  • 串装入LODS
  • 串送存STOS

串操作指令流程
串操作指令流程

在串操作中,右部4个模块,用(一条指令+重复前缀)来完成
完成一个字节(字)操作+修改地址指针,由串操作指令实现
重复前缀,实现了循环结构

string

  • 若按增地址方向操作,串操作结束时:

    • 串传送指令: 指针将指向串尾+1
    • 串比较类指令:指针将指向结束位+1
  • 若按减地址方向操作,串操作结束时:

    • 串传送指令: 指针将指向串尾-1
    • 串比较累指令: 指针将指向结束位-1

串传送MOVS

  • func:
    • 将源数据串传送到目标地址
  • format:
    1. MOVS OPRD1, OPRD2(仅用于对源串段重设)
    2. MOVSB(按字节传送)
    3. MOVSW(按字传送)
  • 串传送指令通常与无条件重复前缀连用

应用例子:

分别用MOV指令和MOVS指令编写将200字节数数据从内存数据段MEM1为首地址的区域送到同一逻辑段MEM2为首地址的区域中的程序。

MOV指令实现算法:

1
2
3
4
5
6
7
8
9
10
      LEA SI, MEM1
LEA DI, MEM2
MOV CX, 200
NEXT: MOV AL, [SI]
MOV [DI], AL
INC SI
INC DI
DEC CX
JNZ NEXT
HLT

MOVS指令实现算法:

1
2
3
4
5
6
LEA SI, MEM1
LEA DI, MEM2
MOV CX, 200
CLD ;Clear DF
REP MOVSB ;按字节传送,并且修改字节指针
HLT

串比较CMPS

在上一节的例子中,完成操作后,检验代码是否正确运行————可以利用串比较指令进行检验

  • func:
    • 用于实现两个数据串的比较
  • manipulation:
    • 目标串-源串,结果不写回目标地址
    • 常与条件重复前缀连用
  • format:
    1. CMPS OPRD1 OPRD2 (仅段重设采用)
    2. CMPSB
    3. CMPSW

前缀的操作对标志位不影响(虽然会进行CX-1操作)
串比较指令会影响全部6个标志位

  • 测试上例中200Bytes数据传送是否正确。
1
2
3
4
5
6
7
8
9
10
      LEA SI, MEM1
LEA DI, MEM2
MOV CX, 200
CLD
REPE CMPSB ; CX=0 or ZF=0 pause
JZ STOP ; 条件转移-> ZF=1 数据串完全相同,转移到STOP
DEC SI ; 指向不匹配的内存单元
MOV AL, [SI] ; 这三句用于取出,地址+元素
MOV BX, SI
STOP: HLT

串扫描SCAS(scan string)

常用于在指定存储区域中寻找某个关键字

  • format:
    • SCAS OPRD <– 目标操作数(被查找的长串)
      (目标操作数,一般在附加段ES,指针为DI)
    • SCASB
    • SCASW
  • 执行与CMPS指令相似的操作,区别是:
    • 这里的源操作数是AX或AL(需要查找的pattern)
      (按字节扫描AL,按字扫描AX)

串扫描指令应用例:

  • 在ES段中从2000H单元开始存放了10个字符,寻找其中有无字符“A”。若有则记下搜索次数,将搜索次数写入到DATA1单元,并将存放“A”的地址写入DATA2单元。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
      MOV DI, 2000H
MOV BX, DI
MOV CX, 0AH
MOV AL, 'A'
CLD
REPNZ SCASB
JZ FOUND
MOV DI, 0
JMP DONE

FOUND:DEC DI ; 减1指向匹配字节地址
MOV DATA2, DI
INC DI ; 回到原地址
SUB DI, BX ; 进行多少次增位,就有几次搜索

DONE: MOV DATA1, DI
HLT

串装入LODS

  • format:

    • LODS OPRD –> 源操作数,指针必须使用SI寄存器
    • LODSB
    • LODSW
  • manipulation:

    • 对字节: AL <– [DS:SI]
    • 对字 : AX <– [DS:SI]
  • 用于将内存某个区域的数据串一次装入累加器,以便显示或输出到接口。

  • LODS指令一般不加重复前缀。

与MOV指令无异

串存储STOS(store string)

  • format:
    • STOS OPRD –> 目标操作数
    • STOSB
    • STOSW
  • manipulation:
    • 对字节: AL –> [ES:DI]
    • 对字: AX –> [ES:DI]

  • 常用于将内存某个区域置同样的值
  • 此时:
    • 将待送存的数据放入AL(字节数)或AX(字数据);
    • 确定操作方向(增/减地址)和区域大小(串长度值)
    • 使用串存储指令+无条件重复前缀,实现数据传送

串操作Notes

  • 需要定义附加段(ES
    • 目标操作数必须在附加段
    • (第四章会学习如何定义附加段)
  • 需要设置数据的操作方向
    • 确定DF的状态
  • 源串和目标串指针分别为SI和DI
  • 串长度值必须由CX给出
  • 注意重复前缀的使用方法
    • 传送类指令前加无条件重复前缀
    • 串比较类指令前加条件重复前缀,但前缀不影响ZF状态

无论是串传送还是串比较完成,无论是否满足,都是先修改指针+修改长度值,再判断是否满足条件。
哪怕串比较不相等,不再继续,但是指针已经在跳出位置下一内存单元