文章目录

  • 0. 计组先导知识
    • 0.1 进位计数制
    • 0.2 计算机中数和字符的表示
  • 1. 基础知识
    • 1.1 汇编语言
    • 1.2 硬件接口
  • 2. 80x86计算机组织
    • 2.1 计算机系统
    • 2.2 8086微处理器
    • 2.3 存储器地址
    • 第1次作业
  • 3. 地址与指令
    • 3.1 寻址方式
      • 3.1.1 数据寻址方式
        • 3.1.1.1 立即数寻址
        • 3.1.1.2 寄存器寻址
        • 3.1.1.3 存贮器寻址
          • 直接寻址
          • 寄存器间接寻址
          • 寄存器相对寻址
          • 基址变址寻址
          • 相对基址变址寻址
      • 3.1.2 指令寻址
      • 第2次作业
    • 3.2 操作数寻址
      • 3.2.1 伪指令的功能与格式
      • 3.2.2 主要伪指令类型
      • 3.2.3 汇编语言程序格式
      • 3.2.4 汇编语言上机过程
      • 第3次作业
    • 3.3 8086的指令系统
      • 3.3.1 数据传送指令
        • 通用数据传送指令
        • 累加器专用传送指令
        • 地址传送指令
        • 标志寄存器传送指令
      • 3.3.2 算数指令
        • 加法指令
        • 减法指令
        • 乘法指令
        • 除法指令
      • 3.3.3 逻辑指令
        • 逻辑运算指令
        • 移位指令
      • 3.3.4 串处理指令
      • 3.3.5 控制转移指令
        • 无条件转移指令
        • 条件转移指令
        • 循环指令
        • 调用指令
        • 返回指令
        • 中断指令
        • 标识处理指令:
      • 3.3.6 处理机控制与杂项操作指令
      • 第四次作业
  • 4. 分支程序设计
    • 4.1 转移指令
    • 4.2 分支结构程序设计
      • 4.2.1 双分支结构
      • 4.2.2 多分支结构
      • 第五次作业
  • 5. 循环程序设计
    • 5.1 循环指令
    • 5.2 循环程序设计
      • 第六次作业
    • 6. 子程序结构
      • 6.1 调用格式
      • 6.2 调用过程
      • 6.3 子程序实例
      • 第七次作业
  • 7. BIOS 和DOS中断
  • 8. I/O端口地址译码技术
    • 8.1 I/O地址空间
    • 8.2 I/O 端口
    • 8.3 I/O 端口地址分配
    • 8.4 I/O 端口地址译码
    • 8.5 I/O 端口地址译码电路设计
      • 第八次作业

0. 计组先导知识

0.1 进位计数制

N进制数的表示:

例如一个16进制数的表示:

  • 十进制整数→非十进制整数
    除基取余法:
    【例】将233D转换为二进制数。
  • 十进制小数→非十进制小数
    乘基取整法:
    【例】将0.6875D转换为二进制数
  • 二进制数←→ 八进制数、十六进制数

0.2 计算机中数和字符的表示

  • 真值: 用+、-分别表示正、负的数称为真值

  • 机器数:数值化的方法来表示数符,通常用0表示正,用1表示负。

  • 原码:原码的最高位表示真值的数符,其余位为数值位,且与真值的数值位相同,必要时在数值位前加上前0。

  • 反码:正数的反码=原码;负数的反码=原码数值位取反。

  • 补码:当一个数为正数,则其补码就是该数本身;为负数,则其补码等于模值与该数绝对值之差。

    • 根据真值求补码:正数的补码=原码;负数的补码=原码数值位取反加1=反码+1。
    • 根据补码求真值:正数的真值=补码;负数的真值=补码数值位取反且末位加1 (补码的补码=原码)
    • 字符的表示:ASCⅡ码
  • 补码的加减法运算:补码加法规则 [X+Y]补=[X]补+[Y]补;补码减法规则:[X-Y]补=[X]补+[-Y]补


最高位向前位的进位同样自动丢失,而不影响运算的结

1. 基础知识

1.1 汇编语言

  1. 汇编语言的地位
  2. 汇编语言的特点
  • 面向机器的低级语言,具有专用性。
  • 保持了机器语言的优点,具有直接和简捷的特点。
  • 可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等。
  • 目标代码简短,占用内存少,执行速度快,是高效的程序设计语言
  • 经常与高级语言配合使用,应用十分广泛。
  1. 汇编语言的应用
    系统程序、高效率代码、I/O驱动程序
  • 很多系统软件是用汇编语言编写的。
  • 某些快速处理、位处理、访问硬件设备等高效程序是用汇编语言编写的。
  • 高级绘图程序、视频游戏程序一般是用汇编语言编写的。

1.2 硬件接口

  1. 接口发展的几个阶段
  • 无接口阶段(微型企业,老板与员工): CPU与外围设备直接相连,直接控制;信号线不兼容,效率低,复杂,速度不兼容,耦合性强,不易扩展等缺点。
  • 简单接口阶段(小型企业,老板,独立性很差的中层干部、员工):在CPU与外设间引入接口电路,可以使连接标准化;CPU(用户程序)通过接口对外设进行间接控制;
  • 复杂接口阶段(大中型企业,老板,独立性较强的中层干部、员工):接口电路通过复杂的接口协议软件可较为独立地控制外围设备,控制过程对外设用户不可见/不可控(即接口的底层,如总线驱动程序),PCI/USB等就是复杂接口。用户对外设的控制需由用户程序(接口的用户层)和底层设备如PCI总线的驱动程序(接口的底层)共同配合完成。
  1. 接口的功能
    (1)执行CPU命令
    接口电路对CPU发来的命令信息(在命令寄存器中,称为命令口)进行识别和分析,分解成若干个控制信号,传送到I/O设备,使其产生具体的操作。
    CPU不是直接把命令送到被控对象,而是通过接口电路进行控制。
    (2)返回外设状态信息
    接口执行CPU的命令后,将整个过程的状态存在接口的状态寄存器(状态口)中,供CPU读取。状态是:“忙”,“闲”,“就绪”,“错”等。
    (3)数据缓冲能力
    避免因速度的差异而丢失数据。接口中一般都有数据缓冲寄存器,称为数据口。数据缓冲器分为输入和输出缓冲器两种。
    (4)信号转换功能
    由于外设提供或需要的信号与CPU的总线不兼容,因此信号必须转换。
    (5)设备选择功能(大型的部门)
    微机系统中一般有多个外设,一个外设中也有多个端口,接口中必须有端口选择能力。
    (6)数据宽度与数据格式转换的功能
    如:并/串转换、串/并转换等。

  2. 接口的组成
    (1)接口逻辑电路
    包括:命令寄存器,状态寄存器,数据缓冲寄存器(数据收发速率不匹配时)。
    可编程大规模集成芯片中都包含这些电路。
    (2)端口地址译码电路
    作用是进行设备选择。需由用户自行设计。
    (3)附加电路
    需根据接口不同的任务和功能添加的功能模块电路。

  3. 接口的软件编程
    (1)初始化程序段
    对可编程接口芯片进行初始化,完成设置。
    (2)传送方式处理程序段
    传送方式的处理。如:查询,中断,DMA等传送过程中的处理程序。
    (3)主控程序段
    完成接口任务的程序段。
    (4)程序终止与退出程序段
    包括程序结束前对接口中硬件的保护程序段。
    (5)配置段
    包括人-机对话,菜单设计等内容。

  4. CPU与接口交换数据的方式
    查询方式,中断方式, DMA方式

  5. 接口电路的分析与设计基本方法(如何当好中层干部?)
    (1)两侧分析法
    凡是接口都有两侧,一侧是CPU,另一侧是外设。
    对CPU一侧就是三总线,因此分析比较容易主要搞清楚是什么类型的CPU以及数据总线、地址总线的宽度和控制线的逻辑定义,时序关系。
    对外设一侧情况很复杂,这是因为被控对象外设种类繁多,所提供的信号线五花八门;其逻辑定义,时序关系,电平高低差异甚大。要搞清两点:一是外设的信号引脚的功能定义和逻辑定义(外部表现),二是了解被控外设的工作过程(内部原理)。

(2)硬软结合法

  • 硬件设计方法(接口硬件有一定设计自由度)
    合理选用外围接口芯片。
    如有需要,需在接口芯片之外设计附加电路。
  • 软件设计方法(接口硬件固定)
    采用汇编语言(或高级语言)直接对底层硬件编程,多用于控制非微机标准设备。
    采用DOS功能调用和BIOS调用编程,多用于控制微机标准设备。
  1. 32微机上的接口
  • 微机接口是接口的一类,其它数字电路系统中CPU与外设之间也有接口
  • 特指低速I/O设备与本地总线如ISA之间的接口
  • PCI总线上的高速I/O设备、CPU总线上的主存/AGP等在本质上也是通过高速接口与CPU或总线桥接口电路相连的
  • 与16位微机相比,在总线结构上(for 扩展性、速度匹配等)、OS(for总线驱动程序)、存储管理机制(for I/O设备编址、访问保护等)上都有很大不同

2. 80x86计算机组织

2.1 计算机系统

2.2 8086微处理器

  1. 8086的基本性能指标
  • 16位微处理器
  • 16根数据线、20根地址线,可寻址的地址空间达1MB (220=1M) (因此其逻辑地址分为段地址和偏移地址)
  • 可以和浮点运算器、I/O处理器或其他处理器组成多处理器系统,从而提高系统的数据吞吐能力和数据处理能力。
  1. 8086的功能结构

  • 指令执行部件(EU)
    功能:负责指令译码、数据运算和指令执行(控制和执行指令)
    组成:算术逻辑运算部件ALU、EU单元控制系统、寄存器(所有的寄存器和数据线都是16位的)
    指令执行的两个主要阶段:取指和执行
    取指:EU不直接同外部总线相连,它从总线接口单元BIU的指令队列中获取指令
    执行:执行指令时,若需要访问存储器或外部设备,EU就向BIU发出操作请求,由BIU完成相应的操作。

  • 总线接口部件(BIU)
    功能:负责管理与系统总线的接口,负责对存储器和外设访问(预取指令和数据,总线 操作,信息传递)
    组成:指令队列、指令指针寄存器、地址加法器和总线控制逻辑

  • 8个16位寄存器分别为AX、BX、CX、DX、SP、BP、SI和DI,标志寄存器为FLAGS。

  • 指令预取

    • 8086处理器的指令读取,实际上是指令预取
      8086处理器维护着长度为6个字节的指令队列
      EU单元译码、执行指令,同时BIU单元读取后续指令
      BIU和EU两个单元相互独立,可以并行操作
    • 最简单的指令流水线技术,节省许多取指时间,提高了工作效率
  1. 8086的寄存器结构

    通用寄存器的一般用途

    通用寄存器的专门用途

控制寄存器

  • 指令指针寄存器IP
    保存将要执行的指令在主存的地址
    不能由指令直接修改
    发生程序转移、中断、异常时由处理器自动改变
  • 标志寄存器

特别说明:堆栈的两种访问方式:
随机访问方式:用BP寄存器来指示随机访问地址是内存!
先进后出访问方式:用SP寄存器来表示栈顶也是堆栈!

寄存器与存储器的比较

寄存器 存储器
在CPU内部 ,访问速度快 ,容量小,成本高 ,用名字表示,没有地址 在CPU外部,访问速度慢,容量大,成本低用地址表示,地址可用各种方式形成

标志寄存器 ( FLAGS/PSW )

  • FLAGS是一个16位的寄存器,共9个标志,其中6个状态标志,3个控制标志

    • 状态标志反映EU执行算术逻辑运算后的结果特征
    • 控制标志用来控制CPU的工作方式或工作状态

标志寄存器的格式以及各位的含义


状态标志——记录程序运行结果的状态信息
最基本的标志,有6个

  • 用来记录指令执行结果的辅助信息
  • 主要由加减运算和逻辑运算指令设置
  • 处理器主要使用其中5个构成各种条件,分支指令判断这些条件实现程序分支
  • 进位标志CF(Carry Flag)
    当加减运算的最高有效位有进位(加法)或借位(减法)时,CF=1,否则CF=0
    针对无符号整数,判断加减结果是否超出表达范围
    N个二进制位表达无符号整数的范围:0~2N−10~2^N-10~2N−1

例1:00111010+01111100= 10110110
最高位无进位, CF=0
例2:10101010+01111100 = [1]00100110
最高位有进位,CF=1

  • 溢出标志OF(Overflow Flag)
    有符号数加减结果有溢出则OF=1,否则OF=0
    针对有符号整数,判断加减结果是否超出表达范围
    N个二进制位表达有符号整数的范围:−2N−1~2N−1−1-2^N-1~2^{N-1}-1−2N−1~2N−1−1

例1:00111010+01111100 = 10110110
超出表达范围,OF=1
例2:10101010+01111100 = [1]00100110
未超出表达范围,OF=0

进位和溢出的区别

  • CF反映无符号整数运算结果是否超出范围
    有进位,加上进位或借位后运算结果仍然正确
  • OF反映有符号整数运算结果是否超出范围
    有溢出,运算结果已经不正确
  • 处理器按照无符号整数求得结果
    设置进位标志CF
    设置溢出标志OF
  • 程序员决定
    操作数是无符号数,关心进位
    操作数是有符号数,注意溢出

溢出标志的判断

  • 处理器硬件判断规则
    最高位和次高位同时有进位或同时无进位,无溢出;最高位和次高位进位状态不同,有溢出
  • 人工判断的简单规则
    只有当两个相同符号数相加(含两个不同符号数相减),而运算结果的符号与原数据符号相反时,产生溢出;其他情况下,不会产生溢出
  • 零标志ZF(Zero Flag)
    运算结果为0则ZF=1,否则ZF=0

例1:00111010+01111100 = 10110110
结果不是0,ZF=0
例2:10000100+01111100 = [1]00000000
结果是0,ZF=1

  • 符号标志SF(Sign Flag)
    运算结果最高位为1则SF=1,否则SF=0

例1:00111010+01111100 = 10110110
最高位为1,SF=1
例2:10000100+01111100 = [1]00000000
最高位为0,SF=0

  • 奇偶标志PF(Parity Flag)
    当运算结果最低字节中“1”的个数为零或偶数时,PF=1;否则PF=0

例1:00111010+01111100 = 10110110
“1”的个数为5个,PF=0
例2:10000100+01111100 = [1]00000000
“1”的个数为0个,PF=1

控制标志

  • 方向标志 DF(Direction Flag)
    仅用于串操作指令,控制地址的变化方向
    设置DF=0,每次串操作后的存储器地址就自动增加,即从低地址向高地址处理数据串
    设置DF=1,每次串操作后的存储器地址就自动减少,即从高地址向低地址处理数据串
    执行CLD指令设置DF=0
    执行STD指令设置DF=1

  • 中断允许标志IF(Interrupt-enable Flag)

  • 追踪标志TF(Trace Flag)

段寄存器
段是安排相关代码或数据的主存区域
段寄存器表明段在主存中的位置
3个16位段寄存器:CS DS SS

2.3 存储器地址

存储器的组织采用分段方式,20位的物理地址由16位的段地址和16位的偏移地址形成,每个段的最大寻址空间为64KB; 段地址必须是16的倍数,即末尾4位必须为0。

  1. 存储单元的地址和内容
  • 存储单元的地址
    将存储单元编号,这个编号就是存储器地址
    用十六进制数来表示地址
  • 存储单元的内容
    存储单元中存放的信息
    存储地址加括号“( )”(编程时用[])

字单元由两个字节单元组成,其地址采用它的低地址来表示。
字存入存储器:低位字节存入低地址单元,高位字节存入高地址单元。(小端存储)

因为地址一定是16位的,所以(0004H)对应的字内容是5678H
(5678H)可能是字单位或者字节单位,对应的值可能是1EH或者2F1EH

段地址和偏移地址
段地址:表示一个段的开始
偏移地址:在段内相对于段起始地址的偏移值
优点: 允许程序在存储器内重定位;有利于程序和数据的分离。

物理地址的形成
物理地址:每一个存储单元有一个唯一的20位地址
表示范围:00000H~FFFFFH 。
物理地址形成:段地址左移4位再加上偏移地址值

存储器的逻辑地址与物理地址

逻辑地址的形式:指令操作数,指令间的相对地址
物理地址:MEM的绝对地址
逻辑地址到物理地址的转换过程因CPU ARCH的不同而不同

存储器的分段
20 根地址线: 地址范围 00000H ~ FFFFFH (1MB)
机器字长16位:仅能表示地址范围 0000H ~ FFFFH (64KB)
小段:
小段的首地址 小段的尾地址
00000 H ~ 0000F H
00010 H ~ 0001F H
00020 H ~ 0002F H

FFFF0 H ~ FFFFF H
每16个字节为一小段,共有64K个小段
段起始地址:小段首地址

段地址与段寄存器
实模式下,在8086~Pentium微处理机中,代码段的段地址放在CS中;数据段的段地址放在DS中;堆栈段的段地址存放在SS中;附加段的段地址存放在ES中。
将CS,DS,SS,ES称为段寄存器

各段在存储器中的分配是由操作系统负责的。一般情况下,根据需求量分配。 注意:只有CS段寄存器是OS分配的,应用程序可读但不可写,其它的段寄存器都可以被修改。

隐含段和偏移寄存器
8086~Pentium微处理机中,段寄存器和偏移寄存器组合有一定规则。

偏移 主要用途
CS IP 指令寻址
SS SP或BP 堆栈寻址
DS BX,DI,SI或16位数 数据寻址
ES 串指令 目标串寻址

注意:当BX/BP与SI/DI组合作为偏移地址时,默认的段寄存器是BX/BP所在段的寄存器,而不是SI/DI所在段的寄存器。

例1:(DS) = 2100H, (BX) = 0500H
物理地址 = 21000H + 0500H = 21500H
例2:(CS) = 3000H, (IP) = 1000H
物理地址 = 30000H + 1000H = 31000H
例3:(SS) = 1000H, (SP) = 0010H
物理地址 = 10000H + 0010H = 10010H
例4:(DS) = 3100H, (SI) = 1000H
物理地址 = 31000H + 1000H = 32000H

第1次作业

  1. 有两个16位字1EE5H和2A3CH分别存放在微机存储器000B0H和000B3H单元中,请用图示表示出它们在存储器里的存储情况。

按照小段存储模式,低位字节放在低地址,高位字节放在高地址。且按照低地址的位置表示存储位置。故存储情况如下图所示:

  1. 微机存储器里存放的信息如右图示,试读出30022H和30024H字节单元的内容,以及30021H和30022H字单元内容。

30022H 字节单元内容 : AB H
30024H 字节单元内容 : EF H
30021H 字单元内容 : AB34 H
30022H 字单元内容 : CDAB H

  1. 在实模式下,段地址和偏移地址为3017H:000AH的存储单元的物理地址是什么?如果段地址和偏移地址是3015H:002AH和3010H:007AH呢?

段地址和偏移地址为3017H:000AH的存储单元的物理地址= 30170H+000AH =3017AH
段地址和偏移地址为3015H:002AH的存储单元的物理地址= 30150H+002AH =3017AH
段地址和偏移地址为3010H:007AH的存储单元的物理地址= 30100H+007AH =3017AH

  1. 如果在一个程序开始执行之前(CS)=0A7F0H(如果十六进制数的最高位为字母,则应该在其前加1个0),(IP)=2B40H,试问该程序的第1个字的物理地址是多少?

物理地址=0A7F00H+2B40H=0AAA40H

3. 地址与指令

3.1 寻址方式

寻址方式
为取得操作数或指令地址所使用的方法

  • 操作数寻址:与数据有关的寻址方式
  • 指令寻址:与转移地址有关的寻址方式

    8086汇编指令格式

3.1.1 数据寻址方式

(1)操作数包含在指令中——立即数寻址
(2)操作数在CPU的内部寄存器中——寄存器寻址
(3)操作数在存储器中 ——存储器寻址

3.1.1.1 立即数寻址

  • 立即数寻址——操作数在指令中
    MOV AX 1100H

    操作数从指令代码中立即得到,即立即数(Immediate),用常量形式直接表达
    因此操作数存储在代码段cs中。

3.1.1.2 寄存器寻址

  • 寄存器寻址——操作数在寄存器中
    MOV AX,BX
    操作数在寄存器中,不需要访问存储器,速度快

3.1.1.3 存贮器寻址

  • 存储器寻址

    • 操作数在存储器中,用存储单元的地址表示
    • 编程时使用包含段寄存器和偏移地址的逻辑地址
      段寄存器指示段基地址
      偏移地址由各种寻址方式计算,常被称为有效地址EA(Effective Address)
    • 一般情况下存储器地址由有效地址表示,段寄存器不用显式说明,数据在默认的段中。如果不使用默认段寄存器,则要用段超越指令前缀加以说明

(1) 段寄存器的默认和超越

访问存储器的方式 默认 可超越 偏移地址
取指令 CS IP
堆栈操作 SS SP
一般数据访问 DS CS、ES、SS、FS、GS 有效地址EA
一般数据访问 SS CS、ES、SS、FS、GS 有效地址EA
串操作的源操作数 DS CS、ES、SS、FS、GS SI
串操作的目的操作数 ES DI

(2) 偏移地址的组成
16位有效地址
EA=基址寄存器+变址寄存器+位移量
基址寄存器:BX或BP
变址寄存器:SI或DI
位移量:8或16位有符号值
一般情况下,由基址寄存器决定哪个段寄存器作为段指针(如果不使用段超越越前缀)

(3) 存储器寻址的5种方式

  1. 直接寻址
  2. 寄存器间接寻址
  3. 寄存器相对寻址
  4. 变址寻址
  5. 带比例的变址寻址
直接寻址
  • 指令中直接包含了操作数的有效地址EA,在指令操作码之后
  • 默认段地址在DS寄存器中,即操作数的实际地址是DS:EA
  • 常用于存取变量

试比较下列指令中源操作数的寻址方式(VARW是内存字变量):
MOV AX, 1234H MOV AX, [1234H] ;前者是立即寻址,后者是直接寻址
MOV AX, VARW MOV AX, [VARW] ;两者是等效的,均为直接寻址

1.直接地址可用数值表示,包括在[ ]之中,也可以用变量表示,例如:MOV AL,VALUE;这里,VALUE为变量,变量是有属性的,它由数据段中定义数据的伪指令确定(伪指令将在第4章介绍)。
2. 若操作数在代码段、堆栈段或附加段中,则应在操作数地址之前使用前缀指出段寄存器名,这种前缀称为段超越前缀.段超越前缀也可以用于其他存储器寻址方式中,以使得给定的段寄存器取代默认的段寄存器。
MOV AL,ES:[2000H]; 将ES段2000H单元的内容传入AL中
3. 直接寻址方式适合于处理存储器的单个单元。IBM-PC机中为了避免指令字的长度过长,规定双操作数指令除立即寻址方式之外必须有一个操作数使用寄存器或段寄存器,这就是一个变量常常先要送到寄存器中去的原因

寄存器间接寻址
  • 操作数的有效地址EA存放在基址寄存器(BP,BX)或变址寄存器(SI/DI)。不能放在AX\CX\DX中
  • 可以方便地对数组的元素或字符串的字符进行操作
  • 寄存器间接寻址没有说明存储单元类型

EA= (BX)/ (BP) / (SI) / (DI)
PA=16*(DS) + (BX)/(SI)/(DI)
PA=16*(SS)+BP


寄存器相对寻址
  • 有效地址是寄存器内容位移量之和
  • 适用于数组、字符串、表格的操作

有效地址=(BX)/(BP)/(SI)/(DI) + 8/16 位移量
例子:
MOV AL, [BP][80H]
MOV AL,[BP+80H]
MOV AX, ARRAY1[SI]
MOV ARRAY2[DI],AX

基址变址寻址
  • 有效地址是基址寄存器变址寄存器之和
  • 适用于二维数组、字符串、表格的操作
  • 必须是一个基址寄存器和一个变址寄存器的组合

有效地址=(BX)/(BP) + (SI)/(DI)
MOV AX, [BX][BP] 错误
MOV AX, [SI][DI] 错误

相对基址变址寻址

有效地址= (BX)/(BP)+ (SI)/(DI) +8/16位位移量。

  • 总结

3.1.2 指令寻址

  • 段内直接寻址
    转向的有效地址 = 当前(IP) + 位移量(8bit/16bit)

例: JMP NEAR PTR NEXT; 近转移 -32768 ~ +32767
汇编时,位移量为16位
JMP SHORT NEXT; 短转移 -128 ~ +127
汇编时,位移量为8位

  • 段内间接寻址

    • CS不变,但IP变化。转向的有效地址是一个寄存器或存储单元的内容。
    • 可用除立即数以外的任何一种数据寻址方式得到

例: TABLE = 20A1H (BX) = 1256H (SI) = 528FH (DS) = 2000H (232F7H) = 3280H (264E5H)= 2450H
JMP BX ; (IP)=1256H
JMP TABLE[BX]
JMP WORD PTR TABLE[BX] ; (IP)=3280H
JMP [BX][SI]
JMP WORD PTR [BX][SI] ; (IP)=2450H

  • 段间寻址
    CS与IP都变化(一般仅供OS使用)
    转向的有效地址是XXXX:YYYY形式

JMP 1234H:5678H ;
(CS)=1234H ,(IP)=5678H

第2次作业

1、现有(DS)=2000H,(BX)=0100H,(SI)=0002H,(20100)=12H,(20101)=34H,(20102)=56H,(20103)=78H,(21200)=2AH,(21201)=4CH,(21202)=0B7H,(21203)=65H,试说明下面各条指令执行后AX寄存器的内容。
(1)MOV AX,1200H
(2)MOV AX,BX
(3)MOV AX,[1200H]
(4)MOV AX,[BX]
(5)MOV AX,1100[BX]
(6)MOV AX,[BX][SI]
(7)MOV AX,1100[BX][SI]

Answer:

  1. 立即数寻址:1200H
  2. 寄存器寻址: 0100H
  3. 直接寻址:4C2AH
  4. 寄存器间接寻址:3412H
  5. 寄存器相对寻址:4C2AH
  6. 基址变址寻址:7856H
  7. 相对基址变址寻址:65B7H

2、假设(DS)=2000H,(ES)=2100H,(SS)=1500H,(SI)=00A0H,(BX)=0100H,(BP)=0010H,数据段中的变量名VAL的偏移地址值为0050H,试指出下列源操作数的寻址方式试什么?其物理地址值是什么?
(1)MOV AX,0BAH
(2)MOV AX,[100H]
(3)MOV AX,[BX]
(4)MOV AX,[BP]
(5)MOV AX,[BX+10]
(6)MOV AX,[BX][SI]
(7)MOV AX,BX
(8)MOV AX,VAL
(9)MOV AX,ES: [BX]
(10)MOV AX, [SI]
(11)MOV AX,VAL [BX]
(12)MOV AX,VAL [BX][SI]

Answer :

  1. 立即数寻址;物理地址不确定,因为立即数来自指令,而指令的地址不能确定
  2. 直接寻址;物理地址=100H+20000H=20100H
  3. 寄存器间接寻址:物理地址=0100H+20000H=20100H
  4. 寄存器间接寻址:物理地址=0010H+15000H=15010H (特别注意:BP是堆栈段指针,因此段地址是堆栈段地址)
  5. 寄存器间接寻址:物理地址=0100H+20000H+000AH=2010AH (特别注意:题目中的10是十进制,要转化位16进制0AH)
  6. 基址变址寻址:物理地址 =0100H+00A0H+20000H=201A0H
  7. 寄存器寻址: 无物理地址,因为来自于寄存器,寄存器没有物理地址
  8. 直接寻址:物理地址=20000H+0050H=20050H(特别注意:使用变量名的寻址属于直接寻址)
  9. 寄存器间接寻址:物理地址=21000H+0100H=21100H
  10. 寄存器间接寻址:物理地址=20000H+00A0H=200A0H
  11. 寄存器相对寻址:物理地址=0100H+20000H+0050H=20150H
  12. 寄存器相对基址变址: 物理地址=20000H+0050H+0100H+00A0H=201F0H

3.2 操作数寻址

3.2.1 伪指令的功能与格式

  • 汇编语言语句类型
    语句类型:
  1. 指令性语句:能够直接翻译成机器代码并让CPU直接执行的语句
  2. 指示性语句:指导汇编程序如何编译汇编语言的源程序,并不翻译成机器代码,CPU也不执行。
  • 汇编语句格式

    • 指令语句(处理器指令、硬指令)
      [名字:] 操作码 [操作数[,操作数]][;注释]
    • 伪指令语句(汇编程序命令、伪指令)
      [名字:]伪操作码 [操作数[,操作数]][;注释]

    [名字]:由用户按一定规则定义的标识符
    组成:英文字母、数字、特殊符号
    形式:标号和变量;
    [;注释]: 语句的说明部分
    [操作码]:含义:指明操作的性质或功能。
    书写规则:操作码与操作数之间用空格分开
    [操作数]: 含义:指定参与操作的数据。
    个数:一般指令,1个或2个,也可以没有;
    伪指令和宏指令,可以有多个。
    书写规则:操作数多于1个时,操作数之间用
    逗号分开

  • 伪指令的功能

    • 程序员提高编程效率
      数据定义及存储器分配伪操作,表达式赋值伪操作,地址计数器与对准伪操作
    • 指导编译器如何编译汇编程序
      选择处理器型号,定义存储模式,定义段,指示程序开始/结束

3.2.2 主要伪指令类型

  • 段定义
data segment; 定义数据段
...
data ends
stack segment; 定义堆栈段
...
stack ends
code segment; 定义代码段assume cs:code, ds:data, ss:stack
start:mov ax,datamov ds,ax;...
code endsend start
  • 指定段地址

ASSUME <段寄存器名>:<段名>[,<段寄存器名>:<段名>…]
功能:建立段寄存器与段的缺省关系

  • 设置段地址值
    在代码段开始处进行DS、SS、ES的段基址装填

例:MOV AX, DATA
MOV DS, AX
程序装入内存后,段寄存器的指向

  • 结束
    END(S) [ label ]

  • 数据的定义和存储器的分配
    [变量] 助记符 操作数[,操作数,…][;注释]
    助记符:DB DW DD DF DQ(64位) DT(80位)
    DB: 定义字节
    DW:定义字
    DD: 定义双字

例:
DATA_BYTE DB 10,4,10H,?
DATA_WORD DW 100,100H,-5,?

例:
ARRAY DB ‘HELLO’
DB ‘AB’
DW ‘AB’

例:操作数用复制操作符DUP,表示操作数重复若干次
VAR DB 100 DUP (?) # 占100个空位置
DB 2 DUP (0,2 DUP(1,2),3) # 0212302123

PAR1 DB 100,20H
PAR2 DW 300H,400H
ADDR_TABL1 DW PAR1,PAR2 ;存放偏移地址16位
ADDR_TABL2 DD PAR1,PAR2 ;存放偏移和段地址各16位

  • 表达式的赋值

    • 表达式名 EQU 表达式

ALPHA EQU 9
BETA EQU ALPHA+18

  • 表达式名=表达式

注意:EQU指令不占用内存空间!
如: BUF1 DW 1,2,3
INTT EQU 5
BUF2 DW 4,5,6
那么3和4的地址是连续的!

EQU与=的差异
同一个程序中“=”可以对一个符号重复定义,但EQU不能对同一个符号重复定义
Y1=7
Y1=128 √
Y1 EQU 7
Y1 EQU 128 ×

解除定义伪指令PURGE
格式:PURGE <符号1,符号2,…,符号n>
功能:解除指定符号的定义
例:
Y1 EQU 7
PURGE Y1
Y1 EQU 128

  • 地址计数器和对准伪操作

    • 在代码段,$表示当前正在汇编的指令的地址

ORG $+8 ; 跳过8个字节的存储区
JNE $+6 ; 转向地址是 JNE 的地址 +6
JMP $+2 ; 转向下一条指令

  • 在数据段,$表示当前地址计数器的值

ARRAY DW 1, 2 , $+4 , 3 , 4 , $+4

  • 地址计数器$的常用使用方法: 常用来确定数组中元素的个数

例:BUF1 DB 1,2,3,4,5
CNT1 EQU $ -BUF1 (常用)
BUF2 DW 1,2,3,4,5
CNT2 EQU ($-BUF2)/2
CNT1、CNT2分别为数组BUF1、BUF2中数据元素的个数

  • ORG 伪操作
    指明下一条汇编语句的偏移地址 ,本身不占内存空间
  • 表达式操作符
    在指令中出现,主要是对常量进行运算
    (1) 算术操作符: +、-、*、/、Mod
    (2)逻辑和移位操作符:
    AND(与)、OR(或)、XOR(异或)、NOT(非)、SHL(左移)、SHR(右移)
    (3)关系操作符
    EQ(相等)、NE(不等)、LT(小于)、LE(小于或等于)、GT(大于)、GE(大于或等于)
    (4) 数值回送操作符
    OFFSET、SEG、LENGTH、SIZE
    OFFSET / SEG 变量 / 标号
    功能:回送变量或标号的偏址 / 段址
    如MOV DX,SEG FUNC
    LENGTH 变量
    功能:回送由DUP定义的变量的单元数(最外层的DUP定义的数量),其它情况回送1
    SIZE 变量
    功能:LENGTH * TYPE ;DB的TYPE值为1,DW的TYPE值为2

例:
ARRAY DW 100 DUP (?)
TABLE DB ‘ABCD’
MOV CX, LENGTH ARRAY ; MOV CX, 100
MOV CX, LENGTH TABLE ; MOV CX, 1
MOV CX, SIZE ARRAY ; MOV CX, 200
MOV CX, SIZE TABLE ; MOV CX, 1

(5) 属性修改的伪指令: PTR
用于暂时改变内存变量或标号的原有属性,但不能修改寄存器的原有属性
格式: 新属性 PTR (旧属性的)表达式
MOV WORD PTR [BX], 5

PTR指令的应用场合
1、有一些指令中,操作数或表达式的属性是不明显
的,需要加以明确,如:
例:CALL DWORD PTR [BX] ;远调用
CALL BYTE PTR [BX] ;段内近调用
2、需要修改操作数或表达式的属性的,如:
例:F1 DW 1234H
MOV AL,BYTE PTR F1 ;AL=34H
例:F2 DB 23H,56H,18H
MOV BX,WORD PTR F2 ;BX=5623H

  • (6) 定位类型的伪指令: PARA
    para (Paragraph,节)表明该段起始地址对齐到para,供OS使用
    一般说来,各个逻辑段的首地址在‘节’的整数边界上(每16个存储单元叫做一节, 1para = 16Bytes),即每个逻辑段的起始地址是16的整数倍,或地址的最低4位为0。

例如: code segment para ‘code’

3.2.3 汇编语言程序格式

  • 汇编语言源程序结构
    完整段定义结构:用段定义伪指令
  • 汇编语言前缀结构
    把整个程序定义成一个FAR型过程(或子程序),该过程能够让其它汇编文件中的段来调用,而near则不能。
  • 代码段中程序的两种结束方式

3.2.4 汇编语言上机过程

  1. 程序运行步骤以及生成的文件
  2. 建立、运行汇编语言程序
  3. 汇编程序功能
    汇编程序的主要功能:
    检查源程序,给出出错信息
    产生目标文件(.obj)和列表文件(.lst)
    展开宏指令

第3次作业

1、画图说明下列语句所分配的存储空间及初始化的数据
(1)AA DB ‘BYTE’,12,-12H, 3 DUP(0,?,2 DUP(1,2),?)
(2)BB DW 5 DUP(0,1,2),?,-5,‘BY’, ‘TE’,256H

(1) 如下图

(2)如下图(注意: 左边为低地址,右边为高地址)

2、假设程序中的数据定义如下:
PARTNO DW ?
PNAME DB 16 DUP(?)
COUNT DD ?
PLENTH EQU $-PARTNO
问PLENTH的值是多少?它表示什么意义?

PLENTH的值为2+16+4=22=16H
表示PARTNO、PNAME、COUNT 这三个变量所占用的字节数的和 (即这段代码之前数据段的长度)

3、请设置一个数据段DATASG,其中定义以下变量
(1)FLD1为字符串变量:‘computer’
(2)FLD2为十进制字节变量:32
(3)FLD3为十六进制字节变量:20
(4)FLD4为二进制字节变量:01011001
(5)FLD5为10个0的字节变量
(6)FLD6为数字的ASCII字符字节变量32654
(7)FLD7为包括5个十进制数的字变量:5,6,7,8,9
(8)FLD8为100个字变量

DATASG SEGMENT
FLD1 db  'computer'
FLD2 db 32
FLD3 db 20H
FLD4 db 01011001B
FLD5 db 10DUP(0)
FLD6 db '32654'
FLD7 dw 5,6,7,8,9
LFD8 dw 100DUP(?)
DATASG ENDS

易错点总结

  1. 汇编语言源程序中的数字,默认是十进制,因此使用十六进制的数字的时候,必须有h或H后缀
  2. 字符、字符串、字节数值数组都是用DB定义。一个字符占一个字节的方式,顺序依次存储的。
// 汇编程序:
mov al,'a'
mov ax,'a'
mov ax,'ab'
//执行后的结果
al = 61h
ax = 0061h
ax = 6162h

参考博客

3.3 8086的指令系统

3.3.1 数据传送指令

通用数据传送指令

传送指令MOV DST, SRC
执行操作:(DST)<-(SRC)

注意:

  1. DST,RST 不能同时为段寄存器
  2. 立即数不能直接送至段寄存器
  3. 不能使用AX、CX、DX存放EA
  4. DST不能是立即数和CS (CS和IP寄存器的修改只能使用JMP XX:YY指令进行修改,不能用MOV指令修改。通常来说,CS都是由OS分配的,应用程序不能对其进行修改。)
  5. DST 和SRC不能同时为存储器寻址,因为两者的位宽是否匹配不确定
  6. 不影响标志位(对所有的数据传输指令而言)

进栈指令PUSH SRC
执行操作: SP <- SP – 2 ; (SP+1), (SP) <-(SRC)
出栈指令POP DST
执行操作:(DST) <- (SP+1), (SP) ; SP <- SP + 2

堆栈:“先进后出”的存储区。段地址存放在SS中,SP在任何时候都指向栈顶,进出栈后自动修改SP
堆栈用于保存子程序返回地址和断点地址以及主程序通用寄存器内容的保护和恢复
因为堆栈遵从“后进先出”原则,在保存寄存器和恢复寄存器的内容时要按照相反的顺序执行一组压入和弹出指令。
8086/8088堆栈操作都是字操作,不允许对字节操作。例如:PUSH AH不是正确指令。

注意

  1. 堆栈操作必须以字为单位
  2. 不影响标志位
  3. 不能用立即寻址方式
  4. DST不能是CS (CS只能用JMP指令间接修改)

交换指令XCHG OPR1,OPR2
执行操作: (OPR1) <-> (OPR2)

注意

  1. 不影响标志位
  2. 不允许使用段寄存器和立即数
  3. 两个操作数必须有一个在寄存器中(内存之间不能相互传送数据,因为不知位宽是否匹配)

累加器专用传送指令

累加器专用传送指令(IN/OUT)

  • 只能使用AX或AL来存放数据,只限8位立即数或DX来存放端口号;
  • IN/OUT指令中AX(AL)操作数的位置是不同的,一个是目标操作数位置,另一个是源操作数位置;
  • IN/OUT指令操作期间,端口地址处将产生一个负脉冲信号

输入指令IN
执行操作: (I/O->CPU)
长格式: IN AL, PORT (字节) IN AX, PORT (字)
执行操作:AL <-(PORT) (字节)AX <- (PORT+1),(PORT) (字)

短格式: IN AL, DX (字节)IN AX, DX (字)
执行操作:AL <- (DX) (字节) AX <- (DX+1),(DX) (字)

输出指令 OUT
执行操作:(CPU -> I/O)
长格式: OUT PORT, AL (字节) OUT PORT, AX (字)
执行操作:(PORT) <- AL (字节) (PORT+1),(PORT) <- AX(字)

短格式: OUT DX, AL (字节) OUT DX, AX (字)
执行操作: (DX) <- AL (字节) (DX+1),(DX) <- AX(字)

注意:

  1. 不影响标志位
  2. 前256个端口号00H~FFH可直接在指令中指定(长格式)
  3. 如果端口号>= 256,端口号-> DX(短格式)

换码指令XLAT 或 XLAT OPR
执行操作:AL <- ( BX + AL )
功能:AL给出偏移量,然后存储该偏移地址处的内容

例子: MOV BX, OFFSET TABLE ; BX=0040H
MOV AL, 3
XLAT TABLE
指令执行后 AL=33H

注意

  1. 不影响标志位
  2. BX是16位寄存器,AL是8位寄存器,偏移地址AL只有8位二进制,所以表格的最大容量是256字节
  3. BX中存放段首地址,段首地址可以是DS,也可以是用户定义的DATA;
  4. xlat查表指令只能是字节操作;每次偏移一个字节;

地址传送指令

有效地址送寄存器指令LEA REG, SRC
执行操作:   REG<- SRC (将源操作数的有效地址EA传送给通用寄存器)
SRC:不能是立即寻址,寄存器寻址

MOV BX,0408H
MOV SI,2000H
LEA BP,[BX+SI+6]; 将240EH送BP, 而不是240EH单元的内容送BP

指针(地址的地址)送寄存器和DS指令LDS REG, SRC
执行操作: REG<- (SRC) : 将源操作数指定的存储单元中的双字(通常为段地址和有效地址)传送给DS及目的操作数,高两字节送DS,低两字节送目的操作数。
获取DS段的指针 DS<-(SRC+2)
相继二字-> 寄存器、DS

(DS)=30C0 H, 相关的存储区情况以及执行的指令的功能如下图:
LDS SI,[40H]

指针送寄存器和ES指令LES REG, SRC
执行操作: REG <-(SRC)
获取ES段的指针 ES <- (SRC+2)
相继二字 ->寄存器、ES

例子:

注意:

  1. 不影响标志位
  2. REG 只能是16位通用寄存器,不能是段寄存器,SRC 必须为存储器寻址方式
  3. LEA指令与LDS、LES指令所传送的有效地址有区别。LEA指令所传送的有效地址为源操作数的有效地址,而LDS及LES指令所传送的有效地址在源操作数所指的存储单元中

标志寄存器传送指令

(FLAGS为16位寄存器)
标志送AH指令LAHF
执行操作: AH <- (FLAGS的低字节) : 将标志寄存器低8位送AH。

AH送标志寄存器指令SAHF
执行操作: (FLAGS的低字节) <-AH : 将(AH)送标志寄存器低8位。

标志进栈指令: PUSHF (FLAGS的高和低两字节)
执行操作: (SP) <- (SP) - 2
( (SP)+1, (SP) ) <- (FLAGS)
 
标志出栈指令: POPF(FLAGS的高和低两字节)

执行操作: (FLAGS) <- ( (SP)+1, (SP) )
(SP) <- (SP) + 2

注意:
数据传送指令中仅SAHF及POPF影响标志寄存器的内容。

3.3.2 算数指令

有关符号位加减法指令中的OF
1、计算机中,当确定为有符号数运算时,符号数一律用补码表示,运算时符号位和数字位一起参加运算。
2、在加法/减法运算中的OF含义说明:
不溢出(OF=0),说明运算结果正确。
溢出(OF=1),说明运算结果错误。
3、OF=An‾⋅Bn‾⋅Sn+An⋅Bn⋅Sn‾O F=\overline{A n} \cdot \overline{B n} \cdot S_{n}+A n \cdot B_{n} \cdot \overline{S_{n}} OF=An⋅Bn⋅Sn​+An⋅Bn​⋅Sn​​
An、Bn分别代表两个加数符号位,Sn代表结果的符号位。
4、在加法/减法运算中的溢出情况总结:
异号数相加或同号数相减不会溢出(OF=0)。
同号数相加或异号数相减时有可能发生溢出(OF=1)。

加法指令

加法指令: ADD DST, SRC
执行操作: (DST) <- (SRC) + (DST)

带进位加法指令:ADC DST, SRC
执行操作: (DST) <- (SRC) + (DST) + CF

加1指令: INC OPR
执行操作: (OPR) <- (OPR) + 1

注意
除INC指令不影响CF标志外(硬件结构决定的),均对条件标志位有影响。

加法指令对条件标志位的影响:

CF 位表示无符号数相加的进位与否。
OF 位表示带符号数相加结果的正确与否

MOV DX,2000H;
MOV AX,8A04H
ADD AX, 9D00H
ADC DX,45H

此程序段实现多字节数20008A04H与459D00H的相加。DX存放有被加数的高两字节,AX存放有被加数的低两字节。ADD指令实现两数低两字节的相加,相加后(AX)=2704H,CF=1(相加结果超过两个字节)。ADC指令实现两数高两字节的相加,且将CF(即低两字节相加产生的进位)加至DX,使DX内容为2046H。

减法指令

减法指令SUB DST, SRC
执行操作: (DST) <- (DST) - (SRC)

带借位减法指令SBB DST, SRC
执行操作: (DST) <- (DST) - (SRC) - CF

减1指令DEC OPR
执行操作: (OPR) <- (OPR) - 1

求补指令NEG OPR
执行操作: (OPR) <- (OPR)
即将操作数按位求反后末位加1,因而执行的操作也可以表示为:(OPR)<- 0FFFFH-(OPR)+1

比较指令CMP OPR1, OPR2
执行操作: (OPR1) - (OPR2)

CMP指令与SUB指令一样执行减法操作,但它并不保存结果,只是根据结果设置条件标志位。
CMP指令后往往跟一条条件转移指令,根据比较结果产生不同的程序分支。
说明:OPRT1和OPRT2可以是寄存器或存储器,但不能同时为存储器,OPRT2还可以为立即数。

注意: 除DEC指令不影响CF标志外(硬件结构决定的),均对条件标志位有影响。

减法指令对条件标志位(CF/OF/ZF/SF)的影响:

有符号减法下CF是没有意义的
无符号数加法下OF是没有意义的

乘法指令

无符号数乘法指令:MUL SRC
带符号数乘法指令:IMUL SRC

执行操作:
字节操作数 AX<- AL * (SRC)
字操作数 (DX,AX) <- AX * (SRC)

MUL CL; AL,CL 中的无符号之积送AX
MUL [SI]; 计算机无法判断源操作数是字节操作数还是字操作数MUL
MUL WORD PTR [SI]; AX中的无符号数与SI所指单元的字无符号数相乘,乘积送DX和AX

注意:

  1. AL (AX) 为隐含的乘数寄存器。
  2. AX (DX,AX) 为隐含的乘积寄存器。
  3. SRC不能为立即数,因为位宽不详。
  4. 除CF和OF外,对条件标志位无定义

乘法指令对 CF/OF 的影响:

乘法指令不会产生溢出和进位,这时用OF和CF位来表示乘积有效数字的长度:
若乘积的高半部分(字节乘法为AH,字乘法为DX)有效,即:
MUL指令中是指AH或DX中的内容不为0
IMUL指令指的则是AH或DX中的内容不是符号位的扩展
则CF和OF都为1,表示DX或AH中含有乘积的有效数字,否则CF和OF为0。

除法指令

  • DIV源操作数
    实现无符号数除法运算。以(AX)或(DX)、(AX)中的内容为被除数,源操作数为除数。商送AL或AX,余数送AH或DX。当源操作数为字节操作数时,默认(AX)为被除数,商送AL,余数送AH;当源操作数为字操作数时,默认(DX)、(AX)内容为被除数,商送AX,余数送DX。指令执行情况如图3.16所示
MOV AX,1001H;
MOV CL, 20H;
DIV CL;
  • IDIV源操作数

功能与DIV指令基本相同,区别在于,该指令实现有符号数除法运算

MOV CX,4
IDIV CX;
  • CBW
    将(AL)的符号位扩展到AH中(即使得AH各位与AL最高位相同),该指令常用在IDIV指令之前。CBW指令执行后,各状态标志位不确定。例如:
MOV AL,76H;
CBW;
  • CWD
    功能与CBW基本相同,区别仅在于,该指令是将(AX)的符号位扩展到DX中。

3.3.3 逻辑指令

逻辑运算指令


移位指令



SHL SHR SAL SAR
移位指令影响除AF外的5个标志位,对AF没定义
ROL ROR RCL RCR
循环移位指令影响CF和OF,对SF ZF PF没影响,对AF没定义

3.3.4 串处理指令

(略,非考点)

3.3.5 控制转移指令

  • 无条件转移指令
    JMP
  • 条件转移指令
    JZ / JNZ 、 JE / JNE、 JS / JNS、 JO / JNO、
    JP / JNP、 JB / JNB、 JL / JNL、 JBE / JNBE、
    JLE / JNLE、 JCXZ
  • 循环指令
    LOOP、LOOPZ / LOOPE、LOOPNZ / LOOPNE
  • 子程序调用和返回指令
    CALL、RET
  • 中断与中断返回指令
    INT、INTO、IRET

无条件转移指令

  • 段内直接短转移:JMP SHORT OPR
    执行操作:IP ← IP + 8位位移量(DST为立即数)
  • 段内直接近转移:JMP NEAR PTR OPR
    执行操作:IP ← IP + 16位位移量
  • 段内间接转移: JMP WORD PTR OPR
    OPR为存放在16位通用寄存器或字内存单元内的偏移量
    执行操作:IP ← (通用寄存器)
    IP ← IP + (EA)

条件转移指令

注意:只能使用段内直接寻址的8 位位移量; 超过60条指令就要小心了!

  • 根据单个条件标志的设置情况转移
  • 比较两个无符号数,并根据比较结果转移

  • 比较两个带符号数,并根据比较结果转移

参考带符号数的CMP指令或减法指令对SF/OF的影响
适用于带符号数的比较

  • 测试 CX 的值为 0 则转移

循环指令

循环指令:LOOP OPR
测试条件:(CX) !=0
为零或相等时循环指令:LOOPZ(LOOPE) OPR
测试条件:ZF=1 且 (CX) != 0
不为零或不相等时循环指令:LOOPNZ(LOOPNE) OPR
测试条件:ZF=0 且 (CX) != 0
执行步骤:
(1) (CX) ← (CX) - 1
(2) 检查是否满足测试条件,如满足则 (IP) ← (IP) + 8位位移量,实行循环;不满足则 IP 不变,退出循环。

注意:CX 中存放循环次数; 只能使用段内直接寻址的8 位位移量; 超过60条指令就要小心了!

调用指令

  • 段内直接近调用CALL DST(DST为子程序名)
    执行操作: (SP) ← (SP) – 2 ;
    ( (SP)+1,(SP) ) ← IP ; 主程序地址压栈
    (IP) ← (IP) + 16位位移量
    注意:IP为Call指令的下一条指令的地址,其与DST子程序的地址间的相对地址或位移量是固定的。
  • 段内间接近调用CALL DST(DST为寄存器如BX或存储器地址 WORD PTR [BX])
    执行操作: (SP) ← (SP) - 2
    ( (SP)+1,(SP) ) ← (IP)
    (IP) ← (EA) (DST为内存地址)

返回指令

  • 段内近返回RET
    执行操作: (IP) ← ( (SP)+1,(SP) )
    (SP) ← (SP) + 2
  • 段内带立即数近返回RET EXP
    (IP) <- POP()
    (SP) <- (SP)+EXP //修改堆栈指针,删除了EXP个内容. *注意并非是子程序的返回值!

中断指令

中断向量:中断例行程序的入口地址,存放于中断向量区。

中断发生时,从中断向量表中取出相应的值赋值给CS和IP的过程是由系统硬件自动完成的,程序员不可见! 程序员能够做的就是修改中断向量表中存储的值。

在8086中,reset不算是中断,不在中断向量表内。reset时CS=FFFFH,IP=0000H; 在内存FFFF0处存放了一个JMP指令!

  • CPU在执行INT指令时,经过某些操作,转去执行中断服务程序。这些操作是由硬件直接实现的,把它称为中断隐指令,其操作过程程序员不可见。中断隐指令并不是指令系统中的一条真正的指令,它没有操作码,所以中断隐指令是一种特殊指令


注意:
TYPE (0~255) 是中断类型号
INT 指令还把 IF 和 TF 置0,但不影响其它标志位
IRET 指令执行完,标志位由堆栈中取出的值确定

标识处理指令:

CLCSTCCMC:对CF位清零/置位/取反
CLDSTD: 字符串移动方向增/减标志
CLISTI:开/关中断

3.3.6 处理机控制与杂项操作指令

控制CPU工作方式的指令,多用于多任务处理

  • 空操作指令NOP
    该指令没有的显式操作数,主要起延迟下一条指令的执行,不影响任何标志位。
  • 等待指令WAIT
    该指令使CPU处于等待状态,直到协处理器(Coprocessor)完成运算,并用一个重启信号唤醒CPU为止。该指令的执行不影响任何标志位。 *协处理器不算外设,而是另一个FPU!
  • 暂停指令HLT
    在等待中断信号时,该指令使CPU处于暂停工作状态【低功耗模式】,CS:IP指向下一条待执行的指令,但不进行任何操作,保持先前操作中所有寄存器的状态不变 。当产生了中断信号,CPU把CS和IP压栈,并转入中断处理程序。在中断处理程序执行完后,中断返回指令IRET弹出IP和CS,并唤醒CPU执行下条指令。指令的执行不影响任何标志位。
  • 封锁数据指令LOCK
    该指令是一个前缀指令形式,在其后面跟一个具体的操作指令。LOCK指令可以保证是在其后指令执行过程中,禁止协处理器修改数据总线上的数据,起到独占总线的作用。该指令的执行不影响任何标志位。
    指令的格式:LOCK INSTRUCTION

第四次作业

1、指出下列指令的错误
(1) MOV AH,BX
(2) MOV [BX],[SI]
(3) MOV AX,[DI ][SI]
(4) MOV MYDAT[BX][SI],ES:AX
(5) MOV CS,AX

Answer:

  1. 源操作数和目的操作数的类型必须一样,即必须同为单字节或者同为双字节。而此指令的源操作数为双字节,而目的操作数为单字节
  2. 源操作数和目的操作数不能同时为存储器寻址,不然无法确定待传送的数据是双字节还是单字节
  3. 基址变址的寻址方式必须是一个基址寄存器和一个变址寄存器的组合,源操作数的寻址方式是由两个变址寄存器的组合,所以不对。
  4. ES是段超越前缀,只能用在存储器操作数前面,而AX是寄存器操作数,前面不能加段超越d前缀。除此之外,即便此处的AX换成了存储器操作数,源操作数和目的操作数均为存储器操作数,无法判断传送的数据类型。
  5. CS不能作为目的操作数

2、下列哪些指令是非法的
(1) CMP 15,BX
(2) CMP BYTE PTR OP1,25
(3) CMP OP1,OP2
(4) CMP AX,OP1

Answer:

  1. 错,CMP 中立即数不能为目的操作数
  2. 正确
  3. 错,不能同时为存储器操作数
  4. 若OP 1为字类型则正确,否则类型不匹配

3、假设下列指令中的所有标示符均为类型属性为字的变量,请指出下列指令中哪些是非法的?它们的错误是什么?
(1) MOV BP,AL
(2) MOV WORD_OP[BX+4*3][DI],SP
(3) MOV WORD_OP1,WORD_OP2
(4) MOV AX,WORD_OP1[DX]
(5) MOV SAVE_WORD,DS
(6) MOV SP,SS:DATA_WORD[BX][SI]
(7) MOV [BX][SI],2

Answer:

  1. 非法: BP寄存器是字类型的,而AL寄存器是字节类型的。
  2. 合法
  3. 非法:两个操作数不能同为内存单元
  4. 非法:DX不能作为寄存器相对寻址方法中的寄存器,而只能选择基址寄存器或者变址寄存器(BX,BP,SI,DI)
  5. 合法
  6. 合法
  7. 非法,没有指定目的操作数的类型,应该改为“mov byte或者word ptr[bx][si],2”

4、假设程序中的数据定义如下:
LNAME DB 30 DUP(?)
ADDRESS DB 30 DUP(?)
CITY DB 15 DUP(?)
CODE_LIST DB 1,7,8,3,2
(1) 用一条MOV指令将LNAME的偏移地址放入AX。
(2) 用一条指令将CODE_LIST的头两个字节的内容放到SI。
(3) 写一条伪操作使CODE_LENGHT的值等于CODE_LIST域的实际长度

  1. MOV AX,OFFSET LNAME
  2. MOV SI,WORD PTR CODE_LIST
  3. CODE_LENGTH EQU $-CODE_LIST

5、试说明下述指令中哪些需要加上PTR伪操作:
BVAL DB 10H,20H
WVAL DW 1000H
(1) MOV AL,BVAL
(2) MOV DL,[BX]
(3) SUB [BX],2
(4) MOV CL,WVAL
(5) ADD AL,BVAL+1

Answer:

  1. 不需要
  2. 不需要
  3. 需要,应修改成“SUB BYTE PTR [BX],2”
  4. 需要,应修改为“MOV CL,BYTE PTR WVAL”
  5. 不需要

6、若TABLE为数据段0032H单元的符号名,其中存放的内容为1234H,试问下列两条指令有什么区别?执行完指令后,AX寄存器中的内容是什么?
MOV AX,TABLE
LEA AX,TABLE

Answer:

  1. " MOV AX,TABLE" 是将TABLE单元的内容送到AX,(AX) =1234H
  2. "LEA AX,TABLE"是将TABLE单元的有效地址送到AX中, (AX)=0032H

7、已知程序段如下:
MOV AX,1234H
MOV CL,4
ROL AX,CL
DEC AX
MOV CX,4
MUL CX
试问:
(1)每条指令执行后,AX的内容是什么?
(2)每条指令执行后,CF、SF和ZF的值是什么?
(3)程序执行完后,AX和CX的内容是什么?

Answer:

 MOV AX,1234H; (AX)=1234H, CF、SF、ZF的值保持不变(因为此处不知道标志寄存器的初值,所以无法判断具体的值)MOV    CL,4;  (AX)=1234H, CF、SF、ZF的值保持不变ROL    AX,CL; (AX)=2341H, CF=1, SF、ZF的值保持不变DEC  AX; (AX)=2340H, CF不变,SF=ZF=0MOV CX,4; AX、CF、SF、ZF的值保持不变MUL   CX; (AX) =8D00H, SF=1,CF=ZF=0

程序执行完后,(DX)=0000H, (AX)=8D00H

小结:

  1. SHL SHR SAL SAR
    移位指令影响除AF外的5个标志位,对AF没定义
  2. ROL ROR RCL RCR
    循环移位指令影响CF和OF,对SF ZF PF没影响,对AF没定义
  3. INC DEC
    增一、减一指令不影响CF,会影响其他的标志位

4. 分支程序设计

汇编程序的一般结构

4.1 转移指令

  • 条件转移指令
  1. 根据单个条件标志的设置情况转移

  2. 比较两个无符号数,并根据比较结果转移
    适用于 地址或者双精度低位字的比较

  3. 比较两个带符号数,并根据比较的结果转移

  • 无条件转移指令
  1. 无条件转移指令JMP
    功能:无条件地使程序转移到指定的目标地址


4.2 分支结构程序设计

4.2.1 双分支结构

  1. 双分支结构程序的典型结构

    【例】显示AL的高位
 SHL AL,1;JC NT1MOV DL,30HJMP NT2
NT1: MOV DL,31H
NT2: MOV AH,02HINT 21H

DOS 功能调用
功能号02H,用于从显示屏幕上输出单个字符
【例】: 显示输出字符’A’

MOV DL,'A'; 调用参数,输出字符
MOV AH,02; DOS功能号: 显示输出
INT  21H;DOS 调用

DOS功能调用:
功能号09H,用于从显示屏幕上输出字符串
例:显示输出字符串‘computer’

STR  DB  ‘computer’,‘$’   ;在数据段定义
…
MOV DX,OFFSET STR ; 调用参数: 输出字符串
MOV AH,09H   ; DOS功能号: 显示输出串
INT 21H         ; DOS调用

【例】 计算某个数的绝对值

 CMP AX,0JGE NTNEG AX
NT: MOV RES,AX

【例】设计字符比较程序,两个字符相同时,显示YES; 否则显示NO。

DATA SEGMENT
D1 DB 'A'
D2 DB 'B'
RES1 DB 'YES' ,'$'
RES2 DB 'NO' , '$'
DATA ENDSCODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATAMOV DS,AXMOV AL,D1MOV BL,D2CMP AL,BLJE NEXT1LEA DX,RES2JMP NEXT2
NEXT1: LEA DX,RES1
NEXT2: MOV AH,09HINT 21HMOV AH,4CHINT 21H
CODE ENDSEND START

【例】设存储单元A和B各有
一无符号字节数,比较大小,将较大数送A单元

DATA SEGMENT A DB 39HB DB 0B4H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATAMOV DS,AXMOV AL,ACMP AL,BJNB NEXTXCHG AL,BMOV A,AL
NEXT:MOV AH,4CHINT 21H
CODE ENDSEND START

4.2.2 多分支结构

实现方法:
用多个双分支结构实现多分支结构
利用地址表法实现多分支结构
利用转移表法实现多分支结构
利用逻辑分解法实现多分支结构

  • 由多个双分支结构实现多分支结构程序设计

【例】计算符号函数SNG(X)的值’

DATA SEGMENTX DB 0B9HY DB ?
DATA  ENDSCODE SEGMENTASSUME CS:CODE, DS: DATA
START:MOV AX,DATAMOV DS, AXMOV AL,XCMP AL,0JL NEXT1CMP AL,0JG NEXT2MOV Y,0JMP RES
NEXT1: MOV Y,0FFHJMP RES
NEXT2:MOV Y,1
RES:MOV AH,4CHINT 21H
CODE ENDSEND START
  • 利用地址表法实现多分支结构程序设计

【例】用地址表法编写程序实现从低到高逐位检测一个字节数据,找出第一个非0的位数。检测时,为0则继续检测,为1则转移到对应的处理程序段显示相应的位数。

DATA  SEGMENT
NUM DB 78H
ADTAB DW AD0,AD1,AD2,AD3,AD4,AD5,AD6,AD74
DATA ENDS
CODE SEGMENTASSUME CS:CODE, DS:DATA
START:MOV AX,DATAMOV DS, AXMOV AL,NUMMOV DL,'?'CMP AL,0JZ DISPMOV BX,0
AGAIN:SHR AL,1JC NEXTINC BXJMP AGAIN
NEXT:SHL BX,1JMP ADTAB [BX]
AD0:MOV DL,'0'JMP DISP
AD0:MOV DL,'1'JMP DISP
AD0:MOV DL,'2'JMP DISP
AD0:MOV DL,'3'JMP DISP
AD0:MOV DL,'4'JMP DISP
AD0:MOV DL,'5'JMP DISP
AD0:MOV DL,'6'JMP DISP
AD0:MOV DL,'7'JMP DISP
DISP:MOV AH,2INT 21HMOV AH,4CHINT 21H
CODE ENDSEND START
  • 转移表法多分支程序设计
    【例】:根据输入值(0~4)的不同,执行不同的操作,用转移表法编写程序
CODE SEGMENTASSUME CS:CODE
START:LEA BX,TABMOV AH,1INT 21HSUB AL,30HMOV AH,0ADD AX,AXADD BX,AXJMP BX
TAB: JMP SHORT MODE1JMP SHORT MODE 2JMP SHORT MODE3JMP SHORT MODE4
MODE0:MOV DL, 30HJMP EXIT
MODE1:MOV DL, 31HJMP EXIT
MODE2:MOV DL, 32HJMP EXIT
MODE3:MOV DL, 33HJMP EXIT
MODE4:MOV DL, 34HJMP EXIT
EXIT:MOV AH,2INT 21HMOV AH,4CHINT 21H
CODE ENDSEND START

说明:转移表中每条转移指令(段内短转移)占用2个字节, 计算公式如下:表地址=模式字*2+转移表首地址

  • 逻辑分解法多分支程序设计

设计方法:将多分支结构采用逻辑等效的方法,按条件的先后,依次分解成下图所示的一串双分支结构,然后使用双分支的方法来进行程序设计。

【例】 根据AL中的值(0~4),执行不同的操作,用逻辑分解法编写程序

DATA SEGMENTNUM DB 2
DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA
START: MOV AX,DATAMOV DS,AXMOV AL,NUMCMP AL,0JZ NEXT0CMP AL,1JZ NEXT1CMP AL,2JZ NEXT2CMP AL,3JZ NEXT3CMP AL,4JZ NEXT4
NEXT0: MOV DL,30HJMP EXIT
NEXT0: MOV DL,31HJMP EXIT
NEXT0: MOV DL,32HJMP EXIT
NEXT0: MOV DL,33HJMP EXIT
NEXT0: MOV DL,34H
EXIT: MOV AH,2INT 21HMOV AH,4CHINT 21H
CODE ENDSEND START

第五次作业

1、内存有一个字节变量VAL中存放着小写字符’a’,请将该字符转换为大写字符并在屏幕中显示出来(要求在debug中调试出该程序)

DSEG SEGMENT
VAL DB 'a';
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV AL, VAL;SUB AL,20H; 转换为大写字母MOV DL,AL ; 显示一个字符的DOS调用MOV AH,02H; DOS输出功能调用INT 21H;MOV AH,4CH; 返回DOS调用INT 21H;
CSEG ENDS
END START

2、设存储单元A和B各有一带符号字节数,比较大小和正负,要求将较大数送RES1单元;如果有负数,将一个负数送RES2,否则RES2送-1(要求在debug中调试出该程序)。

DSEG SEGMENT
A DB 5
B DB -3
RES1 DB ?
RES2 DB ?
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV DL,A;MOV DH,B;CMP DL,DH;JG AGBMOV RES1,DH;B>=AMOV CL,DL; 将小的数送往CLJMP FU;
AGB:MOV RES1,DL; A>BMOV CL,DH ; 将小的数送往CL
FU:CMP CL,0;JL FSS; MOV RES2,-1; 不存在负数JMP EXIT; 返回
FSS:MOV RES2,CL;存在负数
EXIT:   MOV AH,4CH; 返回DOS调用INT 21H;d
CSEG ENDS
END START

5. 循环程序设计

5.1 循环指令

  • 循环指令:LOOP OPR
    测试条件:(CX) != 0

  • 为零或相等时循环指令:LOOPZ(LOOPE) OPR
    测试条件:ZF=1 且 (CX)!= 0

  • 不为零或不相等时循环指令:LOOPNZ(LOOPNE) OPR
    测试条件:ZF=0 且 (CX) !=0


执行步骤:
(1) (CX) ← (CX) - 1
(2) 检查是否满足测试条件,如满足则
(IP) ← (IP) + 8位位移量,实行循环;
不满足则 IP 不变,退出循环。

注意:LOOP指令执行时CX是否为0不影响ZF和CF的变化,等价于DEC指令!所以LOOP指令和LOOPZ指令才有区别!

5.2 循环程序设计

循环程序结构:

初始化:设置循环的初始状态
循环体:循环的工作部分及修改部分
控制条件:计数控制,特征值控制,地址边界控制

  • 用分支指令控制循环
    在STR开始的缓冲区中存放有一个字符串,计算该字符串的长度并存入LEN单元。

【例】在STR开始的缓冲区中存放有一个字符串,计算该字符串的长度并存入LEN单元。

DATA SEGMENT
STR DB 'computer$'
LEN DB ?
DATA ENDS
CODE SEGMENTASSUME CS: CODE, DS:DATA
START:MOV AX,DATAMOV DS,AXLEA SI,STR; 串首地址XOR BL,BL; 计数器清零
LOP:MOV AL, [SI]; 取一个字节CMP AL,24H; 和$ 进行比较JZ STOP ; 相等则结束INC BL;否则计数器加1INC SI; 地址指针加1JMP LOP; 转回到LOP
STOP:MOV LEN, BL ; 存储字符的个数MOV AH,4CHINT 21H
CODE ENDSEND START

【例】求以BUF为首地址的10个内存单元的无符号数据和。已知其和小于等于255,将结果存入第11个内存单元

DATA SEGMENT
BUF DB 12H, 38H, 46H, 0BH, 09H, 41H, 32H, 56, 02H, 26H
RES DB ?
DATA ENDSCODE SEGMENTASSUME CS:CODE,DS: DATA
START: MOV AX,DATAMOV DS,AXMOV AL,0; 存放累加之和MOV CX,0AH; 累加次数LEA BX, BUF;  数据表的首地址
LP:ADD AL,[BX]; INC BXLOOP LPMOV AH,4CHINT 21H
CODE ENDSEND START

【例】在字节数组中找出第一个非0的数据,并将其下标存入RES单元,假设其下标值小于10

DATA SEGMENT
ARR DB 0,0,38H,46HDB 89H,67H,0H,92H
CNT EQU $-ARR
RES DW ?
DATA ENDS
CODE SEGMENTASSUME CS:CODE, DS: DATA
START:MOV AX,DATAMOV DS,AXMOV CX,CNT; MOV DI,-1
AGAIN :INC DICMP ARR[DI],0LOOPZ AGAINJZ EXITMOV RES,DI
EXIT:MOV AH,4CHINT 21H
CODE ENDSEND START

【例】在字符串中从前向后查找空格字符(ASCII码为20H),找到显示Y,否则就显示N

DATA  SEGMENT
STR DB 'ASDFK LIO OP'
LEN EQU $-STR
DATA ENDS
CODE SEGMENTASSUME CS:CODE,DS:DATA
START:MOV AX,DATAMOV DS,AXMOV  CX,LENMOV SI,-1MOV AL,20H
NEXT:INC SICMP AL,STR[SI]LOOPNE NEXTJNZ NFINDMOV DL,'Y'MOV AH,2INT 21HJMP EXIT
NFIND:MOV DL,'N'MOV AH,2INT 21H
EXIT:MOV AH,4CHINT 21H
CODE ENDSEND START
  • 用计数器控制循环
    【例】 已知数据块的长度,统计数据块中正数和负数的个数
DATA SEGMENT
BUF DB -32,25,36,-18,-64,0,-3
COUNT EQU $-BUF
PLUS DB ?;
MINUS DB ?;
DATA ENDS
CODE SEGMENTASSUME CS:CODE DS: DATA
START: MOV AX,DATAMOV DS,AXMOV BL,0; 负数个数MOV DL,0; 正数个数MOV SI,OFFSET BUF; 指针MOV CX,0;循环初值
LOP1:MOV AL,[SI]CMP AL,0JGE NEXT0INC BLJMP NEXT1
NEXT0:INC DL
NEXT1:INC SIINC CXCMP CX, COUNT;JL LOP1MOV MINUS,BLMOV PLUS,DLMOV AH,4CHINT 21H
CODE ENDSEND START

【例】将BUF数据单元开始的100个字节存储单元全部清零

DATA SEGMENT
BUF DB 100 DUP(?)
DATA ENDS
CODE SEGMENTASSUME CS: CODE,DS: DATA
START: MOV AX,DATAMOV DS,AXMOV BX, OFFSET BUF;地址指针MOV CX,64H;计数初值
LP:MOV BYTE PTR [BX],0; 清零INC BX;地址加1LOOP LP;循环次数减1,不为0,则继续循环MOV AH,4CHINT 21H
CODE ENDSEND START
  • 按问题的条件控制循环
    【例】记录某个字节存储数据单元中1的个数,并把结果存入RES中。
DATA SEGMENT
NUM DB 75H
RES DB ?
DATA ENDS
CODE SEGMENTASSUME CS: CODE,DS:DATA
START:MOV AX,DATAMOV DS,AXMOV BL,NUMXOR DL,DL
AGAIN:TEST BL,00HJZ NEXTSHR BL,1ADC DL,0JMP AGAIN
NEXT:MOV RES,DLMOV AH,4CHINT 21H
CODE ENDSEND START

【例】在以BUF为起始地址的内存中放有若干个字节型无符号数,假定逻辑变量的长度为一个字节(其值为10010101 ),若它的D0~ D7位对应着BUF ~ BUF+7单元内容的运算。即某位为0,则将相应单元内容的最高位求反,其它位不变;而某位为1,则将相应单元内容之高低四位互换。

DATA SEGMENT
BUF DB 75H,12H,87H,98HDB 81H,56H,73H,51HB EQU 8C EQU 10010101B
DATA ENDS
CODE SEGMENT ASSUME CS: CODE,DS: DATA
START:MOV AX,DATAMOV DS,AXMOV AH, BMOV CH, CLEA BX,BUF
LP:MOV AL,[BX]SHR CH,1LEA BX,BUF
LP:MOV AL,[BX]SHR CH,1JNC NEXTMOV CL,4ROL AL,CLJMP RES
NEXT:XOR AL,80H
RES:MOV [BX],ALINC BXDEC AHJNZ LPMOV AH,4CHINT 21H
CODE ENDSEND START
  • 多重循环程序设计应用举例

【例】设在以EXST为首址的存储区中依次存放着某考区245个理科生的七门成绩,现要统计每个考生的总成绩,并将其存放在该考生单科成绩之后的两个单元

DATA SEGMENT
EXST DB 01,75,82,92,78,49,85,00,00DB 02,83,92,63,76,82,58,69,00,00..
DATA ENDSCODE SEGMENT ASSUME CS:CODE, DS: DATAMOV AX, DATAMOV DS,AX
START: LEA SI,EXST; 数据表的首地址MOV BL, 245; 245个学生,外循环次数
LOP2: MOV CX,7; 7门课的成绩,内循环的次数XOR AX,AX; 清0,存总成绩INC SI;跳过准考证号
LOP1: ADD AL,[SI]; 单科成绩累加ADC AH,0; 加进位位INC SI; 修改地址指针LOOP LOP1; 没累加完单科成绩,则继续MOV WORD PTR [SI],AX; 累加完,存总成绩INC SI ; 跳过存总成绩的两个单元INC SISUB BL,1; 外循环次数减1,如果是DEC指令则不影响ZFJNZ LOP2; 不为0,则求下一个学生的成绩MOV AH,4CHINT 21H
CODE ENDSEND START

【例】将N个不同的无符号数a1,a2,…,an由小到大进行排序。若每个数占一个字, 则N个数可定义如下:
A DW a1,a2,a3,…,an,它们的内存分配分别为: A[0],A[2],A[4],…,A[2n]

DATA SEGMENT
A DW 1223,83,456,355,89DW 9845,123,789,567
CNT EQU ($-A) /2
DATA ENDSCODE SEGMENTASSUME CS: CODE, DS: DATA
START:MOV AX, DATAMOV DS,AXMOV CX,CNT-1MOV BX,0
LOOP1:MOV DX,CXMOV SI,2
LOOP2:MOV AX,A[BX]CMP AX,A[BX+SI]JNA L1XCHG AX,A[BX+SI]MOV A[BX],AX
L1:ADD SI,2LOOP LOOP2ADD BX,2MOV CX,DXLOOP LOOP1MOV AH,4CHINT 21H
CODE ENDSEND START

第六次作业

1、 在STR到STR+99单元中存放着一个字符串,试编写程序测试该字符串中是否有数字,若有将CL置1,否则CL置0 (要求在debug中调试出该程序)。

DSEG SEGMENT
STR DB 'A5AAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEE'DB 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEE'
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV BX,OFFSET STR; 地址指针MOV CX,64H; 计数器初值,100次循环LP:MOV AL,[BX];CMP AL,'0';JB NS; 小于0CMP AL,'9'JA NS; 大于9MOV CL,1; 存在数字,跳出循环。JMP EXIT;
NS: ; 不是数字INC BX; 地址加1LOOP LP; 循环次数减1,不为0则继续循环。MOV CL,0; 不存在数字
EXIT:   MOV AH,4CH; 返回DOS调用INT 21H;
CSEG ENDS
END START

2、在字节数组中找出第一个负数,并将该负数存入RES单元中;假设该数组中包含20个带符号数且至少有1个负数(要求在debug中调试出该程序)。

DSEG SEGMENTRES DB ?DATA DB 1,-1,2,3,4,5,6,7,8,9DB 0,3,4,-5,6,7,8,-9,0,2
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV CX,20; 循环的次数设为20MOV DI,0;地址指针LP:CMP DATA[DI],0;判断是否为负数JL EXIT; 如果小于0,则退出INC DI; 地址指针加1LOOP LP;继续循环EXIT:    MOV AL,DATA[DI]MOV RES,AL;MOV AH,4CH; 返回DOS调用INT 21H;
CSEG ENDS
END START

6. 子程序结构

子程序的运行方式:
特点:主动调用,而不是随机的(中断则相反)。

6.1 调用格式

  • 调用指令

CALL调用指令
段内直接近调用:CALL DST

执行操作:(SP) ← (SP) - 2( (SP)+1,(SP) ) ← (IP)(IP) ← (IP) + 16位位移量

段内间接近调用:CALL DST

执行操作:(SP) ← (SP) - 2( (SP)+1,(SP) ) ← (IP)(IP) ←(EA)

RET返回指令
段内近返回:RET

执行操作:
(IP) ← ( (SP)+1,(SP) )
(SP) ← (SP) + 2

段内带立即数近返回:RET EXP

6.2 调用过程

  1. 过程定义伪操作
过程名 PROC NEAR(FAR)
...
过程名 ENDP

(1)NEAR 属性:调用程序和子程序在同一代码段中(段内调用)

(2)FAR 属性:调用程序和子程序不在同一代码段中(如同一汇编文件的多个代码段或多个汇编文件的多个代码段时)(段间调用)

2. 子程序的调用和返回
子程序调用:隐含使用堆栈保存返回地址

call  near ptr  subp        (1)  保存返回地址:仅offset地址(2)  转子程序

call  far  ptr  subp (1)  保存返回地址:seg+offset(2)  转子程序

段内近返回:RET

执行操作:(IP) ← ((SP)+1,(SP)) (SP) ← (SP) + 2
  1. 保护恢复寄存器
subt   proc    near(far)push    axpush    bxpush    cxpush    dx…………pop     dxpop     cxpop     bxpop     axret
subt   endp
  1. 子程序的参数传递
    (1) 通过寄存器传送参数
    (2) 通过存储器传送参数
    (3) 通过地址表传送参数地址
    (4) 通过堆栈传送参数或参数地址
    (5) 多个模块之间的参数传送

6.3 子程序实例

【例】利用子程序完成乘法运算(通过寄存器传送参数)

data segmentx db 5y dw ?
data ends
stack segment db 64 dup('s')
stack ends
code segment para ’code‘assume cs:code,ds:data,ss:stack
star proc farpush ds; mov ax,data; 搬移DS段mov ds,axmov bl,1; 入口参数放到bl中call mulxret
star endp
mulx proc nearpush axmov al,xmul blmov y,axpop axret
mul endp
code endsend star

在没有定义堆栈段的情况下,程序开始时的栈顶指向程序的第一个段,如:先定义代码段,后定义数据段,就指向代码段;

【例】将给定的一组字数据X、Y代入Z=((X+Y)×2-X)×4 公式中,计算相应的Z值。假设Z的值不会超过16位。

DATA SEGMENT X DW 5,3,8,9,2,5,3,4,7,6Y DW 3,7,4,5,8,8,4,1,0,7Z DW 10DUP(?)
DATA ENDS;
CODE SEGMENT ASSUME CS:CODE, DS:DATA
START:MOV AX,DATAMOV DS,AXLEA SI,XLEA DI,YLEA BX,ZMOV CX,Y-X ; 字节数SHR CX,1;数组元素个数
REAPTMOV AX,[SI]MOV DX,[DI]CALL SUBRMOV [BX],AXADD SI,2ADD DI,2ADD BX,2LOOP REAPT
EXIT:MOV AH,4CHINT 21H
SUB PROC NEARPUSH BXPUSH CXMOV BX,AX;BX=XADD AX,DX; AX=X+YSAL AX,1;AX=(X+Y)*2SUB AX,BX;AX=(X+Y)*2-XMOV CL,2SAL AX,CL; AX=((X+Y)*2-X)*4POP CX;POP BXRET
SUB ENDP
CODE ENDSEND START

【例】累加数组中的元素(通过存储器传送参数)

DATA SEGMENT ary dw 1,2,3,4,5,6,7,8,9,10count dw 10sum dw ?
DATA ENDS;
CODE SEGMENT ASSUME CS:CODE, DS:DATA
START:MOV AX,DATAMOV DS,AXCALL PROADDMOV AH,4CHINT 21H
PROADD PROC NEARPUSH AXPUSH CXLEA SI,ARYMOV CX,COUNTXOR AX,AX
NEXT:ADD AX,[SI]ADD SI,2LOOP NEXTMOV SUM,AXPOP SIPOP CXPOP AXRET
PROADD ENDP
CODE ENDSEND START

第七次作业

  1. 试编写一个汇编程序,能对键盘输入的小写字母用大写字母显示出来(要求采用子程序格式,即采用子程序完成将小写字母转化成大写字母)。
DSEG SEGMENTDSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV AH,01; 从键盘中接收一个字符INT 21H;CALL SUB1;MOV DL,AL ; 显示一个字符的DOS调用MOV AH,02H; DOS输出功能调用INT 21H;MOV AH,4CH; 返回DOS调用INT 21H;SUB1 PROCSUB AL,20H; 转换为大写字母
SUB1 ENDPCSEG ENDS
END START

2、有2个数组:
ary1 db 12,-35,0,126,-90,-5,68,120,1,-19
ary2 db 24,25,0,-38,-89,99,68,100,2,-20
比较两个数组的对应位,将大的数放在ary1数组中,小的数放在ary2中(要求采用子程序格式)

DSEG SEGMENT
ARY1 DB 12,-35,0,126,-90,-5,68,120,1,-19
COUNT EQU $-ARY1
ARY2 DB 24,25,0,-38,-89,99,68,100,2,-20
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX, DSEG;将段地址送往DSMOV DS, AXMOV CX,COUNT;CX为入口参数,保存数组元素的个数LEA SI,ARY1; SI为入口参数, 保存数组1的起始位置LEA DI,ARY2; DI为入口参数, 保存数组2的起始位置CALL SUB1;MOV AH,4CH; 返回DOS调用INT 21H;SUB1 PROCLP:MOV AX,[SI]MOV DX,[DI]CMP AX,DX;JG AGB;MOV [SI],DX;如果数组1的对应位置元素小于数组2对应位置元素,则交换两数MOV [DI],AX;
AGB:ADD SI,1ADD DI,1
LOOP LP RET;
SUB1 ENDPCSEG ENDS
END START

3、用DOS的10号功能调用输入一个字符串,并用DOS的9号功能调用将这个字符串输出到屏幕上显示。

DSEG SEGMENT
STRING DB 100
LEN DB ?
BUF DB 100 DUP(?)
DSEG ENDSCSEG SEGMENTASSUME CS:CSEG,DS:DSEG
START:MOV AX,DSEGMOV DS,AXLEA DX,STRING;字符串的输入MOV AH,0AH;INT 21H;MOV DL,0AH;输出换行MOV AH,02HINT 21H;XOR CH,CHMOV CL,LENMOV DX,OFFSET BUFMOV BX,DXADD BX,CXMOV BYTE PTR [BX],'$'MOV AH,09H;显示字符串INT 21H;MOV AX,4CH; 返回DOSINT 21HCSEG ENDS
END START

7. BIOS 和DOS中断

BIOS和DOS基本调用:
调用方法
1、将调用参数装入指定的寄存器中;
2、BIOS或DOS功能号装入AH;
3、如需子功能号,把它装入AL;
4、按中断号调用DOS或BIOS中断(INT);
5、检查或取得返回参数。

【例】DOS调用:键盘输入,显示输出

 MOV   AH, 01        ;DOS功能号1:键盘输入 INT     21H       ;DOS调用MOV    CHAR, AL   ;返回参数: 键入字符的;ASCII码(在AL中)MOV    DL, ’A’         ;调用参数: 输出字符MOV    AH, 02        ;DOS功能号2: 显示输出INT     21H           ;DOS调用



【例】读取键盘状态字节,并以十六进制打印出

again:mov   ah,02hint     16hmov     bx,axcall    binihex; 该子程序对二进制和16进 制进行了转换mov     dl,0dhmov     ah,02hint     21hjmp     again


【例】DOS调用: 从键盘输入一个字符

MOV    AH, 01;DOS功能号:键盘输入
INT   21H;DOS调用
MOV    CHAR, AL;返回参数:键入字符的ASCII码(AL)

【例】输入字符到缓冲区STRING

DATA SEGMENTMAXLEN  DB 32ACTLEN DB ?STRING DB 32 DUP(?)
DATA ENDS
CODE SEGMENTASSUME CS;CODE, DS: DATA
START: MOV AX, DATAMOV DS,AXLEA DX, MAXLEN; 把MAXLEN所在地址赋值给DX;并且21h的0a号功能规定了缓冲区的长度设置、存放的内容和顺序,回车符(0DH)表示输入结束,见右上图MOV AH,0AH;屏幕上出现光标,让用户输入字符串INT 21H;
CODE ENDSEND START
  1. DOS 显示功能调用中断

    【例】 DSO调用,显示一个字符
MOV DL, 'A'; 调用参数,输出字符
MOV AH, 02; DOS 功能号:显示输出
INT 21H; DOS 调用

【例】 显示字符串

MESSAGE DB'The sort operation is finished.' ,13,10,'$'
MOV AH,9
MOV DX,SEG MESSAGE
MOV DS,DX
MOV DX,OFFSET MESSAGE
INT 21H

8. I/O端口地址译码技术

8.1 I/O地址空间

  • I/O地址空间是连续的地址集合,一个I/O地址对应的是接口电路中的一个寄存器控制器,称为“端口”
  • I/O地址分配给某个外设后就成为该外设的固有端口地址,其它外设不能使用,否则会发生冲突
  • I/O端口与存储器单元一样,以字节组织数据
  • I/O地址是16位的,范围是0000H-0FFFFH,共64K个可单独寻址的8位端口
  • 2个相邻的8位端口可构成1个16位端口;4个相邻的8位端口可构成1个32位端口。
  • 16位端口对应于偶数地址,32位端口对应于被4整除的地址,8位端口的地址可以从任意地址开始。

8.2 I/O 端口

  • I/O 端口的概念
    I/O端口(port):是接口电路中能被CPU直接访问的寄存器。CPU通过这些端口向接口中的寄存器发送命令读取状态传送数据。因此,一个接口可以有几个端口,如命令口、状态口和数据口,分别对应于命令寄存器、状态寄存器和数据寄存器

  • I/O 端口共用技术
    一般情况下,一个端口只允许接纳一种信息,但有些接口芯片中,一个端口即可作命令口又可作状态口使用,或允许同一个命令口写多个命令字,由此产生了端口的共用

  • I/O 端口地址编制方式

1. 独立的编址
端口地址单独编址,不和存储器地址空间合在一起
。IBM-PC系列就采用这种方式。
优点:
I/O端口地址不占用存储器地址空间。
I/O指令短,执行速度快。
由于专门I/O指令与存储器访问指令有明 显的区别,使程序中I/O操作和存储器操作层次清晰,程序的可读性强。
缺点:需要专门访问I/O端口的指令。

2. 统一编址
从存储器地址空间中划出一部分地址给I/O设备,将I/O接口中的端口当作存储器单元一样进行访问,不设置专门的I/O指令
优点:指令类型多,功能齐全。
缺点:端口占用了存储器的地址空间,使存储器容量减小,另外指令长度比专门I/O指令要长,因而执行速度较慢

  • 独立编址方式的端口访问
  1. I/O指令IN和OUT
    IN指令从I/O端口向AL(AX/EAX)输入字节(字/双字)OUT指令从AL(AX/EAX)向I/O端口输出字节(字/双字)
PORT EQU 0F4H
IN  AL,PORT          ;输入IN  AX,PORTOUT PORT,AL        ;输出OUT PORT,AX

对I/O端口的访问就是CPU对端口的读/写操作。即指I/O端口与CPU的累加器之间的数据传送,并不涉及数据是否传送到存储器的问题。

例如:输入时MOV  DX,300H    ; I/O端口IN  AL,DX             ; 从端口读数据到ALMOV  [DI],AL       ; 将数据从AL→存储器
例如:输出时   MOV  DX,301H    ; I/O端口MOV  AL,[SI]        ; 从内存取数到ALOUT   DX,AL         ; 数据从AL→端口
  1. I/O 端口的寻址方式
  • 直接寻址
    I/O指令直接提供8位I/O地址
    只能寻址256个I/O地址(00~FFH)
    用i8表示I/O地址,表达形式上与立即数一样
  • DX间接寻址
    用DX寄存器保存访问的I/O地址
    可寻址全部I/O地址(0000~FFFFH)
    直接书写成DX,表示I/O地址
输入时:IN AX,0E0H      ;直接寻址MOV  DX,300H    ;端口300HIN AX,DX  ;从端口300H读数据到AX
输出时   OUT 0E0H, AX   ;直接寻址MOV DX,300H    OUT DX,AX      ;间接寻址
  1. 独立编址方式的端口操作

(1) 端口地址范围
直接寻址:端口地址8位,可寻址256个端口
间接寻址:端口地址16位,可寻址2^16=64K个端口

     例:MOV  DX, XXXXH      IN  AL, DX ;IN  AX,60H ;

(2) 传送数据的宽度
例:IN AL, DX
IN AX, DX

  1. I/O指令与I/O读写控制信号的关系
    程序执行IN指令时会在系统总线上产生有效
    的IOR信号(低电平有效),完成读(输入)操作
    执行OUT指令时会在系统总线上产生有效的IOW信号(低电平有效),完成写(输出)操作

8.3 I/O 端口地址分配

  • PC微机I/O地址的分配

    • PC微机把I/O空间分成两部分:系统板上的可编程接口芯片端口地址和常规外设接口控制卡端口地址。
    • PC微机I/O地址线有16根,对应的I/O端口编址可达64K。而IBM只用了低10位地址线,即地址线A0-A9,所以I/0端口的地址范围是: 0000H-03FFH,总共只有1024个端口

  • 现代微机I/O地址的分配
    windows操作系统具有即插即用的资源配置机制,因此I/O端口地址的分配是动态的

  • I/O端口地址选用的原则
    凡是被系统配置占用了的地址一律不能使用
    ② 未被占用的地址,用户可以使用,但对计算机厂家申明保留的地址,不要使用。
    ③ 用户可使用的地址为:300H-31FH
    82C55A:300H-303H
    82C54A:304H-307H
    8251A:308H-30BH
    8279A:30CH-30DH

8.4 I/O 端口地址译码

  • I/O地址译码方法
    1、全译码
    地址线A0-A9全部参加译码,一般在采用单端口时使用
    2、部分译码
    只有高位地址线参加译码,产生片选信号;而低位地址线直接接芯片,作为片内寻址。一般用于具有多个接口芯片的系统。
    3、开关译码法
    在部分译码方法的基础上,加上地址开关(如PC主板上的超频开关)来改变端口地址。

  • I/O地址译码电路的输入输出信号
    1、译码电路的输入信号
    I/O地址译码电路不仅仅与地址信号有关,而且
    与控制信号有关。例如:
    AEN信号:当AEN=1时,为DMA方式
    IOR和IOW信号:控制对端口的读/写等
    2、译码电路的输出信号
    产生一个片选信号CS。CS=0有效,产生唯一低
    电平信号,选中芯片内的寄存器端口;否则芯片
    未被选中

8.5 I/O 端口地址译码电路设计

  • IC器件组成的I/O地址译码电路设计
    【例】设计一个地址为2F8H的地址译码电路
    分析:这是一个单端口的地址译码电路,不需要
    产生片选CS,采用全译码方法


  • 固定式I/O地址译码电路设计
    例:使用74LS138(3-8译码器)为8个接口芯片设计译码电路,每个接口芯片内部的端口数目为32个,每个芯片的基址为00H、20H、40H、60H、80H、A0H、C0H、E0H。(只有A9-A0参与译码,其余地址线为0)。
    分析:根据74LS138的特点,其控制/译码线与地址线的分配如下,其中地址线低5位作为芯片内部端口译码32=2^5




  1. 开关式I/O地址译码电路设计
    例:某微机系统的I/O空间为000H-3FFH,分成连续的16段可选地址,每个段包括8个接口芯片,每个接口芯片拥有8个端口。
    分析:采用部分译码方法,允许16个段可以选择,所以采用4位开关。



    一般情况下,译码器和接口电路的连接方法

第八次作业

  1. 一个系统的地址译码使用74LS138实现,除图中的地址线外,其余地址线为0电平,请问8253端口地址是多少?

    因为CS为低电频有效,倒推其译码的结果是0,所以输入的A4A_4A4​~A2A_2A2​分别为000。

其中E1E_1E1​,E2E_2E2​为低电频有效,E3E_3E3​为高电频有效,因此A5A_5A5​~ A7A_7A7​ 分别为001。

由于OUT口的编号范围是0~2,因此A1A_1A1​A0A_0A0​的取值范围为00,01,10。

由于还可以选择控制口,所以A1A_1A1​A0A_0A0​还可以取11。

综上,A7A_7A7​到A0A_0A0​可以取到10000000B、10000001B、10000010B、10000011B。 因此其端口地址可以为080H—083H。

  1. 一个系统的地址译码使用74LS138实现,除图中的地址线外,其余地址线为0电平,请问8255的端口地址是多少?
    因为G1G_1G1​高电频有效,而A8A_8A8​和A7A_7A7​ 通过与门和G1G_1G1​相连,因此A8A_8A8​和A7A_7A7​都为1。

G2AG_2AG2​A和G2BG_2BG2​B均为低电频有效,所以A6A_6A6​和A5A_5A5​为00。

因为CS为低电频有效,倒推其译码的结果是2,所以输入的A4A_4A4​~A2A_2A2​分别为010。

由图可知,既可以选择A端口,也可以选择B端口,所以A1A0A_1A_0A1​A0​和可以取值为00或者01。

综上,A8A_8A8​ 到A0A_0A0​分别可以取到为0001 1000 1000——0001 1000 1011。因此端口地址可以为0188H—018BH。

汇编与接口技术期末复习笔记(1)—— 汇编部分相关推荐

  1. 《微型计算机原理与接口技术》复习笔记(二)

    使用教材为 <微型计算机原理与接口技术>(慕课版) 孙丽娟.李爱群.陈燕俐.周宁宁.邓玉龙编著 默认存储器单元的地址编排顺序从上往下,地址从低向高编排 微机原理复习笔记一 微机原理复习笔记 ...

  2. 《微型计算机原理与接口技术》复习笔记(一)

    使用教材为 <微型计算机原理与接口技术>(慕课版) 孙丽娟.李爱群.陈燕俐.周宁宁.邓玉龙编著 微机原理复习笔记二 微机原理复习笔记三 微机原理复习笔记四 微机复习笔记(一) 1. 二进制 ...

  3. 《微型计算机原理与接口技术》复习笔记(四)

    使用教材为 <微型计算机原理与接口技术>(慕课版) 孙丽娟.李爱群.陈燕俐.周宁宁.邓玉龙编著 微机原理复习笔记一 微机原理复习笔记二 微机原理复习笔记三 微机原理复习笔记四 中断系统 1 ...

  4. 《微型计算机原理与接口技术》复习笔记(三)

    使用教材为 <微型计算机原理与接口技术>(慕课版) 孙丽娟.李爱群.陈燕俐.周宁宁.邓玉龙编著 微机原理复习笔记一 微机原理复习笔记二 微机原理复习笔记四 微机原理复习笔记三 1. 存储器 ...

  5. 微机原理与接口技术期末复习资料

    8086 1.8086内部结构:总线接口部件BIU(地址加法器.专用寄存器组.指令队列缓冲器.总线控制逻辑),指令执行部件(算术逻辑单元.标志寄存器.通用寄存器.EU控制系统). 通用寄存器:AX(A ...

  6. 单片机原理及接口技术期末复习

    1.单片机概述 1.单片机又称单片微计算机,最初缩写为SCM(Source Code Management,源代码管理),它集成了中央处理单元CPU(包含运算器.控制器),并行I/O.串行I/O.定时 ...

  7. 单片机原理及接口技术期末复习知识点

    第1章 单片机概述 什么是单片机:单片机是由CPU.存储器.I/O接口及总线集成在一个芯片上. 简单了解AT89S51单片机简介. 相当于MCS-51系列中的87C51,AT89S51芯片内4KB的F ...

  8. 信息安全与技术期末复习

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.课程知识体系结构 二.信息加密技术 (一).古典密码体制 1.网络信息安全基本概念: 2.数据加密的组成及各部分含 ...

  9. 《微机原理与接口技术》复习参考资料,期末考试和专接本适用

    <微机原理与接口技术>复习参考资料 复习资料说明: 1.标有红色星号""的内容为重点内容 3.本资料末尾附有"<微机原理与接口技术>综合练习题与答 ...

最新文章

  1. Linux上实现ssh免密码登陆远程服务器
  2. 【转】vfork 和 fork的区别
  3. 3字节转换为有符号整型C语言,3.C语言整型数据
  4. 【模型解读】“全连接”的卷积网络,有什么好?
  5. java 非静态语句块_静态初始化代码块与非静态初始化代码块之间的区别是什么?...
  6. 【APIO2018】Duathlon 铁人两项 【圆方树】
  7. Android--Facebook Login without LoginButton
  8. 第四次学习记录(ROS)
  9. JsonPath工具类封装
  10. win10 SQL SERVER 2017安装详解
  11. Linux 信号量互斥编程
  12. Mac下librdkafka下载安装
  13. Tslib的触摸屏5点校准算法原理和实现
  14. 计算机中年级排名怎么操作,智学网年级排名查看方法规则介绍
  15. angularJs - 弹窗
  16. Springboot+Mybatis接口快速上手
  17. cadence 旋转快捷键_CADENCE快捷键归纳
  18. 录屏软件 ev录屏 安装与使用教程 教学演示视频提问必会的软件
  19. OSChina 周三乱弹 —— 生活终于对我这只小猫咪动手啦
  20. A 暴力搜索 剪枝是关键

热门文章

  1. jQuery的deferred对象深析
  2. S5pv210 出现一个离奇wince6.0 activesync 软件连接问题
  3. webRTC(十四):webrtc 端到端文本聊天
  4. lubuntu-调整分辨率
  5. NASA开始调试校准韦伯望远镜18面金色镜子,需三个月
  6. php保存视频,使用php输出mp4视频
  7. Matlab 预失真器放大,如何实现射频功率放大器的基带自适应预失真技术
  8. DBCO-C6-COOH|1425485-72-8|是DBCO酸的类似物,具有扩展的6-碳原子间隔臂
  9. html5绘制五环,浅析HTML5的Canvas——案例绘制
  10. 使用Openoffice实现并发多进程word文档转换预览