【汇编】#6 80x86指令系统其二(串处理与控制转移与子函数)

文章目录

  • 一、串处理指令
    • [1. 与 REP 协作的 MOVS / STOS / LODS的指令](#1. 与 REP 协作的 MOVS / STOS / LODS的指令)
      • [1.1 重复前缀指令REP](#1.1 重复前缀指令REP)
      • [1.2 字符串传送指令(Move String Instruction)](#1.2 字符串传送指令(Move String Instruction))
      • [1.2 存串指令(Store String Instruction)](#1.2 存串指令(Store String Instruction))
      • [1.3 取字符串指令(Load String Instruction)](#1.3 取字符串指令(Load String Instruction))
    • [2. 与 REPE(REPNE)配合工作的CMPS 和 SCAS指令](#2. 与 REPE(REPNE)配合工作的CMPS 和 SCAS指令)
      • [2.1 相等重复前缀指令 REPE/REPZ](#2.1 相等重复前缀指令 REPE/REPZ)
      • [2.2 串比较指令 CMPS](#2.2 串比较指令 CMPS)
      • [2.3 串搜索指令 SCAS](#2.3 串搜索指令 SCAS)
    • [3. 串输入输出指令 INS/OUTS](#3. 串输入输出指令 INS/OUTS)
  • 二、转移指令
    • [1. 无条件转移指令JMP](#1. 无条件转移指令JMP)
    • [2. 条件转移指令](#2. 条件转移指令)
  • 三、循环指令
    • [1. 循环指令 LOOP](#1. 循环指令 LOOP)
    • [2. (不)相等/(不)为零循环指令 LOOP(N)E/LOOP(BN)Z](#2. (不)相等/(不)为零循环指令 LOOP(N)E/LOOP(BN)Z)
  • 四、子程序
    • [1. 子程序调用CALL](#1. 子程序调用CALL)
      • [1.1 段内直接调用](#1.1 段内直接调用)
      • [1.2 段内间接调用](#1.2 段内间接调用)
      • [1.3 段间直接调用](#1.3 段间直接调用)
      • [1.4 段间间接调用](#1.4 段间间接调用)
    • [2. 返回指令RET](#2. 返回指令RET)

一、串处理指令

字符串操作指令的实质是对一片连续存储单元进行处理,这 片存储单元是由隐含指针DS:SIES:DI来指定的。

字符串操作指令可对内存单元按字节或字进行处理,并能根据操作对象的字节数使变址寄存器SI(和DI)增减1或2。具体规定如下:(DF控制方向)

  • 当DF=0时,变址寄存器SI(和DI)增加1或2;
  • 当DF=1时,变址寄存器SI(和DI)减少1或2。

1. 与 REP 协作的 MOVS / STOS / LODS的指令

1.1 重复前缀指令REP

重复前缀指令是重复其后的字符串操作指令,重复的次数由 CX来决定

其一般格式为:
REP MOVS / STOS / LODS

每一次循环CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,CX=0时,停止循环。

1.2 字符串传送指令(Move String Instruction)

功能:将以SI为指针的源串中的一个字节(或字)存储单元中 的数据传送至以DI为指针的目的地址中去,并自动修改指针,

使之指向下一个字节(或字)存储单元

REP MOVS:将数据段 中的整串数据 传送到附加段中。

  • (DS:[SI])→ES:[DI]。
  • 当DF=0时,(SI)和(DI)增量;当DF=1时,(SI)和(DI)减量。
  • 指令的格式:
    MOVS DST,SRC (需在操作数中表明数据格式)
    MOVSB (字节)
    MOVSW (字)
  • 执行 REP MOVS 之前,应先做好:
    • 源串首地址(末地址)→ SI
    • 目的串首地址(末地址)→ DI
    • 串长度 → CX
    • 建立方向标志

1.2 存串指令(Store String Instruction)

功能:将AL或AX中的数据送入ES:DI所指的目的串中的字节(或 字)存储单元中。

  • 字节操作:(AL)→[DI],字操作:(AX)→[DI]。
  • 修改指针DI,使之指向串中的下一个元素。
    当DF=0时,(DI)增量)。当DF=1时,(DI)减量。
  • 指令的格式:
    STOS DST (需在操作数中表明数据格式)
    STOSB (字节)
    STOSW (字)

1.3 取字符串指令(Load String Instruction)

功能:将SI所指的源串中的一个字节(或字)存储单元中的数据取出来送入**AL(或AX)**中。

  • 字节操作:([SI])→AL,字操作:([SI])→AX。
  • 修改指针SI,使它指向串中的下一个元素。
    当DF=0时,(SI)增量。当DF=1时,(SI)减量。
  • 指令的格式:
    LODS SR(需在操作数中表明数据格式)
    LODSB (字节)
    LODSW (字)

2. 与 REPE(REPNE)配合工作的CMPS 和 SCAS指令

2.1 相等重复前缀指令 REPE/REPZ

一般格式为:
REPE/REPZ CMPS/SCAS

  • 判断条件:CX≠0 且 ZF=1;(CX=0或ZF=0则退出)若条件不成立,则结束重复操作,执行程序中的下一条指令;
  • 条件成立时,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指令执行完后,继续对循环条件进行判断。

存在相反指令REPNE/REPNZ,条件判断CX与上相同,ZF与上相反

2.2 串比较指令 CMPS

SI 所指的源串中的一个 字节(或字)存储单元中的数据与DI 所指的目的串中的一个字节(或字)存储单元中的数据相减,并根据相减的结果设置标志,但结果并不保存。

  • ([SI])-([DI])
  • 修改串指针,使之指向串中的下一个
    元素。当DF=0时,(SI)和(DI)增量。当DF=1时,(SI)和(DI)减量。
  • 格式:
    • CMPSB 字节串比较
    • CMPSW 字串比较

2.3 串搜索指令 SCAS

AL(字节)或AX(字)中的内容与DI所指的目的串中的一个字节(或字)存储单元中的数据相减,根据相减结果设置标志位,结果不保存

  • 字节操作:(AL)-([DI]);字操作:(AX)-([DI])
  • 修改指针使之指向串中的下一个元素。当DF=0时,(DI)增量。当DF=1时,(DI)减量。
  • 格式:
    • SCASB 字节串搜索
    • SCASW 字串搜索

3. 串输入输出指令 INS/OUTS

INS:

将由DX寄存器指定的I/O端口中的字、字节传送到附加段中的目的串中,并根据DF和数据类型来改变目的变址寄存器的方向内容

格式:

  • INSB 字节串输入: ES:[DI] ←((DX)),
    DI←DI±1
  • INSW 字串输入: ES:[DI] ← ((DX)),
    DI←DI±2

OUTS:

将由源串中的字、字节传送到在DX寄存器指定的

I/O端口中,并根据DF和数据类型来改变源变址寄存器的

方向内容

格式:

  • OUTSB 字节串输出: ((DX))←DS:[SI]
    SI←SI±1
  • OUTSW 字串输出: ((DX))←DS:[SI]
    SI←SI±2

二、转移指令

转移指令分无条件转移指令有条件转移指令两大类。

  • 无条件转移指令包括:JMP、子程序的调用和返回指令、中断的调用和返回指令等。
  • 条件转移指令又分三大类:
    • 基于无符号数的条件转移指令
    • 基于有符号数的条件转移指令
    • 基于特殊算术标志位的条件转移指令

1. 无条件转移指令JMP

  • 段内直接短转移:JMP (SHORT) OPR
    (IP)← (IP)+ 8位位移量
  • 段内直接近转移:JMP (NEAR PTR) OPR
    (IP)← (IP)+ 16位位移量

位移量 是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移。向地址增大方向转移时,位移量为正;反之位移量为负。

  • 段内间接转移: JMP (WORD PTR) OPR
    (IP)← (EA)

将一个寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容

  • 段间直接远转移:JMP (FAR PTR) OPR
    (IP)← OPR 的段内偏移地址
    (CS)← OPR 所在段的段地址

将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行

  • 段间间接转移: JMP (DWORD PTR) OPR
    (IP)← (EA)
    (CS)← (EA+2)

用一个存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的字单元中的,低位字送IP寄存器,高位字送CS寄存器


2. 条件转移指令

条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段

  • 基本格式:

    • JXX LABEL条件满足,发生转移:IP←IP+位移量
      条件不满足,顺序执行指令
    • 操作数LABEL是采用短转移,称为相对寻址方式
  • 单个条件标志的设置情况转移

  • 无符号数的条件转移指令

  • 有符号数的条件转移指令

  • 测试CX的值为0则转移指令

    • 条件转移指令中还有一条较特殊的指令,因为CX寄存器通常在程序中用做计数器,JCXZ指令就可以用来判断计数是否为0
    • 格式 :JCXZ LABEL CX=0,发生转移:IP←IP+位移量;CX≠0,顺序执行下一指令

三、循环指令

1. 循环指令 LOOP

如果(CX)≠0,转向"标号"所指向的指令,否则,终止循环,执行该指令下面的指令。

语句格式: LOOP 标号

使用LOOP指令可代替两条指令:

DEC CX

JNE 标号
转向的范围为-128~+127字节

2. (不)相等/(不)为零循环指令 LOOP(N)E/LOOP(BN)Z

  • 对于LOOPE/LOOPZ:
    • 语句格式: LOOPE/ LOOPZ 短标号
    • 每次循环(CX)=(CX)-1(不改变任何标志位)
      如果CX≠0且ZF=1,则程序转到循环
      体的第一条指令,否则,程序将执行该循
      环指令下面的指令。
  • 对于LOOP(N)E/LOOP(BN)Z:
    • 使用方法相同,判断条件中的ZF条件相反

四、子程序

子程序是完成特定功能的一段程序。如果某程序段在源程序内反复出现,就可把该程序段定义为子程序。这样可以缩短源程序长度、节省目标程序的存储空间,也可提高程序的可维护性和共享性。

1. 子程序调用CALL

类似但不同于JMP指令,CALL指令需要保存返回地址(调用函数时将下一指令的地址压栈)

  • 段内调用------入栈偏移地址IP:
    SP←SP-2,SS:SP←IP
  • 段间调用------入栈偏移地址IP和段地址CS:
    SP←SP-2,SS:SP←IP;
    SP←SP-2,SS:SP←CS。

1.1 段内直接调用

  • 格式:CALL DST
  • 实际步骤:
    • 将子程序的返回地址存入堆栈,以便子程序返回使用。即: (SP)←SP - 2;(SP)+1,(SP)←IP
    • 转移到子程序入口地址去继续执行子程序。指令中的DST在汇编格式指令作为子程序入口地址的符号地址(标号)。在8086机器语言中,它是一个16位的偏移量。即: (IP)←IP+ D16

1.2 段内间接调用

  • 格式:CALL DST
  • 主要区别是子程序的入口地址DST的寻址方式不同而已。它可以是寄存器操作数和各种寻址方式的存储器操作数,当然不允许是立即数和段寄存器操作数。
    • 例如:
      CALL BX ;BX的内容是子程序的偏移量
      CALL word ptr [BX] ;BX所指内存字单元的值是子程序的偏移量

1.3 段间直接调用

  • 格式:CALL DST
  • 执行操作:
    • SP←SP - 2;
    • (SP)+1,(SP)←CS ;
    • SP←SP - 2;
    • (SP)+1,(SP)←IP ;
    • IP ←偏移地址(指令的第2、3字节);
    • CS ←段地址(指令的第4、5字节);

1.4 段间间接调用

  • 格式:CALL DST
  • 执行操作:
    • SP←SP - 2;
    • (SP)+1,(SP)←CS ;
    • SP←SP - 2;
    • (SP)+1,(SP)←IP ;
    • IP ←(EA);
    • CS ←(EA+2);
  • 主要区别是子程序的入口地址DST的寻址方式不同而已。它可以是寄存器操作数和各种寻址方式的存储器操作数,也即由各种寻址方式形成的有效地址EA和EA+1两个单元内容送入IP,EA+2和EA+3两个单元内容送入CS。
    • 例如:
      CALL DWORD PTR [BX];BX所指内存双字单元的值是子程序的偏移量和段值

2. 返回指令RET

  • 段内近返回:RET
    实际操作: (IP )← (SP)+1,(SP)
    (SP)← SP + 2
  • 段内带立即数近返回:RET EXP
    RET 可以带有一个立即数 , 堆栈指针 SP 将增加 , 即
    SP←SP+EXP。这个特点使得程序可以方便地废除若干执行CALL指令以前入栈参数。
  • 段间远返回:RET
    实际操作:(IP) ← (SP)+1,(SP)
    (SP)←(SP) + 2
    (CS)← (SP)+1,(SP)
    (SP)←(SP) + 2
  • 段间带立即数远返回:RET EXP(同段内带立即数返回)
相关推荐
几颗流星2 分钟前
Rust 像素级绘图入门:Pixels 库核心机制解析
后端·rust
乌日尼乐8 分钟前
【Java基础整理】封装、继承、抽象、接口和多态
java·后端
我是谁的程序员12 分钟前
不用 Instruments 而在 Windows 环境下测试 iOS App
后端
ServBay12 分钟前
PHP 8.6 新特性预览,更简洁的语法与更严谨的类型控制
后端·php
文心快码BaiduComate15 分钟前
用Comate开发我的第一个MCP——让Vibe Coding长长脑子
前端·后端·程序员
神奇小汤圆18 分钟前
Spring Boot + 执行管道:让业务流程清晰可控
后端
我是谁的程序员1 小时前
iOS App 中 SSL Pinning 场景下代理抓包失效的原因
后端
UrbanJazzerati1 小时前
掌握SOQL For Loops:高效处理大量Salesforce数据的艺术
后端·面试
墨风如雪2 小时前
手把手教你测试VPS网络质量:详解测试IP与LookingGlass用法 (以RackNerd洛杉矶DC02为例)
后端·网络协议
计算机学姐2 小时前
基于SpringBoot的美妆销售系统【个性化推荐算法+数据可视化统计+库存预警+物流信息】
java·vue.js·spring boot·后端·mysql·信息可视化·mybatis