【汇编】#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(同段内带立即数返回)
相关推荐
hai40587几秒前
Spring Boot中的响应与分层解耦架构
spring boot·后端·架构
Adolf_19931 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
海里真的有鱼1 小时前
Spring Boot 项目中整合 RabbitMQ,使用死信队列(Dead Letter Exchange, DLX)实现延迟队列功能
开发语言·后端·rabbitmq
工业甲酰苯胺2 小时前
Spring Boot 整合 MyBatis 的详细步骤(两种方式)
spring boot·后端·mybatis
m0_714590262 小时前
汇编(实现C语言程序的调用)
c语言·开发语言·汇编
新知图书2 小时前
Rust编程的作用域与所有权
开发语言·后端·rust
wn5313 小时前
【Go - 类型断言】
服务器·开发语言·后端·golang
希冀1234 小时前
【操作系统】1.2操作系统的发展与分类
后端
GoppViper4 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理