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

2024-04-28 20:44

本文主要是介绍【汇编】#6 80x86指令系统其二(串处理与控制转移与子函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

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

这篇关于【汇编】#6 80x86指令系统其二(串处理与控制转移与子函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944220

相关文章

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

电脑提示xlstat4.dll丢失怎么修复? xlstat4.dll文件丢失处理办法

《电脑提示xlstat4.dll丢失怎么修复?xlstat4.dll文件丢失处理办法》长时间使用电脑,大家多少都会遇到类似dll文件丢失的情况,不过,解决这一问题其实并不复杂,下面我们就来看看xls... 在Windows操作系统中,xlstat4.dll是一个重要的动态链接库文件,通常用于支持各种应用程序

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w