跳至主要內容

汇编与接口

yyshino大约 54 分钟

汇编与接口

第1章 微型计算机概述

硬件系统

由冯·诺依曼在1940年最早提出的, 各个部件功能如下:

  • 控制器:发布各种操作命令、控制信号等。
  • 运算器:主要进行算术和逻辑运算。
  • 存储器:存储程序、数据、中间结果和运算结果。
  • 输入/输出(I/O)接口:原始数据和程序等通过输入接口送到存储器, 而处理结果、控制信号等通过输出接口送出。

微处理器(CPU)

CPU在内部结构上包含下面这些部分:

  • 运算器:算术逻辑部件ALU;
  • 控制器:时序和控制部件;
  • 累加器和通用寄存器组;
  • 程序计数器(指令指针)、指令寄存器和译码器;
  • 总线接口部件:指令队列缓冲器、存储地址形成部件等

CPU功能:

  • 可以进行算术和逻辑运算
  • 可保存较少量数据
  • 能对指令进行译码并执行规定的动作;
  • 能和存储器、外设交换数据
  • 提供整个系统所需要的定时和控制
  • 可以响应其他部件发来的中断请求

系统总线

总线:总线是CPU向存储器和输入/输出接口传送地址、数据和控制信息的公共通路

CPU总线包含三种不同功能的总线:

  • 数据总线DB(data bus)(16根):传输数据
    • 数据总线DB用于传送数据信息。数据总线是双向三态形式的总线
  • 地址总线AB(address bus):传送地址信息
    • 地址总线AB是专门用来传送地址的, 由于地址只能从CPU传向外部存储器或I/O端口, 所以地址总线总是单向三态的, 这与数据总线不同。地址总线的位数决定了CPU可直接寻址的内存空间大小。
  • 控制总线CB(control bus) :传输控制信号
    • 控制总线CB用来传送控制信号和时序信号。控制信号中, 有的是微处理器送往存储器和I/O接口电路的, 如读/写信号, 中断响应信号等, 有的是其它部件反馈给CPU的, 如中断申请信号复位信号总线请求信号准备就绪信号

例: 8086的数线为16位, 地址线为 20位, I/O口使用16位地址线。

第2章 80X86微处理器

8086内部结构

从功能上, 8086分为两部分, 即

  1. 总线接口部件(bus interface unit, BIU)

  2. 执行部件(execution unit, EU)

8086是16位处理器, 因此寄存器宽度均为16位。

  • SP:Stack Pointer
  • BP: Base Pointer
  • DI: Des Index
    • 目的变址
  • SI: Src Index
    • 源变址

8086微处理器内部结构

8086微处理器内部结构
8086微处理器内部结构

CPU ( 8086CPU )

  • EU(执行部件)

    • EU功能:
      • 负责指令的译码和执行。
      • 负责向总线接口部件BIU提供偏移地址。
      • 对通用寄存器和标志寄存器进行管理
    • EU组成:
      1. 算术逻辑部件ALU
        • 标志寄存器
      2. 暂存寄存器
      3. 通用寄存器组
        • 4个通用寄存器AX、BX、CX、 DX
          • AX――累加器(Accumulator), 使用频度最高
          • BX――基址寄存器(Base Register), 常存放存储器地址
          • CX――计数器(Count Register), 常作为计数器
          • DX――数据寄存器(Data Register), 存放数据
        • 4个专用寄存器
          • SI――源变址寄存器(Source Index), 常保存存储单元地址
          • DI――目的变址寄存器(Destination Index), 常保存存储单元地址
          • BP――基址指针寄存器(Base Pointer), 表示堆栈区域中的基地址
          • SP――堆栈指针寄存器(Stack Pointer), 指示堆栈区域的栈顶地址
      4. EU控制电路。
  • BIU(总线接口部件)

    • BIU功能:负责CPU与内存或I/O端口传送指令或数据。

      • BIU从内存取指令送到指令队列缓冲器。当EU执行指令时, BIU要配合EU从指定的内存单元或I/0端口中读取数据,或者把EU的操作结果送到指定的内存单元或I/0端口去。
    • BIU组成:

      1. 指令队列缓冲器

      2. 16位的指令指针寄存器 (IP Instruction Pointer)

        • 4个段地址寄存器(CSDSES(附加段)SS
      3. 20位的地址加法器, 如下图 (加的4个0表示形成物理地址前, 先把段首地址(段基址)左移四位(x16D or x10H) )

通用寄存器

  • 数据寄存器
    • AX——AH(高字节)AL(低字节)——累加器
    • BX——BHBL——基数寄存器
    • CX——CHCL——计数寄存器
    • DX——DHDL——数据寄存器
  • 地址指针寄存器:用来存取位于当前堆栈段中的数据
    • SP——堆栈指针寄存器:给出栈顶的偏移地址
    • BP——基址指针寄存器:存放位于堆栈段中的一个数据区基址的偏移地址。
  • 变址寄存器:存放当前数据段的偏移地址
    • SI——源变址寄存器
    • DI——目的变址寄存器
  • 指令指针寄存器IP
    • 存放着BIU要取的下一条指令的偏移地址。
    • 下一条指令的物理地址= CS(段首址)x16+IP
  • 标志寄存器★
    1. 状态标志
      • ① 符号标志SF (sign flag )
      • ② 零标志ZF (zero flag)
      • ③ 奇偶标志PF (parity flag)
      • ④ 进位标志CF (carry flag)
      • ⑤ 辅助进位标志AF (auxiliary carry flag) (基本不考)
      • ⑥ 溢出标志OF (overflow flag)
    2. 控制标志
      • 中断允许标志IF
        • IF=1,则CPU可以接受可屏蔽中断请求
      • 方向标志DF:
        • DF=1时,地址自动递减;
        • DF=0时,地址自动递增。
      • 跟踪(陷阱)标志TF
        • 为调试程序的方便而设置的。
        • TF=1,则处于单步工作方式;
        • TF=0,将正常执行程序。
  • 段寄存器
    • 代码段(CS):用来存放当前正在运行的程序不能做目的操作数
    • 数据段(DS):存放当前运行程序所用的数据
    • 堆栈段(SS):堆栈作用是保护数据
    • 附加数据段(ES):辅助的数据区。

8086 CPU引脚

引脚图
引脚图
  1. AD15~AD0:地址/数据复用引脚。在总线周期的T1状态用来输出要访问的存储器或I/0端口地址,在T2~T4状态,作为数据传输线。
  2. A19/S6~A16/S3:地址/状态复用引脚。在T1状态:输出高4位地址,在T2~T4状态:输出状态信息。访问存储器时: A19~A16AD15 ~AD0组成20位地址;访问I/0端口时:不使用这4条引线。
  3. $ \overline{BHE} / S_7 $:高8位数据总线允许/状态复用引脚。在T1状态:输出,若为0,表示高8位数据线D15~D8上的数据有效。
  4. RD/WR为读/写选通信号, 三态输出, 低电平有效;
  5. ALE地址锁存允许信号,输出,正脉冲。在任何一个总线周期的T1状态,ALE输出有效电平,以表示当前总线上输出的是地址信息,要求进行地址锁存。
  6. $ \overline{DEN} $:数据允许信号,输出,低电平有效,提供给数据总线收发器8286,表CPU准备发送或接收一个数据。常作为数据总线驱动器的三态控制信号。
    • 在最小模式系统中, 有时利用数据收发器8286/8287来增加数据驱动能力, DEN用来作数据收发器8286/8287的输出允许信号。在DMA工作方式时, 被置成高阻状态。
  7. $ M/\overline{IO} $:存储器/外设控制信号,输出。1一访问存储器,0一访问外设。
    • M/IO信号为高电平时, 表示CPU正在访问存储器, 信号为低电平时, 表示CPU正在访问I/O端口。一般在前一个总线周期的T4状态, 有效, 直到本周期的T4状态为止。在DMA方式时, M/IO置为高阻状态。
  8. $ DT/\overline{R} $:数据收发控制信号,输出,三态。用来控制数据传送方向。1一发送数据,0 接收数据。
  9. READY: “准备好”信号,由所寻址的存储器或I/0端口发来的响应信号,表明存储器或I/O端口的状态。CPU在T3采样READY,若READY=0,则在T3后插入一个或多个TW,直至READY=1,进入T4,完成数据传送,从而结束当前总线周期。
  10. RESET复位信号:输入,高电平有效
  11. INTR(Interrupt Request):可屏蔽中断请求信号, 输入, 电平触发, 高电平有效。
    • 当外设接口向CPU发出中断申请时, INTR信号变成高电平。典型的可屏蔽中断源的例子是打印机中断, CPU对打印机中断请求的响应可以快一些, 也可以慢一些, 因为让打印机等待儿是完全可以的。CPU只有两根中断请求输入线, 有多个中断源怎么办? 一般借助于外部电路。
  12. INTA(Interrupt Acknowledge):中断响应信号, 输出, 低电平有效。
    • 在中断响应总线周期T2、T3、TW状态, CPU发出两个INTA负脉冲, 第一个负脉冲通知外设接口已响应它的中断请求, 外设接口收到第二个负脉冲信号后, 向数据总线沙锅内放中断类型号。
  13. NMI(NonMaskable Interrupt Request):不可屏蔽中断请求信号, 输入, 边沿触发, 正跳变(上升沿)有效。
  14. TEST(Test):测试信号, 输入, 低电平有效。
    • 每隔五个时钟周期测试一下看看是否需要继续等待。若高电平, 继续等待, 否则执行下一条指令。
  15. HOLD:总线保持请求信号,输入,高电平有效 (了解)
  16. HLDA:总线保持响应信号,输出,高电平有效 (了解)
  17. CLK(Clock):时钟信号, 输入。
  18. VCC(+5V), GND(地)
总体回顾一下各引脚信号:
① GND、VCC	地和电源 
② AD15~AD0		地址/数据复用
③ A19/S6~A16/S3	地址/状态复用
④ BHE#/S7 		高8位数据总线允许/状态复用
⑤ NMI		不可屏蔽中断请求NMI(NonMaskable)  
⑥ INTR		可屏蔽中断请求信号输入 
⑦ RD		读信号输出 
⑧ CLK		时钟输入 
⑨ RESET		复位信号输入 
⑩ READY 	“准备好”信号输入 
⑾ TEST#	测试信号输入 
⑿ MN/MX#	最小和最大模式控制输入 

最小模式下的引脚

引脚信号:
① INTA#	中断响应信号输出 
② ALE	Address Latch Enable;地址锁存允许信号
	当地址锁存器接到该信号后将地址/数据总线上的地址锁存在总线上, 
	随后才能传输数据(地址和数据线复用)。
③ DEN#	DataENable	数据允许信号 
④ DT/R#	数据收发信号输出 
⑤ M/IO#		存储器/输入输出控制信号输出 
⑥ WR#		写信号输出 
⑦ HOLD		总线保持请求信号输入 
⑧ HLDA		总线保持响应信号输出

总线操作和时序

1、几个基本概念

  • 时钟周期:是CPU的基本时间计量单位, 它由计算机主频决定。8086 主频是5MHz, 一个时钟周期就是200ns。(1s = 1000ms, 1ms = 1000us 1us = 1000ns)
  • 总线周期:BIU完成一次访问存储器操作所需要的时间称作一个总线周期。一个最基本的总线周期由4个时钟周期组成, 习惯上称4个状态, 即T1,T2,T3,T4状态。只有在CPU和内存或I/O端口之间传递数据以及取指令时, CPU才执行总线周期。
  • 空闲周期:如果在一个总线周期之后, 不立即执行下一个总线周期, 则系统总线就处于空闲状态, 此时执行空闲周期Ti。
  • 指令周期:就是计算机完成对一条指令的读取并执行这一系列步骤所需要的时间。 一个指令周期包含一个或几个总线周期。
2.8086的主要操作: 

① 系统的复位和启动操作;

② 暂停操作;

③ 总线操作;

④ 中断操作;

⑤ 最小模式下的总线保持;

⑥  最大模式下的总线请求/允许。

最小方式下的读操作

最小方式下的读操作
最小方式下的读操作

一些概念

堆栈

堆栈是以“先进后出”或“后进先出”原则管理的存储区域。SS给出堆栈段的段基址, SP存放栈顶地址,指出从栈顶到段首址的偏移量。

奇区和偶区

8086的1MB存储空间实际上分为两个512KB的存储体,分别叫奇存储体(奇区)和偶存储体(偶区)。

  • 偶存储体与数据总线D7~D0相连,该存储体中每个地址均为偶数地址;
  • 奇存储体与数据总线D15~D8相连,该存储体中每个地址均为奇数地址。

指令周期:执行一条指令所需要的时间。不同指令的指令周期在时间上是不相等的

总线周期: CPU访问一次存储器或I/0接口所需要的时间。一个指令周期由一个或几个总线周期组成。在8086中最基本的总线周期由4个时钟周期组成,分别为T1、T2、T3、T4。

时钟周期:执行指令的所有操作都是在时钟脉冲的控制下一步一步进行的。时钟周期是CPU的基本时间计量单位。时钟周期由主频决定。计算公式:T=1/f

**等待状态 $T_w$ **:当被写入数据或被读取数据的存储器或外设在速度上跟不上CPU的要求时,就会由存储器或外设通过READY信号线在T3状态启动之前向CPU发一个READY无效信息,表示数据未就绪,于是CPU将在T3之后插入1个或多个附加的时钟周期Tw。当存储器或外设完成数据的读/写时,便在READY线上发出有效信号,CPU接到此信号,会自动脱离Tw而进入T4状态。

**空闲状态 $T_1$ **:总线周期只用于CPU和存储器或I/0端口之间传送数据和供填充指令队列,如果在1个总线周期之后,不立即执行下1个总线周期,那么,系统总线就处于空闲状态,即执行空闲周期TI。在空闲周期中,可以包含1个时钟周期或多个时钟周期。

复位和启动:

  • RESET引脚至少维持4个时钟周期的高电平信号时, 8086/8088复位。如果是初次加电引起的复位,则要求维持不小于50us的高电平。
  • 8086/8088复位后将从内存的FFFF0H处开始执行指令。因此,一般在该处放一条无条件转移指令,转移到系统程序的入口处。这样系统一旦被启动,便自动进入系统程序。

第3章 80X86指令系统和寻址方式

8086/8088指令系统概述 (了解即可)

数据类型

  • 无符号二进制数
  • 带符号二进制数
  • 浮点数
  • BCD码
  • 串数据
  • ASCII码数据
  • 指针类数据
  • 位串:一串连续的二进制数
    • 字节串:一串连续的字节。
    • 字串:一串连续的字。
    • 双字串:一串连续的双字。

8086 指令格式

指令的操作码

  • 指令的操作码(简称OP)采用二进制代码表示本指令所执行的操作, 在大多数指令的操作码中, 常用某位指示某些具体操作信息。下图所示8086操作码, 含有3个特征位, 分别为W位、D位和S位。
指令格式
指令格式

注意:

  • 一条指令可以包含一个操作数, 也可以包含一个以上的操作数;一个操作数的指令称为单操作数指令, 单操作数指令中的操作数可能由指令本身提供, 也可能由指令隐含地指出。
  • 若位移量或立即数为16位, 那么在指令代码中, 将低位字节放在前面, 高位字节放在后面。
  • 8086指令系统中大多数指令的操作码只占用第一个字节, 但有几条指令是特殊的, 其指令中的第一个字节不但包含操作码成分, 而且还隐含地指出了寄存器名, 从而整个指令只占一个字节, 成为单字节指令。这些指令字节数最少, 执行速度最快, 用得也最频繁。

指令的执行时间

  • 指令执行时间取决于时钟周期长短和执行指令所需要的时钟周期数。
  • 执行一条指令所需的总时间为基本执行时间、计算有效地址的时间和为了读取操作数和存放操作结果需访问内存的时间之和。

8086的寻址方式和指令系统

寻址方式

  • 数据寻址方式:是指获取指令所需的操作数或操作数地址的方式
    • 8086指令中所需的操作数来自以下几个方面。
      • 操作数包含在指令中。在取指令的同时, 操作数也随之得到, 这种操作数被称为立即数
      • 操作数包含在CPU的某个内部寄存器中, 这种操作数被称为寄存器操作数
      • 操作数包含在存储器中, 这种操作数被称为存储器操作数
  • 程序寻址方式:是指程序中出现转移和调用时的程序定位方式
  1. 立即数寻址——直接给出操作数

    MOV CX, 2A50H		;将立即数2A50H送到CX寄存器中。
    
    ; 例二
    MOV  AX, 0A7FH    ;AX←0A7FH, 执行后, AH=0AH, AL=7FH
    MOV  AL, 5H       ;AL←5H
    ;立即寻址方式主要是用于给寄存器或存储单元赋初值
    
    
  2. 寄存器寻址——操作数为内部寄存器(AX/BX/CX/DX/SI/DI/SP/BP)

    MOV DX,AX		;AX内容送到DX中(AX内容不变)
    
    ; 例二
    MOV  AH, AL
    
  3. 存储器寻址

    • 直接寻址: 操作数给出有效地址(即偏移地址)

      • 有效地址只包含偏移量一种成分。
      • 直接寻址一般多用于存取某个存储器单元中的操作数, 比如从一个存储单元取操作数, 或者将一个操作数存入某个存储器单元。
MOV AL,[200H]
  • 寄存器间接寻址: 有效地址只包含在基址寄存器或变址寄存器中。这些寄存器可以是BX、BP、SI、DI之一

    • BX、SI、DI默认段为DS段,物理地址=DS*16+BX/SI/DI
    • BP默认段为SS段,物理地址=SS*16+BP
; 1) 以BX、SI、DI进行寄存器间接寻址(BX、SI、DI作为地址指针)的方式, 
;隐含的段寄存器为数据段寄存器DS 
   
MOV AX,[BX]
   
MOV  AX, [BX]                   ;物理地址=DS×16+BX
MOV  BX, [SI]                   ;物理地址=DS×16+SI
MOV  [DI], DX                   ;物理地址=DS×16+DI
   
; 2) 以BP进行寄存器间接寻址(BP作为地址指针)的方式
;隐含的段寄存器为堆栈段寄存器SS, 操作数存放在堆栈段区域, 
;将堆栈段寄存器SS的内容左移4位, 再加上基址寄存器BP的内容, 即为操作数的物理地址。
;例 
MOV  [BP], BX                ;物理地址=SS×16+BP
   
;无论用BX、SI、DI或者BP作为间接寄存器, 都允许段超越, 
;即可以使用上面所提到的约定以外的其它段寄存器。
;例 
MOV  AX, ES:[BX]             ;物理地址=ES×16+BX
MOV  DS:[BP], DX             ;物理地址=DS×16+BP

  • 相对寄存器寻址: 有效地址是寄存器内容+位移 (是在寄存器间接寻址基础上加上位移量, 位移量可以是正的也可以是负的。)

    • 操作数的物理地址=16xDS + BX/SI/DI +位移或=16xSS + BP +位移
    MOV AX,[BP+1234H]
    
    ;例 
    MOV  AX, 3003H[SI]
    ;假设DS=3000H, SI=2000H, 指令中的3003H即为位移量DISP。
    ;指令操作的存储器物理地址=3000H×10H+EA=30000H+2000H+3003H=35003H.
    
    
  • 基址加变址寻址方式: 基址变址寻址方式是用基址寄存器BX,BP和变址寄存器SIDI变址寄存器进行的间接寻址。

    • 操作数的物理地址=16xDS + BX(基址寄存器)+SI/DI (变址寄存器)或=16xSS + BP + SI/DI
    ;MOV  AX, [SI+BX]
    ;假设DS=3000H, SI=2000H, BX=1000H。
    ;指令操作的存储器物理地址=3000H×10H+EA=30000H+1000H+3003H=34003H.
    
    MOV AX,[BX][SI]
    MOV AX,[BX+SI]
    MOV AX,DS:[BP][DI]
    ;以上三种写法含义相同
    
    
  • 相对的基址加变址寻址方式

    • 将基址寻址方式和变址寻址方式联合起来的寻址方式称为基址、变址寻址方式。这种寻址方式, 操作数在存储单元中, 其物理地址由段寄存器内容左移4位加上一个基址寄存器和一个变址寄存器, 再加上16位或8位位移量。
  • 操作数的物理地址=16xDS+BX+SI/DI+位移或=16xSS+BP+SI/DI+位移

    MOV  AX, MASK[BX][SI]
    ;假设 MASK=64H, BX=A500H, SI=2200H, DS=6000H
    ;物理地址=DS×10H+EA=6000H×10H+A500H+2200H+64H=6C764H
    
    
    MOV AX,MASK[BX][SI]
    MOV AX,[MASK+BX+SI]
    ;不同写法含义相同
    

程序寻址方式(写子程序时用到, 不做要求)

I/O地址空间

I/O端口寻址是对输入输出设备的端口地址寻址, 可分为两种形式, 即直接端口寻址和间接端口寻址。

  • 直接端口寻址

    • 由指令直接给出端口地址, 端口地址范围为0~255。

      ;例 
      IN  AL, 32H		;32H为8位端口地址
      
  • 间接端口寻址

    • 由DX寄存器指出端口地址, 这种方式给出的端口地址范围为0~65535。

      ;例 
      IN  AL, DX		;DX寄存器的内容为端口寻址
      

段寄存器的确定

访存类型默认段寄存器段超越前缀的可用性
代码CS不可用
PUSH、POP类代码SS不可用
串操作的目标地址ES不可用
以BP、SP间址的指令SS可用CS、DS, ES
其它DS可用CS、SS、ES

8086指令系统

数据传送指令
  • 数据传送类指令用于实现CPU的内部寄存器之间
  • CPU内部寄存器和存储器之间
  • CPU累加器AX或AL和I/O端口之间的数据传送

此类指令除了SAHF和POPF指令外均不影响标志寄存器的内容。

在数据传送指令中, 源操作数和目的操作数的数据长度必须一致。

MOV指令

  • 指令格式:MOV dest,src ;dest←src

  • 功能: 将源操作数的内容传送到目的操作数

    • MOV指令用于将一个操作数从存储器传送到寄存器, 或从寄存器传送到存储器, 或从寄存器传送到寄存器, 也可以将一个立即数存入寄存器或存储单元, 但**不能用于存储器与存储器之间, 以及段寄存器之间的数据传送**, MOV指令传送关系如图3.4所示。
  • MOV指令有6种数据传输格式。

    ;1)CPU的通用寄存器之间的数据传输
    ;例 3.17
    MOV  AL, BL         ;BL寄存器的8位数送到AL寄存器
    MOV  SI, BX        ;BX寄存器的16位数送到SI寄存器
    
    ;2)立即数(常数)到存储单元的数据传输
    ;例 3.18
    MOV  MEM_BYTE, 20H 	;将立即数20H送到MEM_BYTE存储单元
    MOV  DS:[0005H], 4500H
              ;立即数4500H送到DS:0005H的存储单元中
    
    ;3)立即数到通用寄存器的数据传输
    ;例 3.19
    MOV  AL, 20H          ;将立即数20H送到AL寄存器
    MOV  SP, 2000H       ;将立即数2000H送入SP寄存器
    
    ;4)通用寄存器和存储单元之间的数据传输
    ;例 3.20
    MOV  AL, DS:[1000H]   
            ;将地址DS:1000H存储单元的内容送到AL
    MOV  ES:[0002H], BX          
            ;将BX中的16位数据传输到地址ES:0002H
            ;所指的两个相邻存储单元中
    
    ;5)段寄存器和存储单元之间的数据传输
    ;例 3.21
    MOV  ES, [BX]                 ;BX寄存器所指内容传送到ES 
    MOV  [1000H], CS              ;将CS内容传送到地址为1000H的存储器单元
    
    ;6)通用寄存器和段寄存器之间的数据传输。
    ;例 3.22
    MOV  AX, ES                  ;将ES段地址传送到DS段
    MOV  DS, AX 
    
    
  • 使用MOV指令时, 必须注意以下几点:

    • MOV指令可以传8位数据, 也可以传16位数据, 这决定于寄存器是8位还是16位, 或立即数是8位还是16位。
    • MOV指令中的目的操作数和源操作数不能都是存储器操作数, 即不允许用MOV实现两个存储单元间的数据传输。
    • 不能用CS和IP作为目的操作数, 即这两个寄存器的内容不能随意改变。
    • 不允许在段寄存器之间传输数据, 例如MOV DS,ES 是错误的。
    • 不允许用立即数作为目的操作数。
    • 不能向段寄存器传送立即数。如果需要对段寄存器赋值, 可以通过CPU的通用寄存器AX来完成。

交换指令 XCHG

  • 指令格式:XCHG dest,src ;dest←→src

  • 功能:源操作数、目的操作数交换数据

    • XCHG指令用于交换两个操作数。这条指令实际上起到了三条MOV指令的作用, 指令中的两个操作数可以是两个寄存器操作数或一个寄存器与一个存储器操作数。
    • 交换指令可实现通用寄存器之间、通用寄存器与存储单元之间的数据(字节或字)交换。
  • 示例

    ;例 3.24
    XCHG  AL, BL 
    ;(AL)与(BL)寄存器的字节型数据进行交换
    
    XCHG  BX, CX 
    ;(BX)与(CX)寄存器的字型数据进行交换
    
    XCHG  DS: [2200H], DL	
    ;(DL)与地址DS:2200H的内容进行交换,(DH)与地址DS:2201H的内容进行交换
    
    
  • 使用交换指令时应注意以下两点:

    • 两个操作数不能同时为存储器操作数。
    • 任一个操作数都不能使用段寄存器, 也不能使用立即数。

I/O指令

  • 输入指令

    • 指令格式:IN 累加器,端口( IN AX/AL, I/O地址 )

    • 指令功能:把一个字节/字由输入端口传送到AL/AX中。

    • 示例

      ;例 3.25
      IN   AL, 21H              ;将端口21H的8位数读到AL
      MOV  DX, 201H
      IN   AX, DX          ;将端口201H和202H的16位数读到AX中 
      
      
  • 输出指令

    • 指令格式:OUT 端口,累加器 ( OUT I/O地址, AX/AL )

    • 指令功能:把AX中的16位数或AL中的8位数输出到指定端口。

    • 示例

      ;例 3.25
      OUT 22H, AL        ;将AL中的数据传到端口22H
      MOV DX, 511H
      OUT DX, AX      ;将AX的数据输到511H和512H端口 
      

取有效地址指令LEA

  • 格式:LEA 目的操作数,源操作数

  • 功能: LEA指令的作用是将有效地址(在这里指地址偏移值)送通用寄存器, 而不是将存储单元的内容送通用寄存器。

  • 在很多情况下, LEA指令可以用相应的MOV指令代替。

    LEA  BX,VARWORD
    MOV  BX,OFFSET VARWORD
    ;这两条指令的执行结果是完全一样的。
    ;区别在于后者用伪指令OFFSET, 由编译程序在编译时赋值;而前者在执行时赋值。
    
    
  • 注意:

    • 两个操作数不能同时为存储器操作数。
    • 任一个操作数都不能使用段寄存器, 也不能使用立即数。

装入地址指令 LDS

  • 指令格式:LDS dest,src ;将内存中连续4个字节内容送到DS和指定的通用寄存器

  • 指令功能:

    • LDS指令把src操作数所指的内存中连续4个字节单元内容的低16位数据存入dest指定的通用寄存器中, 高16位存入DS中;
    • 从源操作数指定的存储单元中取出地址指针(4字节),低地址两个字节送入目的操作数,高地址的两个字节送入DS寄存器
    • LES指令把src操作数所指的内存中连续4个字节单元内容的低16位数据存入dest指定的通用寄存器中, 高16位存入ES中。
  • 注意:dest必须是通用寄存器之一, src必须是内存操作数

  • 示例

    ;例 3.29
    LDS  DI,[2130] ;将2130H和2131H单元的内容送DI
    ;将2132H和2133H单元的内容送DS
    
    

标志传送指令

  • 指令格式:
    • LAHF
    • SAHF
  • 指令功能:标志传送指令有取标志指令LAHF存标志指令SAHF, LAHF指令用于将标志寄存器的低8位送入AH, SAHF指令用于将AH的内容送入标志寄存器的低8位。

表转换指令XLAT

  • 指令格式:
    • XLAT label
    • XLAT ;AL← DS:((BX)+(AL))
  • 指令功能:XLAT指令以转换表中的一个字节来代换AL寄存器中的内容, 可用于码的转换。其中DS:BX指向转换表的首址, 转换前AL内容为序号, 转换后AL内容为对应的码。
; 例如, 将ASCII码转换为EBCDIC码, 也可用于代码加密。
有关程序段如下:
SUB   AL, ‘0’      ;将AL中ASCII字符转换成表XMIT_TABLE中的序号
LDS   BX, TAB_POINT    ;将表头地址指针送DS:BX
XLAT  XMIT_TABLE     ;查转换表, 将对应的加密码放入AL
OUT   42H, AL    ;从42H端口输出加密后的ASCII码
TAB_POINT  DD XMIT_TABLE
XMIT_TABLE DB ‘5791368024’

堆栈操作指令

  • 堆栈是向下生成的, 并且栈顶是满的。也就是说, 压栈操作是先将SP减2, 再将数据压入SS:SP指向的单元;弹出操作则先将SS:SP指向的数据弹出, 再将SP加2。

  • 指令格式:

    • PUSH src
      • 功能: 将源操作数压入堆栈
      • 过程: SP新 <— SP原-2 ,再入栈
    • POP dest
      • 功能: 将堆栈中数据弹出至目的操作数
      • 过程: 出栈, SP新 <— SP原+2
  • 指令功能:

    • PUSH指令用于压入存储器操作数, 寄存器操作数或立即数。注意, src和dest为16位的寄存器或存储单元, 图3.6 给出了进栈和出栈操作示意图。
    进栈和出栈操作示意图
    进栈和出栈操作示意图
    • 使累加器(AL)中的一个值变换为内存表格中的某一个值,一般用来实现代码转换,即查表功能。
  • 示例

    ;例 3.32
    PUSH  AX                       ;将AX的内容压入堆栈
    PUSH  [2000]  ;将DS段逻辑地址为2000H的内容压入堆栈
    ;POP指令与PUSH指令相反, 将栈顶的数据弹出到通用寄存器或存储器中。
    
    ;例 3.33
    POP AX              ;将栈顶的内容, 弹出到AX寄存器
    POP M_ADD           ;将栈顶的内容, 弹出到M_ADD指定的存储器中
    
    
  • 注意:

    • PUSHPOP指令只允许按字访问堆栈, 即两类指令的操作数必须是16位寄存器或存储单元的操作数。
    • CS不能作为目的操作数
算术运算指令

加法类指令

  • 不带进位的加法指令

    • 指令格式:ADD dest,src ;dest←(dest)+(src)
    • 指令功能:ADD指令用来对源操作数和目的操作数字节或字相加, 结果放在目的操作数中。
    • 说明:
      • ADD指令不允许两个存储器单元内容相加, 两个操作数不能同时为存储器操作数
      • ADD指令也不允许在两个段寄存器之间相加
      • 对标志位有影响, 主要是CF、ZF、OF、SF标志位
  • 带进位标志的加法指令

    • 指令格式:ADC dest,src ;dest←(dest)+(src)+(CF)
    • 指令功能:ADC指令和ADD指令的功能类似, 区别在于ADC在完成两个字或2个字节数相加的同时, 还要考虑进位标志CF的值, 若进位位CF为1, 则将结果加1。
    • 注意:src源操作数和 dest目的操作数不能同时为存储单元。段寄存器不能进行算术运算。
  • 示例

    ;例 3.39
    ;有两个4字节数分别放在FIRST和SECOND开始的存储区, 低字节在低地址处, 
    ;编写一程序将两数相加, 并将结果存入FIRST开始的存储区。
    MOV  AX, FIRST             ;第一个数的低16位→AX
    ADD  AX, SECOND           ;两数的低16位相加→AX
    MOV  FIRST, AX             ;低16位相加结果存入FIRST及FIRST+1单元
    MOV  AX, FIRST+2           ;第一个数的高16位→AX
    ADC  AX, SECOND+2         ;两数的高16位连同低16位进位相加→AX
    MOV  FIRST+2, AX           ;高16位相加的结果存入FIRST+2及FIRST+3单元
    
    
  • 加1指令

    • 指令格式:INC reg/mem ;reg/mem←(reg)/(mem)+1
    • 要求:reg为8位或16位通用寄存器, mem为8位或16位存储单元
    • 指令功能:将源操作数加1, 再送回该操作数。这条指令一般用于循环程序的指针修改, INC指令只有一个操作数。
    • 说明:
      • 操作数可以是寄存器或存储单元, 但不能为立即数
      • INC指令影响标志位AF、OF、PF、SF和ZF, 但不影响CF位
      • INC指令将操作数视为无符号数。

减法类指令

  • 不带借位的减法指令

    • 指令格式:SUB dest, src ;dest←(dest)−(src)
    • 指令功能:将目的操作数减去源操作数, 结果送到目的操作数, 并根据结果设置标志。
    • 说明:
      • SUB指令不允许两个存储器单元内容相减, 两个操作数不能同时为存储器操作数。
      • SUB指令也不允许在两个段寄存器之间相减。
      • 对标志位有影响, 主要是CF、ZF、OF、SF
  • 带借位的减法指令

    • 指令格式:SBB dest, src ;dest←(dest)-(src)-(CF)
    • SBB指令与SUB指令的功能相似, 区别是SBB在完成字节或字相减的同时, 还要减去借位CF。
    • 说明:
      • src源操作数和 dest目的操作数不能同时为存储单元。
      • 段寄存器不能进行算术运算。
  • 减1指令

    • 指令格式:DEC reg/mem ;reg/mem←(reg)/(mem)-1

    • 减1指令只有一个操作数。操作数可以为寄存器或者存储单元, 不能为立即数。该指令实现将操作数中的内容减1, 又叫减量指令。

      ;例 3.43
      DEC  CX                         ;(CX)←(CX) - 1
      DEC  DS:[100H+2] ;将数据段DS偏移地址100H+2所指单元内容
      ;减1, 结果送回该单元
      注意:DEC指令和INC指令一样, 执行后对CF不产生影响。
      
  • 取补指令

    • 指令格式:NEG reg/mem ;reg/mem←0-(reg)/(mem)

    • 指令功能:将操作数取补后送回源操作数, 即将操作数连同符号逐位取反, 然后在末位加1, 适用于操作数在机器内用补码表示的场合。 NEG指令的操作数可以是8位或16位通用寄存器和存储器操作数, 不能为立即数。

    • 示例

      • 例 3.44
        MOV  AL, 00000001B	               ;AL=00000001B
        NEG  AL                             ;将AL中的数取补, AL=11111111B
        NEG  WORD PTR [SI+1]                ;将SI+1、SI+2单元中的内容取补
        
  • 比较指令

    • 指令格式:CMP dest, src ;(dest)−(src)

    • 指令功能:将目的操作数与源操作数相减, 不送回结果, 只根据结果置标志位。

    • 示例

      例 3.45
      CMP  AX,BX                 ;将AX-BX后, 置标志位
      CMP  AL,20H              ;将AX-20H后, 置标志位
      
    • 说明:

      • 本指令通过比较(相减)结果置标志位, 表示两个操作数的关系。比较有以下几种情况, 以CMP A,B为例说明。

      • 判断两个操作数是否相等:可根据ZF标志位判断, 若ZF=1, 说明A=B;若ZF=0, 说明A≠B。

      • 判断两个操作数的大小:

        • 判断两个无符号操作数的大小:可根据CF标志位来判断, 若CF=1, 说明A<B;若CF=0, 说明A≥B。
        • 判断两个带符号操作数的大小:可根据SF及OF标志来判断, 若SF⊕OF=1, 即SF与OF不同时, 说明A<B;若SF⊕OF=0, 即SF与OF相同时, 则A≥B。

乘除法了解即可 (不做要求)

指令格式作用过程对标志位影响
MUL OPS无符号数乘法字节乘法: (AL)×(OPS)→AX 字乘法: (AX)×(OPS)→(DX, AX)影响CF、OF
IMUL OPS有符号数乘法字节乘法: (AL)×(OPS)→AX 字乘法: (AX)×(OPS)→(DX, AX)同上
CBW将AL的内容从字节扩展为 字, 存放到AX。若AL中数据的最高位为0, 则(AH)=00H; 若AL中数据的最高位为1, 则(AH)=0FFH。
CWD将AX的内容从字扩展为双 字, 存放到DX、AX。若AX中数据的最高位为0, 则(DX)=0000H; 若AX中数据的最高位为1, 则(DX)=0FFFFH。
DIV OPS无符号数除法字节除法:(AX)/(OPS)→AL(商), AH(余数) 字除法: (DX, AX)/ (OPS)→AX(商), DX(余数)除0会产 生溢出中 断
IDIV OPS有符号数除法字节除法: (AX)/(OPS)→AL(商), AH(余数) 字除法: (DX, AX)/ (OPS)→AX(商), DX(余数)
AAA/AAS加法/减法非压缩BCD码调 整若AL的低4位大于9或AF=1, 则自动将AL的内容 加06H, AH内容加1并置AF=CF=1, 将AL的高4 位清零 若AL的低4位小于或等于9, 则仅将AL的高4位清 零, 并AF→CF
DAA/DAS加法/减法压缩BCD码调整若AL的低4位大于9/AF=1, 则AL的内容加06H, 并 AF位置1 若AL的高4位大于9, 则AL的内容加60H, 并CF
逻辑运算

化为8421码, 按位 与/或/非/异或

NOT 目的 源按位取反
AND 目的,源目的 与 源→目的
OR 目的,源目的 或 源→目的
XOR 目的,源目的 异或 源→目的
TEST 目的, 源目的 与 源, 并修改标 志位, 但不回送结果
移位指令 (简单看看)
2022-11-06_190346image-20221106190951704image-20221106191111469
控制转移指令

修改IP,CS

  1. 无条件转移JMP (分类了解)

    • 段内直接转移JMP 目标标号
    • JMP NEAR PTR 目标标号
    • 段内直接短转移 JMP SHORT 目标标号
    • 段内间接转移 JMP WORD PTR OPD
    • 段间直接转移JMP FAR PTR 目标标号
    • 段间间接转移 JMP DWORD PTR OPD
  2. 条件转移 ★★

    • 检测单个标志位标志

      image-20221106200453240
      image-20221106200453240
  3. 循环控制指令 ★

    • LOOP 标号

      • 功能:每执行一次LOOP指令, CX的内容减1, 若(CX)≠0, 则循环转移到标号所 指定的目标地址去重复执行程序, 直到(CX)=0, 退出循环, 接着执行LOOP指令 的下一条指令。

        ;例: 
        MOV CX, 0100H		;设置循环次数
        DELAY: LOOP DELAY
        
    • 相等/为零计数循环指令

      • 格式:LOOPE/LOOPZ 标号
      • 功能:每执行一次循环指令, CX的内容减1, 若(CX)≠0且ZF=1, 则循环转移到 标号所指定的目标地址去重复执行程序, 否则执行循环指令的下一条指令。 处理器控制指令
    • 不相等/不为零计数循环指令

      • 格式:LOOPNE/LOOPNZ 标号
      • 功能:每执行一次循环指令, CX的内容减1, 若(CX)≠0且ZF=0, 则循环转移到标号 所指定的目标地址去重复执行程序, 否则执行循环指令的下一条指令。
    • 调用指令:CALL 标号

    • 返回指令:RET

中断指令
  • 软中断指令
    • 格式:INT n
    • 功能:
      • n为中断类型码, 可以取0~0FFH之间的256个值。每个中断类型码在中断矢 量表中占4个字节, 前两个字节用来存放中断服务程序入口地址的偏移地址, 后 两个字节用来存放段基址。
      • CPU执行INT指令时, 首先将标志寄存器FR 入栈, 接着清除IF、TF, 然后将当前 程序断点的段基址和偏移地址入栈保护, 最后将中断矢量表中与中断类型码对应 的4个字节内容先后送入IP、CS, 这样CPU转去执行中断服务程序
  • 中断返回指令
    • 格式:IRET
    • 功能:放在中断服务程序的出口处, 由它从堆栈中弹出程序断点分别送IP、CS, 并弹出一个字送标志寄存器FR, 以退出中断, 返回到断点处执行后续程序。 中断服务程序的最后一条指令必须是IRET

第4章 80X86汇编语言程序设计 (填空)

概述(了解)

语句的类型

  • 硬指令语句(指令性语句)

    • 是指能产生目标代码, CPU可以执行的, 能完成特定功能的语句, 它主要由CPU指令组成。
  • 伪指令语句(指示性语句)

    • 是一种不产生目标代码的语句, 它仅仅在汇编过程中告诉汇编程序应如何汇编。
    • 定义变量, 定义过程, 给变量分配存储单元, 给数字或表达式命名等。所以伪指令语句是汇编程序在汇编时用的, 不产生机器码。
  • 宏指令语句 它是一个指令序列, 汇编时凡有宏指令语句的地方都将用相应的指令序列的目标代码插入。

指令性语句是计算机可执行的,而伪指令不能执行,用来定义变量,分配存储单元,指示程序开始和结束等。

这两种语句的差别:

  • 在形式上:带不带冒号,是否可转向它.

  • 在本质上:汇编时能否形成对应的机器码

基本知识

汇编语言有三种基本语句:指令语句、伪指令语句、宏指令语句

指令语句的格式为:

[标号:] 硬指令助记符  操作数, 操作数	;注释

  • 指令语句的基本要求
    • 指令语句的基本要求
      • 标号是指令的符号地址,必须以英文“:”结尾,是选顶。8086/8088汇编语言中使用的标号必须遵循下列规则:
        • 字母(a~z, A~Z) ,数字(0~9)或某些特殊字符(@、_、$、?等)组成;
        • 第一个字符必须是除数字外的字符形式;
        • “?”不能单独作为标号;
        • 标号的有效长度为31位。
      • 助记符是指令名称的代表符号,是指令语句中的关键字,不可省略。必要时可以在指令助记符的前面加上一个或多个“前缀”,实现某些附加操作。
      • 操作数是指令执行需要的数据。有些指令不需要操作数,可以默认;有些指令需要多个操作数,必须以英文“,”将其隔开;>操作数可以是表达式。
      • 注释是对指令功能加以说明,方便阅读和理解程序,汇编程序不对它进行任何处理。>是可选项;注释必须用英文“;”开头(单条语句)

伪指令语句的格式为:

名字  伪指令助记符  参数, 参数….  ;注释

  • 伪指令语句的基本要求

    • 符号名是一个任选字段,符号名后面不能用冒号“:"以区别于指令语句。不同伪指令的符号名可以是常量名、变量名、过程名、结构名、记录名等,可以作为指令语句和伪指令语句的操作数,此时符号名就表示一个常量或存储器地址;

    • 伪指令字段是语句不可或缺的部分;

    • 操作数的有无、个数、操作数类型等由伪指令字段具体确定。操作数可以是常量(数值和字符)、常量名、变量、标号,以及一些专用符号;

    • 注释字段的格式和作用与指令语句时相同。

汇编语言源程序文件可以用以下两种格式书写:

  • 第一种格式是从MASM 5**.**0开始支持的简化段定义格式(但其中的两个指令 **.**startup和 **.exit是6.**0版本才引入的)。

  • 第二种格式是MASM 5**.**0以前版本就具有的完整段定义格式。

完整段格式定义方式

;Step1:定义数据段
DATA SEGMENT
   ...
DATA ENDS


; Step2:   定义堆栈段(可选)
STACK SEGMENT
   ...
STACK ENDS
 ;Step3:定义附加段(可选)
EXTRA SEGMENT
  …
EXTRA ENDS


; Step3 : 定义代码段
CODE SEGMENT 
   ASSUME CS:CODE,DS:DATA,SS:STACK     ;明确段与段寄存器的关系

START:  MOV AX,DATA
              MOV DS,AX
 
              MOV AX,STACK
              MOV SS,AX
              MOV SP,?H      ; ?为堆栈大小, 注意2倍关系
               ...
              ; MOV AH,4CH   ;或者 MOV AX,4C00H
             INT 21H 
CODE ENDS
END START

MASM汇编语言表达式、运算符

常量

  • 数字常量

    • 二进制常量,以B结尾
    • 十进制常量,以D结尾或省略(汇编语言中默认无标记数为十进制数)
    • 十六进制常量,以H结尾,如0A8C6H.
  • 字符串常量

    • 用单引号引起来的字符或字符串也代表常数。 例:’A’,’BCDE’,汇编时被翻译成对应的ASCII码41H和42H,43H,44H,45H。
    • 字符串最大长度为255个字符
  • 符号常量

    • 利用一个标识符表达的一个数值。常数若使用有意义的符号名来表示, 可以提高程序的可读性, 同时更具有通用性。

    • --比如C语言的#define PI 3.14

    • MASM提供等价机制, 用来为常量定义符号名, 符号定义伪指令有“EQU”和“=”

    • TYPE运算符用来取存储器的单元类型,各单元类型对应值如下:(重点👿)

      存储器单元类型对应值
      DB(字节)1
      DW(字)2
      DD(双字)4

其他运算符

  • 方括号[]

    • 指令中用方括号表示存储器操作数, 方括号里的内容表示操作数的偏移地址。

      ;例如:
      MOV  AX,[BX]	;将(BX)和(BX+1)指向的存储器两个单元的内容送AX
      
  • 段超越运算符“:

    • 运算符“:”(冒号)跟在某个段寄存器名(DS、ES、SS或CS)之后表示段超越, 用来指定一个存储器操作数的段属性, 而不管其原来隐含的段是什么。

      ;例如:
      M0V AX, ES:[DI]	;把ES段中由DI指向的字操作数送(AX)
      

变量定义伪指令

  • 变量是存储器中某个数据区的名字, 在指令中可以作为存储器操作数。

  • 变量定义伪指令可为变量申请固定长度的存储空间, 并可以同时将相应的存储单元初始化。该类伪指令是最经常使用的伪指令。

    伪指令格式: [变量名]  伪指令  初值表
    
  • 说明:

    • 变量名是用户自定义标识符, 表示初值表首元素的逻辑地址, 即用这个符号表示地址, 常称为符号地址。变量名可以没有, 这种情况, 汇编程序将直接为初值表分配空间, 无符号地址。设置变量名是为了方便存取它指示的存储单元。

    • 初值表是用逗号分隔的参数, 主要由数值常量, 表达式或 ?、DUP组成。其中?表示初值不确定, 即未赋初值;重复初值可以用DUP进行定义。DUP的格式为:

      重复次数  DUP(重复参数)
      
    • 变量定义伪指令有DB/DW/DD, 它们根据申请的主存空间单位分类,

定义字节单元伪指令DB (重点👿)

  • 功能:定义变量的类型为BYTE, 给变量分配字节或字节串。

  • 要求:初值表中每个数据一定是字节量(Byte), 可以是0~255的无符号数或是 −128~+127带符号数, 也可以是字符串常量。

    • ;例如:
      DATA SEGMENT ;数据段
          X 	DB ‘A’,  −5
              DB 2 DUP(100), ?
          Y 	DB ‘ABC’
      DATA ENDS
      
    • 存储器中的分配情况如图

      数据定义的存储形式
      数据定义的存储形式

定义字单元伪指令DW

  • 功能:定义变量的类型为WORD,给变量分配一个或多个字单元,并可以将它们初始化为指定值。

  • 要求:初值表中每个数据一定是字 (Word),一个字单元可用于存放任何16位数据,如一个段地址、一个偏移地址、两个字符、0~65535之间的无符号数或者是 −32768~+32767之间的带符号数。

    • ;例如:
      DATA		SEGM;数据段
         	COUNT		DW		8000H ,?,’AB’
          MAXINT		EQU	64H
          NUMBER   	DW		MAXINT
          ARRAY		DW		MAXINT DUP(0)    
      DATA		ENDS
      
  • 数据在存储器的分配情况如图所示

    字单元存储方式实例
    字单元存储方式实例

定义双字单元伪指令DD(了解即可)

  • 功能:定义变量的类型为DWORD,用于分配一个或多个双字单元,并将它们初始化为指定值。

  • 要求:初值表中每个数据是一个32位的双字 (Double Word),可以是有符号或无符号的32位整数,也可以用来表达16位段地址(高位字)和16位的偏移地址(低位字)的远指针。

    • ;例如:
      VARDD		DD	0,?,12345678H
      FARPOINT	DD	00400078H
      
  • 注意:在内存中存放时,低位字在前,高位字在后。

变量和标号的属性

变量、标号、段名及过程名都表示的是地址,那么,这些标号和名字一经定义便具有以下三种属性:

  • 段值:标号和名字对应存储单元所在段的段地址。
  • 偏移值:标号和名字对应存储单元所在段的段内偏移地址。
  • 类型:标号、子程序名的类型可以是NEAR(近)和FAR(远),分别表示段内或段间;变量名的类型可以是
  • BYTE(字节),WORD(字)和DWORD(双字)等。

标号和名称:标号和名称代表该语句的存储器地址

助记符和定义符:助记符例如ADDOR, 定义符例如SEGMENT

操作数:有常量、变量、标号、寄存器、表达式

变量:具有段属性、偏移量属性、类型属性, 类型有字节(BYTE) 、字(WORD)、双字(DWORD)等。

表达式:由常数、变量、操作符和运算符组成



有三种运算符:

  • 算术运算符:+(加)、-(减)、×(乘)、/(除)、MOD(取模)
  • 逻辑运算符:AND(与)、OR(或)、XOR(异或)、NOT(非)
  • 关系运算符:EQ(等于)、NE(不等于)、LT(小于)、GT(大于)、LE(小于等于)、 GE(大于等于)。 当关系不成立, 则结果为0; 当关系成立, 则结果为全1。

有两种操作符:

  • 分析运算符

    • 取地址偏移量运算符OFFSET

      • 格式:OFFSET 变量或标号

        ;例: 
        MOV SI, OFFSET BUF
        ;等价于 LEA SI, BUF
        ;注意:OFFSET后面只能是变量或标号。
        
    • 取段基址运算符SEG

      • 格式:SEG 变量或标号

        ;例:
        MOV AX, SEG BUF
        ;将BUF所在段的段基址送入寄存器AX。
        
    • 取类型运算符TYPE

      • 格式:TYPE 变量或标号
      • 该算符返回的结果为一数值。
    • 取变量单元数运算符LENGTH

      • 格式:LENGTH 变量
      • 如果一个变量已用重复操作符DUP说明其变量的个数, 则利用LENGTH算符可以 得到这个变量的个数。
      • 如果未用DUP说明, 则得到结果总为1。
    • 取变量字节数运算符 SIZE

      • 格式:SIZE 变量

      • 如果一个变量已用重复操作符DUP说明其变量的个数, 则利用SIZE算符可以得到 这个变量的字节总数。

      • 如果未用DUP说明, 则得到的结果和TYPE算

        符所得结果相同。

  • 合成运算符

    • 类型设置运算符PTR

      • 格式:类型 PTR 表达式

      • 其中类型可以是BYTE、WORD、DWORD、NEAR、FAR。该算符强制设置表达 式类型为算符前的规定类型。

        ;例: 
        MOV BYTE PTR [SI],  200
        

符号定义伪指令

  • 格式:符号名 EQU 表达式

    ;例: 
    A EQU 5*3+2
    

数据定义伪指令

  • 数据定义伪指令:用来定义一个变量, 为变量分配存储空间, 赋初值等。
  • 格式:[变量名] 数据定义符 表达式, 表达式
    • DB——字节
    • DW——字
    • DD——双字

数据定义伪指令

  • 表达式可以是以下几种:

    • 常量或常量表达式。
    • ASCII码字符或字符串。
    • 问号“?”表示初值未确定, 常用来预留存储空间。
    • 重复子句DUP格式为: N DUP (表达式) 其中N为重复次数, 括号内的表达式为重复的内容。
    • 地址表达式。即用变量名来表示的变量地址。
    ;例
    X1 DB 08H ;定义字节型变量X1
    BUF DW 01H,02H,03H,04H ;定义字型变量BUF
    
    ;例:
    BUF1 DB ‘HELLO’ ;定义字节型变量BUF1
    BUF2 DB ‘AB’	;
    BUF3 DW ‘AB’ 	;定义字型变量BUF3
    

段定义伪指令

常用的系统功能调用 (重点👿)

最为常用的五个DOS中断服务

最为常用的五个DOS中断服务
最为常用的五个DOS中断服务

顺序结构程序设计 (都得会👿)

汇编语言源程序主体(代码段)可以有顺序、分支、循环、子程序和宏等结构。

早期版本的汇编程序不直接支持结构化程序设计,可以用微处理器指令系统中的转移指令、循环指令、子程序调用及返回指令,实现程序的各种结构形式。

;例 求两个数的平均值。这两个数分别放在X单元和Y 单元中,而平均值放在Z单元中。
;根据题意,所设计的程序如下:
.MODEL	SMALL
.STACK
.DATA
X		DB	8CH
Y 		DB	64H
Z		DB	?
.CODE
.STARTUP
    MOV	AL,X		;AL←8CH
        ADD	AL,Y		;AL←8CH+64H
      MOV	AH,00H  	;AH←00H
        ADC	AH,00H 	;进位送AH
        MOV	BL,2    	;除数2→BL
        DIV	BL      	;AX除以BL的内容,
                        ;商→AL,余数→AH
        MOV	Z,AL   	;结果送入Z单元
            .EXIT 0
END

分支程序设计 (看得懂👿)

无条件转移指令

  • 指令格式:JMP dest

  • JMP reg/m16

  • 指令功能:JMP指令无条件地转移到指令所指定的目标地址,dest标号提供转移目的地址,或者由寄存器、存储器提供转移目的地址。

  • 根据目标地址相对于转移指令的位置,转移可分为短转移、段内转移和段间转移。

    • 短(SHORT)转移属于相对转移,指在段内短距离(−128~127)转移。

    • 段内(NEAR)转移指CS值不变,只给出地址偏移值的转移;这种转移的目标地址与转移指令都在同一段内。

    • 段间(FAR)转移指CS段值和IP值都发生改变的转移。在这种情况下,程序从一个段转移到另一段中的某一地址去执行,因此,JMP指令中要同时给出段值和偏移值。

  • 示例

    ;例 
    JMP  NEAR PTR TABLE[BX]    ;为段内转移,IP←[BX+TABLE][BX+TABLE +1]
    JMP  FAR PTR TABLE[BX]      ;为段间转移,IP←[BX+TABLE][BX+TABLE +1]
    ;         CS←[BX+TABLE+2][BX+TABLE +3]
    ;在16位寻址方式下,可以用WORD和DWORD来区分不带标号的转移是段内转移还是段间转移。
    ;例 3.60
    JMP  WORD PTR [BX]          ;为段内转移,IP←[BX][BX+1]
    JMP  DWORD PTR [BX]        ;为段间转移,IP←[BX][BX+1],CS←[BX+2][BX+3]
    
    ;例 
    DRVTBL  LABEL  WORD
    DW  DRV$INIT
    DW  MEDI$CHK
       		┇
    DW  ENTRY
       		┇   
    ENTRY:
    ┇
    MOV  AX,SEG DRVTBL
    MOV  DS,AX
    MOV  SI,NUMBER    ;NUMBER为表中ENTRY存储地址相对
                       ;DRVTBL的偏移量
    JMP  NEAR PTR DRVTBL[SI]
    
    

条件转移指令

  • 无符号数条件转移指令格式及其功能

    JA/JNBE label ;高于/不低于等于,条件满足则转移到label指定的地址。
    
    JAE/JNB label ;高于等于/不低于,条件满足则转移到label指定的地址。
    
    JB/JNAE label ;低于/不高于等于,条件满足则转移到label指定的地址。
    
    JBE/JNA label ;低于等于/不高于,条件满足则转移到label指定的地址。 
    
    JC label ;有进位,条件满足则转移到label指定的地址。
    
    JE/JZ label ;等于/为0,条件满足则转移到label指定的地址
    
    JNC label ;无进位,条件满足则转移到label指定的地址。
    
    JNE/JNZ label  ;不等于/不为0,条件满足则转移到label指定的地址
    
    JNP/JPOlabel ;非偶/奇,条件满足则转移到label指定的地址
    
    JP/JPE label  ;偶/偶,条件满足则转移到label指定的地址。
    
  • 带符号数条件转移指令格式及其功能

    JG/JNLE	label 	;大于/不小于等于,条件满足则转移到label指定的地址。
    
    JGE/JNL	label  	;大于等于/不小于,条件满足则转移到label指定的地址。
    
    JL/JNGE	label  	;小于/不大于等于,条件满足则转移到label指定的地址。
    
    JLE/JNG	label  	;小于等于/不大于,条件满足则转移到label指定的地址。
    
    JNO	    label  	;无溢出,条件满足则转移到label指定的地址。
    
    JNS	    label	;正数或0,条件满足则转移到label指定的地址。
    
    JO	  labe;溢出,条件满足则转移到label指定的地址。 (不考)
    
    JS	 label;负数,条件满足则转移到label指定的地址。 (不考)
    
    
  • 据CX中的值来决定转移的指令格式及其功能

    JCXZ label ;CX中的值为0,则转移到label指定的地址。
    

示例

  • 单分支结构

    ;例 计算AX中符号数绝对值的程序段。
             CMP	AX,0
             JGE	NONNEG  ;分支条件:AX≥0
             NEG	AX	  ;条件不满足,负数,
                              ;执行分支体进行求补
    NONNEG: MOV   RESULT,AX ;条件满足,
                             ;为正数,保存结果
    		CMP	AX,0
         	JL	YESNEG	;分支条件:AX < 0
         	JMP    NONENG     ;条件不满足,正数,
                            ;转向保存结果
    YESNEG:NEG AX          ;条件满足,为负数,
                            ;需要求补
    NONNEG:MOV RESULT,AX  ;保存结果
    ;选择分支条件不当,不仅多了一个JMP指令,而且也容易出错。
    
    
  • 作业2

    ;例 判断方程AX2+BX+C=0是否有实根,若有实根则将字节变量TAG置1,否则置0。假设A、B、C均为字节变量,数据范围为−128—+127。
        ;分析:二元一次方程有根的条件是:B2-4AC≥0。依据题意,首先计算出B2和4AC,然后比较两者大小,根据比较结果分别给TAG赋不同的值。
    
    
    

循环程序设计 (看得懂👿)

循环指令实际上也令LOOP是条件转移指令,它用存放在CX中的数作为循环重复计数值递减计数,直到CX中的数为0时终止循环。

LOOP循环指令

  • 指令格式: LOOP label
  • 指令功能:在执行LOOP指令时,处理器先将CX中计数值减1,再判其值:
    • 如果计数值不为0,则转到LOOP指令中指出的目标语句(执行循环体内的语句);
    • 如果计数值为0,则执行LOOP指令后的下条指令(退出循环)。如果CX的初值为0,则循环将进行 二的16次方 。

LOOPE/LOOPZ循环指令

  • 指令格式:
    • LOOPE label
    • LOOPZ label
    • LOOPE和LOOPZ是同一条指令的两种不同的助记符,其指令功能是:执行本指令时,将CX寄存器的内容减1并回送CX寄存器,ZF不受CX减1的影响。
    • 这两条指令执行后是否循环,依下述条件判断:
      • 如果CX≠0且ZF=1,则转移到目的标号执行,IP←IP(现行)+偏移量。
      • 如果CX≠0且ZF=0,则停止循环,按指令顺序执行。
      • 如果CX=0(无论ZF如何)停止循环,按指令顺序执行。
    • 注意:LOOPE/LOOPZLOOPNE/LOOPNZ指令对标志位没有影响

LOOPNE/LOOPNZ循环指令

  • 指令格式:LOOPNE/ LOOPNZ label

  • LOOPNE和LOOPNZ是同一条指令的两种不同的助记符,其指令功能:将CX寄存器的内容减1并回送CX寄存器,ZF不受CX减1的影响。

  • 判断是否循环的条件是:

    • 如果CX≠0且ZF=0,继续循环,转到目的标号执行,即IP←IP(现行)+偏移量。

    • 如果CX≠0且ZF=1,则停止循环,按指令顺序执行。

    • 如果CX=0停止循环,按指令顺序执行。

  • 注意:LOOPE/LOOPZ与LOOPNE/LOOPNZ指令对标志位没有影响

6. 输入输出接口及数据传输控制方式

接口的概念

接口(Interface)包括软件接口和硬件接口

软件接口

其一是指软件本身的狭义“接口”,是软件不同部分之间的交互接口。比如API——应用程序编程接口

其二是指人与软件之间的交互界面 -“用户界面”

硬件接口, 通常称为I/O接口

就是把外围设备同微型计算机连接起来的电路称为外设接口电路,简称外设接口。

接口的功能

它是以微处理器为基础,配以内存储器及输入输出(I/0)接口电路和相应的辅助电路而构成的裸机。

微机的接口一般有如下的几个功能:

(1)执行CPU命令的功能。

(2)返回外设状态的功能。

(3)数据缓冲的功能。

(4)设备寻址的功能。(例如前面讲的存储器自带地址解码器)

(5)信号转换的功能。(例如光驱将电信号ó光信号)

(6)数据宽度与数据格式转换的功能。

I/O端口及其编址方式

I/O端口I/O操作

  • 端口(Port)是指能被微处理器直接访问的接口电路中的寄存器的地址。微处理器通过这些地址(即端口)向接口电路中的寄存器发送命令、读取状态和传送数据。

  • I/O操作就是指对I/O端口的操作,即CPU所访问的是与I/O设备相关的端口,而不是I/O设备本身。

  • 计算机对外设的操作->就是对外设的接口电路的操作->就是对接口电路上的寄存器操作->就是对该寄存器的地址(端口)进行操作。(下一步的问题就是如何分配I/O端口的地址,或者说给定了I/O地址,如何和地址总线连接)

计算机对外设的操作->就是对外设的接口电路的操作->就是对接口电路上的寄存器操作->就是对该寄存器的地址(端口)进行操作。(下一步的问题就是如何分配I/O端口的地址,或者说给定了I/O地址,如何和地址总线连接)


CPU与外设数据的传输控制方式

CPU与外设之间传输数据的控制方式通常有三种:

  • 程序方式
    • 条件传送方式(查询方式) 👿
      • 查询式输入数据传送过程的4个步骤:
        • ①CPU先读取状态字
        • ②检查状态字是否表明数据准备就绪
        • ③如果准备就绪,则执行输入指令读取数据,
        • ④状态位清零。这样便开始下一个数据传输过程。
  • 中断方式
  • DMA方式

7. 串并行接口技术

可编程定时器计数器8253/8254

  • 工作方式: 👿
    • 方式0:计数到零产生中断请求。软件启动。
    • 方式1:硬件可重复触发的单稳态触发器。硬件启动。
    • 方式2:分频器。软、硬件启动。
    • 方式3:方波发生器(用得最多的方式)。软、硬件启动。
    • 方式4:软件触发选通。软件启动。
    • 方式5:硬件触发选通。硬件启动。

8251A 内部结构 👿

  • 接收器:包括接收缓冲器、串并转换逻辑和接收控制电路三个部分
  • 发送器:包括发送缓冲器、并串转换逻辑和发送控制电路三个部分。
  • 数据总线缓冲器。它用来与CPU的数据总线D0~D7相连。其中含有3个缓冲器:
    • ① 状态字缓冲器。它用来存放8251A内部的工作状态,供CPU查询、测试之用;
    • ② 接收数据缓冲器。用来存放接收器已经装配完毕的字符, 准备CPU来读取;
    • ③ 发送数据/命令缓冲器。 用来寄存CPU送入8251A的数据或命令。
  • 读/写控制逻辑电路。用以实现对CPU输出的控制信号译码,以控制实现如下表所示的读/写功能。
  • 调制/解调控制电路

编程

;计算1~100数字之和,并将结果存入字变量SUM中

.MODEL SMALL
.STACK
.DATA
		SUM DW ?
.CODE
.STARTUP
		XOR		AX,AX		;将被加数清零 异或
		MOV		CS,100
AGAIN:  ADD		AX,CS		;按100,99...,2,1倒叙累加
		LOOP	AGAIN
		MOV		SUM,AX		;将累加和送入指定单元
.EXIT 0
END
;两个32位加法
ASSUME CS:CODE
CODE SEGMENT
MOV AX,1234H
MOV BX,1234H
MOV CX,0ABABH
MOV DX,0ABABH
ADD BX,DX
ADC AX,CX
MOV AX,4COOH
INT 21H
CODE ENDS
END

参考

汇编与接口技术期末复习笔记(1)—— 汇编部分open in new window