【微机原理与接口 5】—— 常用指令分析1 (数据传输类指令剖析)
文章目录
一、数据传输类指令
1.1 通用数据传输指令
1.1.1 MOV指令
首当其冲的就是 指令了,它的形式是 : 目标操作数,源操作数
下面重点看看 指令对操作数的要求:
- 目标操作数和源操作数的字长必须相同
- 两个操作数不能同时为段寄存器
- 两个操作数不能同时为存储器操作数(也就是说,如果我们想把内存单元的某一个数赋值到内存的另外一个单元,是不能一步到位的,必须借助中间媒介)
- 目标操作数不能为立即数
- 立即数不能直接传输给段寄存器
- CS,IP 不作为目标操作数
辨析下面指令:
【1】MOV DS, 1000H (×):立即数不能够直接赋值给段寄存器
【2】MOV CS, AX (×):代码段寄存器不能作为目标操作数
【3】MOV VALUE1, CX (×):这里的 VALUE1 是一个定义了的变量,那么它就是一个立即数,立即数不能够作为目标操作数
【4】MOV [BX], [SI] (×):这里用方括号表示存储器寻址,那么 [SI] 就代表存储器里面的一个数,MOV 指令中两个操作数不能够同时为存储器操作数
【5】MOV DS, ES (×):两个操作数不能同时为段寄存器
【6】MOV AH, BX (×):两个操作数字长不一致,AH 是8位的,BX 是16位的
【7】迷惑题:MOV DX,09H (√):看起来这两个操作数字长不等,但是别忘了,09H 是0开头的,既然是0开头,前面有几个0都可以,那么09H 可以写成 0009H,这样就 OK 了
1.1.2 堆栈操作指令 PUSH , POP
学完了数据结构,对于堆栈的定义应该不陌生。但是这里需要说明一件事情:就是 堆栈操作指令所操作的数必须是一个字(两个字节),也就是 16位的数!
指令: 源操作数; 目标操作数
先看看 ,我们知道但凡堆栈,都有栈顶指针。那么在这里我们默认栈顶指针都是在高地址的(下面),在有新数据压入时,栈顶指针自减,然后会往上变成低地址。
对于 PUSH 操作,我们首先先将栈顶指针 :,然后把数据压入(16位的!)
对于 POP 操作,类似地,我们先将栈顶指针做:(+代表往下,地址增大)
说明:8088/8086 对于单操作数的指令,都是不允许操作数是立即数的!!!
1.1.3 交换指令 XCHG
操作数1, 操作数2
这个指令的作用就是将两个操作数的内容互换,但是对操作数有以下要求:
- 任何一个操作数都不能为立即数。因为这两个操作数既是源操作数,又是目标操作数。既然是目标操作数就不能是立即数。
- 两个操作数中必须得保证有一个是寄存器操作数,例如 BX, AX之类的
- 两个操作数不能够同时为存储器操作数。(也就是存储器寻址方式)
- 同样不允许有段寄存器作为操作数
例如:
假设 BX寄存器内存放的内容是 BX = 6F30H, 是基址+变址寻址方式,由于没有段超越,所以BP默认的段寄存器是 SS,假设:SS = 2F00H, BP = 0200H,SI = 0046H 那么 表示的偏移地址是:0246H,对应的物理地址就是:2F000H+0246H = 2F246H。那么也就是把 内存地址为 2F246H 的数和寄存器 BX 内的数交换
1.1.4 查表指令 XLAT
这个适用于查找一维数组中的元素。使用 XLAT 的时候不用写操作数,直接 XLAT 就OK。
但是,有几点说明:
- XLAT 规定:需要使用 BX 存放表头地址,AL 用于存放一维数组中元素距表头的距离。因此,需要查找的元素地址就是 BX+AL
- 那么 XLAT 的工作是将地址 BX+AL 所指向的数组元素赋值给 AL
1.2 地址传输类指令
1.2.1 LEA (近地址)
LEA 指令是取近地址的,也就是说,LEA 工作的区域就是在同一个段里面,因此不用考虑段基址
LEA REG, MEM。LEA指令的功能是将变量的 16 位的偏移地址写入到目标寄存器。注意:LEA 指令的源操作数一定要是存储器操作数!!
LEA 的目标操作数一定不能是段寄存器,而一定是通用寄存器!!,通常是间址寄存器
例子:LEA BX, [BX][SI]
假如有:BX = 1000H, SI = 1000H.那么偏移地址是 3000H,结果:BX = 3000H
1.2.2 LDS & LES (远地址)
LDS 和 LES 都是取的远地址。也就是在另外一个段的地址。这样一来,就需要同时取段基地址和偏移地址了。也就是说,LDS 和 LES 的源操作数应该是一个 32 位的存储器操作数
格式如下:
LDS 通用寄存器,存储器操作数
LES 通用寄存器,存储器操作数
例子:
LDS 的作用是将存储器操作数的偏移地址赋值给 通用寄存器,将其段地址赋值给 DS 寄存器
LES 的作用是将存储器操作数的偏移地址赋值给 通用寄存器,将其段地址赋值给 ES 寄存器
1.3 标志位传输指令
这里我们将要了解 4 个指令:
首先是: 和 ,它们的默认操作数是 和 。其中, 的英文全称是:Load AH from flags. 也就是说,它的功能是将 寄存器的第八位赋值给 AH。
的英文全称是:Store AH into flags. 意思是将 里面的数存入 的低八位
和 很简单,就是将 的内容压入堆栈或者说弹出堆栈
1.4 输入输出指令
这一类指令很重要,我们首先需要明确几个定义:1. 什么是接口?2. 什么是端口?
所谓接口,比如说,我们电脑上有一个用来插 U 盘的东西,我们称之为 “USB接口”,这类和外部设备连接的 “口”,我们就叫做接口。一个计算机里面可以有好多接口。
而端口是什么呢?比如说,你电脑通过接口连接了某一个设备,而这个设备里面又会有许许多多的寄存器,我们电脑的 CPU 可以直接访问这些寄存器。因此,在外设里面,能够被 CPU 直接访问的寄存器就是端口。
既然有那么多端口,如果要想实现对端口数据的读或写,那么势必需要对这些端口进行地址编码,这样才能准确低找到所需要控制的端口。因此,也就引申出了下面端口的寻址方式:
根据端口地址码的长度,指令具有两种不同的端口地址表现形式:
- 假设我们的端口数目不多,小于256个,那么我们可以使用8位二进制来进行地址编码。那么这个8位的地址我们可以在指令里面直接给出来。(也就是可以寻址的端口数为:)
- 如果端口很多,端口地址是 16位时,我们在指令里面的端口地址必须要由 指定!这叫间接寻址。所能够寻址的端口数是 )
另外,端口的编码也分为了两种方式:1. 独立编码的方式:端口地址的编码和存储空间的编码是两个不同的独立地址空间。2. 统一编址方式:对内存单元和端口进行统一的编址
下面我们来看看这两个指令:
【1】IN acc, PORT:acc 表示累加器,PORT 顾名思义就是端口的意思。IN 操作的功能是把 PORT 所指向的端口的内容读入 acc里面 (注意:acc 只能是 AX 或 AL)
【2】 OUT PORT, acc 就是把 acc里面的内容写进 PORT 所指向的端口里面