汇编语言

一、 选择题(5X2’=10’)
二、 填空题(6X2’=12’)
三、 简答题(4X7’=28’)

  • 有哪几种寄存器名

四、 程序分析与填空题(4X7’=28’)

  • 给一个程序段,填程序空缺
  • 简单题类似p22页 习题2.3
  • 做好课后习题

五、 程序设计题(2X7’=14’)

六、 论述题(1X8’=8’)

  • 开放性

搞熟例题和习题

第一章

  • 论述题为什么要学汇编语言

  • 进制转换

  • 补码

第二章

  • 背寄存器有哪些2.3
  • 简单题类似习题2.3
  • 习题2.5不会考这么难的题

第三章

  • p31 例3.1 3.2 p42 表3-1(输出字符,缓冲区)
  • 熟悉汇编语言工作环境,编译过程步骤
    • 程序跟踪调试
  • 功能调用命令 36页 37页填空题,用了哪些命令
  • DOS命令

第四章(重点)

  • 几种寻址方式(填空选择)
  • 框图

第五章

  • 熟悉指令 : 常用的加法、减法
  • 69页类型扩展 70页 例5.17/5.18
  • BCD码命令
  • 85页-87 例5.39 5.40搞清楚程序设计需要哪几部分
    • 数据段,代码段定义。主程序,关联
    • 就算主程序写不出来,也要把常规步骤写出来
  • 程序设计涉及到程序转移指令
    • 跳转
  • 习题 5.9 5.5 5.17 5.19 5.20
  • p78 例题5.29综合性例题

第六章伪指令

  • 宏指令不考
  • 清楚指令和伪指令的定义和应用场景
  • 伪指令的定义方法和格式
  • p103 ~ p107 所有例体
    • (ORZ /$)包括操作符
  • p107页 例题6.9根据 程序画图例
  • 习题6.1 6.7

第七章分支循环

  • 例题7.2 7.3
  • 分支向量表概念
  • 循环没时间可以不看
  • 习题7.1 7.2 7.6

第八章

  • 8.1 p136 过程定义与过程结构

第一章

1.计算机中数据的表示

1.1 不同进制

进制 代表
二进制 B
八进制 O
十进制 D
十六进制 H

1.2 进制转换

十六进制转十进制

$$
5FH = 516^1+1516^0 = 95D
$$

二进制转十进制

$$
101101.1B = 12^5+12^3+12^2+12^0+1*2^{-1} = 45.5D
$$

十进制转二进制

8 4 2 1 法凑数

1.3 带符号数的补码表示

负数用补码表示

方法:

  • 对正数各位取反,最低位加1

$$
求[-3]_补
$$

1
2
3
4
5
6
7
8
9
10
1.正数 

0000 0011
2.各位取反

1111 1100

3.最低位加1

1111 1101

补码的加减法

  • 加法

$$
[X+Y]_补 = [X]_补 + [Y]_补
$$

  • 减法

$$
[X-Y]_补 = [X]_补 + [-Y]_补
$$

1.4 无符号数

数值范围

8位二进制表示无符号数
$$
0 <= N <= 255
$$
16位二进制表示无符号数
$$
0 <= N <= 65525
$$

2.习题

  1. 什么是机器语言:机器语言就是用二进制编码组成的机器指令的集合和一组使用机器指令的规则。
  2. 什么是汇编语言:汇编语言是对机器指令中的操作码用英文单词的缩写描述,对操作数用标号、变量、常量描述。
  3. 汇编语言的特点:
    1. 与机器有关:移植性差,但可直接控制硬件。
    2. 程序效率高。
    3. 局限性:受指令的限制,如考虑存储单元等。
    4. 调试困难。
  4. 汇编程序与汇编源程序的区别是什么:汇编源程序是指用汇编语言编写的程序,而汇编程序特指将汇编源程序汇编成目标文件的编译程序。

第二章

1. 存储器

1.1 16位CPU

8086是16位结构的CPU ,16位结构的CPU结构特征

​ (1) 数据总线为16位

​ (2) 运算器一次最多可以处理16位的数据

​ (3) 寄存器的最大宽度位16位

​ (4) 寄存器和运算器之间的通路为16位

1.2 存储单位

1
2
3
4
8位 = 1个字节
8 bit = 1 Byte
2个字节 = 1个字
2 Byte = 1 word

2. 寄存器

记住就完了

8086CPU所有寄存器都是16位,可以存放两个字节(一个字)

通用寄存器

  1. AX:累加器。16位可分为AH高8位和AL低8位。
  2. BX:基址寄存器,存放数据和内存的起始偏移地址。BH、BL
  3. CX:计数寄存器,存放数据和存放重复操作的次数。CH、CL
  4. DX:数据寄存器,存放数据和存放32位数据的高16位。DH、DL

地址寄存器

  1. SP:堆栈指针,存放堆栈栈顶的偏移地址。
  2. BP:基址指针,存放内存中数据的偏移地址。
  3. SI:源变址寄存器,存放内存中源数据区的偏移地址;指在某些指令作用下它可以自动地递增或递减其中的值。
  4. DI:目的变址寄存器,存放内存中目的数据区的偏移地址,并在某些指令作用下自动地递增或递减其中的值。

段寄存器
$$
物理地址 = 段地址 * 16 + 偏移地址
$$

  • 分段方式中, 内存并没有分段 , 段的划分来自于CPU
  • 段地址和偏移地址都是16位二进制数
  • 段地址 * 16相当于二进制向左移动四位
1
2
3
段基址位1896H,偏移地址位1655H,其物理地址为

18960H + 1622H = 19FB5H
  1. CS:代码段寄存器,存放当前正在执行的程序段的段基址。

    • 在编写汇编程序时,必须要有代码段
  2. SS:堆栈段寄存器,存放堆栈段的段基址。

  3. DS:数据段寄存器,存放数据段的段基址。

  4. ES:附加段寄存器,存放另一个数据段的段基址。

指令指针寄存器

IP:指令指针寄存器,存放即将执行指令的偏移地址。

标志寄存器

  1. FLAGS:存放CPU的两类状态。
  2. 状态标志:CF(进位)、PF(奇偶)、AF(辅助进位)、ZF(零)、SF(符号)和OF(溢出)
  3. 控制标志:TF、IF(中断)和DF(方向)
标志名(加粗重点) 标志为1 标志为0
OF 溢出(是/否) OV NV
DF 方向(减/增) DN UP
IF 中断(允许/不允许) EI DI
SF 符号(负/正) NG PL
ZF 零 (是/否) ZR NZ
AF 辅助进位(有/无) AC NA
PF 奇偶(偶/奇) PE PO
CF 进位(有/无) CY NC

OF:溢出标志。

有符号数有效 (只有正数与正数相加、负数与负数相加才有可能溢出)

  • OF=1表示有两个有符号数的运算结果超出了可以表示的范围,结果是错误的;
  • OF=0表示没有溢出,结果正确。
  • 进行无符号数运算时也会产生新的OF标志(CPU不知道处理对象是否为有符号数),此时程序员可以不关心OF标志。// 因为计算机只计算二进制,所谓的有符号和无符号运算都是看程序员自己觉得的,对于有符号数程序员会利用补码定义负数

SF:符号标志。SF=1表示运算结果的最高位为“1“。

  • 对于有符号数

    • 在溢出标志OF=0时,SF=1表示运算结果为负,SF=0表示运算结果非负(SF = 最高位的值)。
    • OF=1时,由于结果是错误的,所以符号位也和正确值相反。例如:两个负数相加产生溢出,此时SF=0。
  • 对于无符号数运算,SF无意义(但是可以看出结果的大小规模)。

**ZF:零标志。

  • ZF=1表示运算结果为零,减法运算后结果为零意味着两个参加运算的数大小相等
  • ZF=0,表示运算结果非零。

CF:进位/借位标志。

无符号数有效

无符号数的加减法 = 有符号数补码的加减法

  • CF=1 表示两个无符号数的加法运算有进位,或者是减法运算有借位,需要对它们的高位进行补充处理;
    • 做减法时,直接观察 (被减数>减数 CF =1)
    • 做加法时,可以转化为十进制,看是否超过255
  • CF=0 表示没有产生进位或借位。
  • 进行有符号数运算时也会产生新的CF标志,此时程序员可以不关心CF标志。

DF:方向标志。

  • DF=0时,每次执行字符串指令后,源或目的地址指针用加法自动修改地址;
  • DF=1时用减法来修改地址。它用来控制地址的变化方向。

IF:终端允许标志。IF=1表示允许处理器响应可屏蔽中断请求信号,称为开中断,IF=0表示不允许处理器响应可屏蔽中断请求信号,称为关中断。

AF:辅助进位标志。在进行字操作时,低字节向高字节进位时,AF=1,否则为0。一般用于两个BCD数运算后调整结果用,对其他数的运算没有意义。

PF:奇偶标志 。PF=1表示运算结果的低8位中偶数个”1“;PF=0表示有奇数个”1“。它可以用来进行奇偶校验。

3. 32位80x86CPU的工作模式

三种工作模式 : 实模式、保护模式、虚拟8086模式

1.实模式

为了兼容16位机的特点

  • MS DOS 只能在实模式下运行

2.保护模式

主要工作模式

  • 全部地址线参与寻址
  • Windows系统及应用程序在保护模式下运行

3.虚拟8086模式

生成多个虚拟8086CPU,以便在运行实模式下的8086程序

  • Windows下打开的DOS窗口运行一个DOS应用程序,程序久运行在虚拟8086模式下。

4.习题

  1. 简述计算机系统组成:

    计算机由中央处理器CPU、存储器、输入系统和输出系统组成,由系统总线连接在一起。CPU包括运算器和控制器,运算器执行指令、控制器负责计算机的控制。存储器是计算机的记忆部件,以二进制形式存放程序和数据。输入输出系统包括大容量存储器,如硬盘。以及其他外设,如鼠标、键盘、显示器等。

  2. 简述16位机的各类寄存器的主要作用:参考本章2. 寄存器

  3. 写出每条汇编指令执行后的相关寄存器的值:

    1. Mov ax, 1345H ax = 1345H
    2. Mov ah, 24H ax = 2445H
    3. Mov al, 45H ax = 2445H
    4. Mov bx, 3412H bx = 3412H
    5. Mov al, bh ax = 2434H
    6. Mov ah, bl ax = 1234H
  4. 实模式下,写出段地址和偏移地址为1234:2002、1430:0042、FF00:0FFF的物理地址。(物理地址 = 段地址 * 16 + 偏移地址)

    1. $1234:2002 => 12340H + 2002H = 14342H$
    2. $1430:0042 => 14300H + 0042H = 14342H$
    3. $FF00:0FFF => FF000H + 0FFFH = FFFFFH$
  5. 下列各数均为十进制数,请采用8位二进制补码运算,并回答标志寄存器FLAGS中CF和OF的值,运算结果所代表的十进制数是多少?如果用16位二进制补码运算,其结果所代表的十进制数是多少?FLAGS中CF和OF的值呢?

    1. 86+69 // 题目是85+69 我直接将错就错
      $86=0101\ 0110_2,69=0100\ 0101_2$
      $86+69=0101\ 0110_2+0100\ 0101_2=1001\ 1011_2$

      补码转换$1001\ 1011_2\ => -0110\ 0101_2$此时十进制数为$-101$
      因为溢出OF=1,没有进位CF=0,最高位为1故符号位SF=1,计算结果不为零ZF=0
      16位下:$005BH$十进制数为$155$
      没有溢出OF=0,没有进位CF=0,最高位为0故符号位SF=0,计算结果不为零ZF=0

    2. 86+(-69)
      $86=0101\ 0110_2,-69=-0100\ 0101_2=1011\ 1011_2$
      $86+(-69)=0101\ 0110_2+1011\ 1011_2=1\ 0001\ 0001_2$
      补码转换$0001\ 0001_2=>0001\ 0001_2$此时十进制数为$17$
      因为没溢出OF=0,有进位CF=1,最高位为0故符号位SF=0,计算结果不为零ZF=0
      16位下:$0011H$十进制为$17$
      因为没溢出OF=0,没进位CF=0,最高位为0故符号位SF=0,计算结果不为零ZF=0

    3. 86-(-69) // 加法看进位,减法看借位

      $86=0101\ 0110_2,-69=-0100\ 0101_2=1011\ 1011_2$
      $86-(-69)=>(无符号) 86-187=0101\ 0110_2-1011\ 1011_2=0101\ 0110_2 + 0100\ 0101_2=1001\ 1011_2$
      补码转换$1001\ 1011_2\ => -0110\ 0101_2$此时十进制数为$-101$
      因为溢出OF=1,有借位CF=1,最高位为1故符号位SF=1,计算结果不为零ZF=0
      16位下:$005BH$十进制数为$155$
      没有溢出OF=0,有借位CF=1,最高位为0故符号位SF=0,计算结果不为零ZF=0

    4. 86-(69)
      $86=0101\ 0110_2,69=0100\ 0101_2$
      $86-69=0101\ 0110_2-0100\ 0101_2=0101\ 0110_2+1011\ 1011_2=1\ 0001\ 0001_2$

      补码转换$0001\ 0001_2=>0001\ 0001_2$此时十进制数为$17$
      因为没溢出OF=0,无借位CF=0,最高位为0故符号位SF=0,计算结果不为零ZF=0
      16位下:$0011H$十进制数为$17$
      没有溢出OF=0,没有借位CF=0,最高位为0故符号位SF=0,计算结果不为零ZF=0

  6. 给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围从__到__
    答:偏移地址16位从0000H~FFFFH
    故寻址从00010H+0000H ~ 00010H+FFFFH 即00010H到1000FH

  7. 有一数据存放在内存20000H单元中,现给定段地址为SA,若想从偏移地址寻到此单元,则SA应满足的条件是:最小为__,最大为__。
    答:偏移地址16位从0000H~FFFFH
    寻址到20000H,最小为(20000H-FFFFH=10001H)除10H向上取整得到1001H,则最大为(20000H-0000H)除10H向下取整得到2000H

    • 除10H即除16
  8. 已知8086系统某存储单元物理地址为:52506H,你认为段基址的最大值、最小是分别是多少?8086微机最多可以有多少个不同的段基址?

    答:同上计算,最大:52506H/10H向下取整得到5250H(偏移地址为0),最小:(52506H-FFFFH)/10H向上取整得到4251H。
    段地址16位,故最多有$2^{16}=65536$个段基址。

  9. 从物理地址为00100H开始到00103H单元中顺序存放的数据为:12H、34H、56H,78H。请画出数据存放示意图,并回答以下问题:
    image-20231112163008184

    1. 写出地址00101H字节单元的内容;
      答:34H
    2. 写出地址00102H字节单元的内容
      答:56H,若为字单元则7856H(小端:低字节低地址,高字节高地址)

第四章

1.立即寻址方式

定义

  • 操作数直接写在指令中

  • 用途: 用于直接指定一个常数送给寄存器

注意

  • 8086中立即数是8位或者16位
  • 立即寻址原来表示常数
  • 立即寻址方式只能用于源操作数字段
  • 立即数的类型必须与目的操作数的类型一致

举例

1
2
MOV AL , 6H
MOV AX , 12AFH

2.寄存器寻址方式

定义

  • 操作数就是寄存器中的值

    • 指令中给出寄存器名
  • 用途: 用于指定2个寄存器作为操作数

注意

  • 指令执行不需要访问内存因而执行速度快

举例

1
MOV AX , BX

3.直接寻址方式

定义

  • 操作数的有效地址EA(偏移地址)就在指令中 指令中直接给出了操作数的有效地址

    • 由于存储器各个段的段地址已分别由各个段寄存器存放,只要知道偏移地址就能求出其物理地址

    • 操作数的段地址为数据段,由DS指出,即操作数本身存放在数据段中

举例

1
2
3
4
MOV AX , DS:[4050]
方括号中的数值作为操作数的偏移地址(有效地址)

操作数的物理地址 = (DS) * 10H + EA

注意

  • 编写汇编源程序.asm文件时 , 对于直接寻址方式而言,必须用前缀 “ DS: “中指出该单元在数据段中
    • DS:[2000H]代表一个数据段的存储单元,偏移地址为2000H
    • 没写前缀DS: ,2000H代表的是立即数
  • 在Debug的A命令输入命令(执行汇编指令),就不要加上前缀,系统默认为数据段

4.寄存器间接寻址方式

定义

  • 操作数的有效地址EA就在寄存器中
    • 不是把寄存器的内容作为操作数,而是把寄存器的内容作为操作数的地址,而操作数还在内存中。
  • 用途: 适用于简单的表格处理
    • 用寄存器间接指向一个内存单元,寄存器的值不同,指向的内存单元的地址就不同,常用于循环程序中

注意:

  • 寄存器间接寻址只允许 BX BP SI DI 这四个寄存器作为间接地址寄存器

SI为源变址寄存器,DI为目的变址寄存器,BP为基址寄存器

  • BX BP SI 默认DS作段地址寄存器
  • BP 默认 SS作段地址寄存器

举例

1
2
3
4
5
6
MOV AX , [BX]
已知 ( DS ) = 1500H , ( BX ) = 4580H
则 EA = ( BX ) = 4580H
物理地址 = 15000H + 4580H = 19580H
若 (19580H) = 4580H
(AX) = 4589H
1
2
3
4
5
6
MOV SS:[DI] , AX
已知(ES) = 2500H, (DI) = 5138H
则 (EA) = 25000H + 5138H = 2A318H
若 (AX) = 2468H
则 (2A318H) = 68H
(2A319H) = 24H
1
2
3
4
5
MOV AX , [BX]/[SI]/[DI]   默认DS寄存器作段地址

MOV AX , [BP] 默认SS寄存器

MOV ES:[DI] , AX 指定ES寄存器

5.寄存器相对寻址方式

定义

  • 操作数的有效地址EA是一个寄存器和位移量之和(比寄存器间接寻址多一个位移量)

    • 默认搭配是DS段寄存器和BX,SI,DI

    • SS段寄存器和BP

  • 操作数物理地址 = (DS) * 10H + (BX) + 8位(16)位位移量

  • 用途: 常用于查表操作 用于访问一维数组

举例

1
2
3
4
5
6
7
8
MOV AX , TOP[SI]

TOP为位移量
已知(DS) = 1500H (SI) = 7310H ,TOP = 25H
则有效地址EA = TOP + (SI) = 7310H + 25H = 7335H
物理地址 = (DS) * 10H + EA = 15000H + 7335H = 1C335H
若 (1C335H) = 2428H
则 (AX) = 2428H

这三条指令是等效的

1
2
3
MOV AX , ARRY[BX]
MOV AX , [ARRY][BX]
MOV AX , [ARRY+BX]

这两条指令是等效的

1
2
MOV [BX].2623H , AX
MOV [BX+2623H] , AX

6.基址变址寻址方式

定义:

  • 操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和

注意

  • 允许使用的基址寄存器为 BX 和 BP
  • 允许使用的变址寄存器为 SI 和 DI
1
2
3
4
物理地址 = ( DS ) * 10H + ( BX ) + ( DI )
物理地址 = ( DS ) * 10H + ( BX ) + ( SI )
物理地址 = ( SS ) * 10H + ( BP ) + ( DI )
物理地址 = ( SS ) * 10H + ( BP ) + ( SI )

举例

1
2
3
4
5
MOV AX , [BX+DI]
已知 (DS) = 2100H, (BX) = 0158H (DI) = 10A5H (221FD) = 34H, (221FE) = 95H ,(AX) =0FFFFH
有效地址EA = (BX) + (DI) = 0158H + 10A5H = 11FDH
物理地址 = (DS) * 10H + EA = 21000H + 11FDH =221FDH
执行后 (AX) = 953AH
1
2
3
4
5
6
MOV AX, [BX][SI]  	默认DS寄存器作段地址
MOV AX, [BP][DI] 默认SS寄存器作段地址
MOV AX, ES:[BX][DI] 指定ES寄存器作段地址
MOV DX, [BP][SI] 默认SS寄存器作段地址
MOV [BX+DI] , CX 默认DS寄存器作段地址
MOV [BP+SI] , AL 默认SS寄存器作段地址

7.相对基址变址寻址方式

定义

  • 有效地址是一个基址寄存器和一个变址寄存器以及一个位移量之和(比基址变址寻址多一个位移量)
  • 用途: 可以用于二维数组的处理

注意

  • 允许使用的基址寄存器为BX和BP
  • 允许使用的变址寄存器为SI和DI
  • 位移量可以为常量或者符号地址

举例

1
2
3
4
物理地址 = (DS) * 10 H + (BX) + (DI) + 8(16位)位移量
物理地址 = (DS) * 10 H + (BX) + (SI) + 8(16位)位移量
物理地址 = (SS) * 10 H + (BP) + (SI) + 8(16位)位移量
物理地址 = (SS) * 10 H + (BP) + (DI) + 8(16位)位移量
1
2
3
4
以下三种表达方式是等效的 EA = MASK+(BX)+(SI) 物理地址 = (DS) * 10H + EA
MOV AX , MASK[BX][SI] 默认DS寄存器作段地址
MOV AX , [MASK+BX+SI] 默认DS寄存器作段地址
MOV AX , [BX+SI] .MASK 默认DS寄存器作段地址

8.总结

  • 不管变量的类型如何, 其有效地址总是16位

1)错误操作

双操作数指令的两个操作数,长度必须匹配

1
MOV AX , AH ; AX为16位,AH为8位

双操作数指令的两个操作数中,不能两个操作数同为内存单元

​ 因为CPU与内存交换数据,通过地址线选中该内存单元,不能两个操作数同时经过数据线对内存单元进行读出或者写入

1
2
MOV B , A
MOV [BX] , [DI]

9.习题

  1. 指出以下指令的寻址方式,array是变量。
1
2
3
4
5
6
7
8
(1)MOV	AX,9	;	立即数寻址
(2)MOV BYTE PTR[BX],9 ; 寄存器间接
(3)MOV BX,[DI] ; 寄存器寻址
(4)MOV AX,BX ; 寄存器寻址
(5)MOV [SI+BX],9 ; 基址变址寻址
(6)MOV ARRAY[BX],CX ; 寄存器相对
(7)MOV AX,ARRAY+9 ; 直接寻址
(8)MOV AX,ARRAY[BX+DI] ; 相对基址寻址
  1. 假定(DS)=1200H,(SS)=4400H,(BX)=463DH,(BP)=2006H,(SI)=6A00H,位移量D=4524H,以AX寄存器为目的操作数,试写出以下各种寻址方式下的传送指令,并确定源操作数的有效地址EA和物理地址。
1
2
3
4
5
6
7
(1)立即寻址:MOV AX,D  => AX = 4524H
(2)直接寻址:MOV AX,DS:[D] => AX = 12000H+4524H = 16524H
(3)使用BX的寄存器寻址:MOV AX,BX => AX = 463DH
(4)使用BX的间接寻址:MOV AX,[BX] => AX = 12000H+463DH = 1663DH
(5)使用BP的寄存器相对寻址:MOV AX,[BP+D] => AX = 44000H+2006H+4524H = 4A52AH
(6)基址变址寻址:MOV AX,[BX+SI] => AX = 12000H+463DH+6A00H = 1D03DH
(7)相对基址变址寻址:MOV AX,[BX+SI+D] => AX = 12000H+463DH+6A00H+4524H=21561H

第五章

1.数据传送指令

1)MOV 传送指令

规定

  • 操作数与目的操作数的长度必须 明确且一致
    • MOV AH , 258
  • 目的操作数与源操作数 不能同为存储器 , 不允许在两个存储单元直接直接传送数据
    • MOV [AX] , [DI]
  • 目的操作数不能为 CS 或 IP , 因为CS:IP要指向的是当前要执行的指令所在的地址
  • 目的操作数不可以是立即数

注意

段地址寄存器(DS SS CS ES)必须通过寄存器得到段地址,不能直接由符号地址、段寄存器、立即数得到

1
2
3
4
5
以下都是错误的
MOV DS , DATA_SEG 符号地址
MOV DS , ES 段寄存器
MOV DS , 1234 立即数
MOV CS , AX 指令合法,但是代码寄存器不能赋值(一个程序至少要有CS寄存器)

2)PUSH 进栈指令

格式

  • PUSH SRC 将源操作数压入堆栈

操作

SRC为源操作数

  • ( SP ) <— ( SP ) - 2
  • (( SP ) + 1 , (SP)) <— ( SRC )

指令将源操作数压入堆栈 , 目的操作数的地址由 SS:SP 指出 , SP总是指向栈顶(大地址)

入栈时, 要将栈顶指针 SP 减2(2个字节,16位) , 来指向新的内存地址接受16位源操作数 , 并且同时指向新的栈顶

3)POP 出栈指令

格式

  • POP DST

操作

DST表示目的操作数

  • ( DST ) <— (( SP ) + 1 , ( SP ))
  • ( SP ) <— ( SP ) + 2

堆栈中源操作数地址由 SS:SP 指出

源操作数弹出后 , SP + 2 ,下移一个字, 指向新的栈顶

举例

1
2
PUSH	[2018]  ;把地址为DS:[2018]的字送往栈顶
POP [2018] ;把栈顶的字送往地址为DS:[2018]的内存

4)XCHG 交换指令

格式

  • XCHG OPR1 , OPR2

操作

  • ( OPR1 ) <— —> ( OPR2 )
  • OPR1 和 OPR2都是目的操作数 ,执行后交换了位置
  • 不能用立即数寻址

错误

1
2
3
XCHG	AX , 5		操作数不能为立即数
XCHG [BX] , VAR 操作数不能同为内存单元
XCHG AX , BH 长度不一致

2.累加器专用传送指令

注意

  • 这组指令只限于 AX , AL (累加器)
  • 输入/输出(IO)端口是CPU与外设传送数据的接口,单独编制,不属于内存
  • 端口地址范围是0000 ~ FFFFH

1) IN(input)输入

定义

  • 把端口号PORT或由DX指向的端口的数据输入到累加器,根据端口号的长度,有长格式和短格式两种形式

长格式

定义:

  • 机器指令长度为2个字节 , 端口号占一个字节

格式:

  • IN AL , PORT(字节)
  • IN AL , PORT(字)

PORT为端口号 , 范围是00 - FFH

  • 八位二进制 / 两位十六进制

短格式

定义:

  • 端口号范围为 0100H - 0FFFFH
  • 短格式机器指令长度为1个字节,因为端口号存在DX寄存器中

格式:

  • IN AL , DX(字节)
  • IN AX , **DX(**字)

2)OUT(output) 输出

定义

  • 把累加器的数据输出到端口PORT或由DX指向的端口

长格式:

  • OUT PORT , AL(字节)
  • OUT PORT , AX(字节)

短格式:

  • OUT DX , AX(字节)
  • OUT DX , AL(字节)

3)XLAT(translate) 换码

定义:

  • 把BX+AL的值作为以后小地址,取出其中一个字节送到AL

格式:

  • XLAT

操作:

  • AL <— ( BX+AL )

3.地址传送指令

  • LEA 有效地址送寄存器
  • LSD 指针送寄存器和DS
  • LES 指针送寄存器和ES

1)LEA 有效地址送寄存器指令

格式

  • LEA REG , SRC

操作

  • REG <— SRC

定义:

  • 把源操作数的有效地址EA(偏移地址)送到指定寄存器
1
2
LEA	BX , TABLE  ;	MOV BX , OFFSET [2016H]
指令执行后, BX = 2016H

2) LDS 指针送寄存器和DS指令

格式:

  • LDS REG , SRC

操作

  • REG <— ( SRC )
  • DS <— ( SRC + 2 )

定义:

  • 源操作数SRC所指向的内存单元中的两个字送到指定的寄存器REG和DS
1
2
3
LDS  SI , [ BX ]
执行前 , 如果 DS = 2000H , BX = 0400H, (2000:0400) = 1234H , (2000:0402) = 5678H
执行后 , SI = 1234H , DS = 5678H (BX寄存器默认的段寄存器是DS)

3) LES 指针送寄存器和ES指令

格式:

  • LDS SI , [BX]

操作

  • REG < — ( SRC )
  • ES < — ( SRC+2 )

4.标志寄存器传送指令

  • LAHF 标志送AH寄存器
  • SAHF AH送标志寄存器
  • PUSHF 标志入栈
  • POPF 标志出栈

四条指令的格式相同,只有操作码部分,操作数为固定默认值,传送类指令(除SAHF\POPF)均不影响标志位

5.算术运算指令

重要!!!

1)类型扩展指令

  • CBW 字节扩展成字
  • CWD 字扩展成双字

这两条指令的格式相同,只有操作码部分,没有操作数部分。

操作数默认是累加器,无需在指令中给出

CBW :

  • 当执行CBW时,默认将AL寄存器的内容扩展到AX寄存器中,扩展方法为符号扩展
    • 符号扩展即如果AL的最高位为1(负数) , 则CBW指令扩展时使 AH = FFH
    • 如果AL的最高位为0 , 则CBW指令扩展时使 AH = 00H

CWD:

  • 执行CWD时,默认将AX寄存器的内容扩展到(DX,AX)中
    • DX存放双字中的高位
    • AX存放双字中的低位
  • 如果AX最高位为1,CWD指令扩展时使 DX = FFFFH
  • 如果AX最高位为0,CWD指令扩展时使 DX = 0000H

举例

正数扩展

1
2
3
4
5
MOV AH , 11H
MOV DX , 1111H
MOV AL , 52H
CBW 指令执行后 , AX = 0052H
CWD 指令执行后 , DX = 0000H (AX最高位为0), AX =0052H(存放AX中低位)

负数扩展

1
2
3
4
5
MOV AH , 11H
MOV DX , 1111H
MOV AL , 88H ;88H最高位为1
CBW 指令执行后 , AX = FF88H
CWD 指令执行后 , DX = FFFFH , AX = FF88H

2)加法指令

  • ADD 加法
  • ADC 带进位加法
  • INC 加1

加减运算必考 ADC SBB , CF , OF

ADD:

格式:

  • AADD DST , SRC

操作:

  • ( DST ) <— ( DST ) + ( SRC )

注意:

  • 加法指令执行后会影响标志寄存器中的CF和OF标志位

举例

无符号为数的溢出标志位CF

1
2
3
4
5
6
7
8
9
10
11
MOV	AL , 72H
ADD AL , 93H
1.当93H72H被视为无符号数时
执行后AL=05HAL只能存放8位二进制,最高位的1被送进了标志寄存器的CF位,即产生了进位,也叫无符号位的溢出
无符号数加法,如果CF=0,表示结果是正确的。如果CF=1,表示结果是错误的

2.当93H72H被视为有符号数时
72H = 01110010B = 114D = [114D]补
93H = 10010011B = [-109D]补
等同于 114+(-109) = 5
有符号数加法,不需要考虑CF的结果

有符号数的溢出标志位OF

1
2
3
4
5
6
7
8
9
MOV	AL , 92H
ADD AL , 93H

92H93H均为有符号数时
92H = 10010010B = [-110D]补
93H = 10010011B = [-109D]补
加法运算结果应该是(-219)超过了AL范围,所有结果移除了,OF置为一

只有相同符号的数才有可能溢出

ADC:

格式:

  • ADD DST , SRC

操作:

  • (DST) <— (SRC) + (DST) + CF

CF即为标志位的值,无符号数加法考虑

1
2
3
4
5
6
7
8
9
10
11
12
设数A存放在DXAX , DX中存放高位字。数B存放在BXCXBX存放高位字
DX = 2000H , AX = 8000H
BX = 4000H , CX = 9000H

ADD AX , CX
ADC DX , BX

ADD AX , CX执行后,AX = 1000H , CF = 1, OF = 0 有进位
ADC DX , BX执行后,DX = 6001H , CF = 0, OF = 0 加上了CF中的1

无论无符号数还是有符号数,低位字相加无需考虑溢出,只有高位字相加产生的CF位和OF位才是判断是否溢出的依据

3)减法指令

  • SUB 减法
  • SBB 带借位减法
  • DEC 减1
  • NEG 求补
  • CMP 比较

SUB减法指令

格式:

  • SUB DST , SRT

操作:

  • (DST) <— (DST) - (SRC)

SBB带借位减法指令

格式:

  • SBB DST , SRC

操作:

  • (DST) <— (DST) - (SRC) - CF

DEC减1指令

格式:

  • DEC OPR

操作:

  • (OPR) <— (OPR) - 1

该指令不影响CF标志位

NEG求补指令(求相反数)

格式:

  • NEG OPR

操作:

  • (OPR) <— -(OPR)

CMP比较指令

格式:

  • CMP OPR1 , OPR2

操作:

  • (OPR1) - (OPR2)

CF 标志位指明无符号的溢出

OF标志位指令有符号数溢出

举例

1
2
3
4
5
6
7
8
MOV	AL , 72H
SUB AL , 94H

1.对于无符号数减法时。计算机允许被减数向高位借位,体现在CF标志位。需要借位时,将CF标志位置1.
相当于运算172H - 93H = DFH

2.对于有符号数减法时。被减数72H是正数(符号位为0),减数93H是负数(符号位为1)。运算结果DFH(符号位为1,是个负数)。此时OF置1,表示溢出
72H-93H = (114D) - (-109D) = 223D ,超出了9位表示范围,溢出了

当两个有符号数的符号相同时,结果是不会发生溢出的。只有符号数的符号相反才有可能发生溢出,需要通过OF标志位判断

1
2
3
4
5
6
7
8
9
DX = 2001H , AX = 8000H
BX = 2000H , CX = 9000H

1.SUB AX , CX
2.SBB DX , BX

1.执行后 CF = 1 ,相当于18000H-9000H = F000H
此时 CF = 1 ,OF = 0 , ZF = 0 , SF = 1
2.执行后 DX = 0000H ,相当于DX = DX - BX - CF = 2001H - 2000H - 1 = 0000H

4)乘法指令

  • MUL 无符号数乘法
  • IMUL 有符号数乘法

MUL:

格式:

  • MUL SRC

操作:

  • 当操作数为字节时, (AX) <— (AL) * (SRC)
  • 当操作数为字时, (DX , AX) <— (AX) * (SRC)

注意:

  • IMUL格式和操作与MUL相同。

  • 乘法指令中 , 目的操作数默认认为累加器AX

  • 两个相乘数必须长度相同,根据SRC长度而定是AL或者AX。SRC可以是寄存器或者变量,不能是立即数(立即数长度不确定)

  • 运算结果长度是乘数的两倍,不会出现溢出情况

举例:

1
2
3
4
5
6
7
MOV	AL , OF1H
MOV BL , AL
MUL BL
IMUL BL

作为无符号数相乘 , 执行后 AE = E2E1H F1H * F1H = E2E1
作为有符号数相乘 , 执行后 AE = OOE1H(表示两个负数相乘,结果是正数) OFH * OFH = 00E1H

5)除法指令

  • DIV 无符号数除法
  • IDIV 有符号数除法

DIV

格式:

  • DIV SRC

操作:

  • SRC为字节时,(AL) <— (AX)/(SRC)的, (AH) <— (AX)/(SRC)的余数
  • SRC为字时,(AX) <— (DX,AX)/(SRC)的, (DX) <— (DX,AX)/(SRC)的余数

IDIV

  • IDIV指令格式和操作与DIV相同
  • IDIV中:最终商的符号应该是两个操作数符号的异或,而余数的符号和被除数符号一致

注意:

  • 除法指令中,目的操作数必须是累加器AX和DX(乘法只能是AX)
  • 被除数长度应为除数长度的两倍,余数放在目的操作数的高位,商放在目的操作数的低位
  • SRC不能是立即数
  • 在除法中,会产生溢出现象
    • 除数是字节类型时,除法指令要求商为8位。
      • 如果被除数的高8位绝对值 > = 除数的绝对值。商会产生溢出
    • 除数是字类型时,除法指令要求商为16位。
      • 如果被除数的高16位绝对值 > = 除数的绝对值。商会产生溢出

举例

作字节除法

1
2
3
4
5
6
7
MOV AX , 3000H
MOV BL , 2
DIV BL

操作是- (AL) <--- (AX)/(SRC)的商, (AH) <--- (AX)/(SRC)的余数
但是此时被除数的高八位(AH = 3H)的绝对值 > BL,产生了溢出
相当于300H/2H = 768/2 = 384 ,显然超过了AL8

作字除法

1
2
3
4
5
6
7
MOV	AX , 300H
CWD
MOV BX , 2
DIV BX

执行CWD后,因为AX最高位为0DX = 0000H , AX = 0000H
被除数的高16位为0,所以不会溢出

6)BCD码(8421)的十进制调整指令

  • DAA 加法的十进制调整指令
  • DAS 减法的十进制调整指令

DAA:

格式:

  • DAA

操作:

  • 加法指令中,以AL为目的操作数,当加法运算结束后,用DAA把AL中的和调整为正确的BCD码格式
1
2
如果AL4位 > 9 ,或AF = 1, 则AL = AL +6
如果AL4位 > 9 ,或CF = 1, 则AL = AL + 60H ,CF = 1

举例:

AF辅助进位标志

8位运算或16位运算时如果有进位或借位CF就等于1,而4位运算时如果有进位或借位AF就等于1。

AF是为了在BCD码运算时,要用到的,因为BCD码是以4位表示的。

1
2
3
4
AL = 28H = 28(BCD) BL = 65H = 65(BCD)

ADD AL , BL 执行后, AL = 8DH
DAA 执行后, AL = AL + 6H = 8DH + 6H = 93(BCD)
1
2
3
4
5
如果AX = 88H = 88(BCD) , BX = 65H = 65(BCD)

ADD AL , BL ;AL = 88+65 = 11H , AF = 1, CF = 1
DAA ;因为CF = 1,AF = 1 。所有AL = 11H + 66H = 77H = 77(BCD) , CF = 1
ADC AH , 0 ;因为CF = 1 。所有AX = 177H = 177(BCD)

DAS:

格式

  • DAS

操作

  • 减法指令中,以AL为目的操作数,减法运算结束后,用DAS把差调整为BCD码
1
2
如果AL4位 > 9 ,或AF = 1, 则AL = AL - 6
如果AL4位 > 9 ,或CF = 1, 则AL = AL - 60H ,CF = 1

举例:

1
2
3
4
如果AL = 93H = 93(BCD) , BL = 65H = 65(BCD)

SUB AL , BL ;AL = 93H - 65H = 2EH
DAS ;AL = 2EH + 2EH - 6H = 28(BCD)

6.逻辑与位移指令

  • AND
  • OR
  • NOT
  • XOR 异或
  • TEST 测试

逻辑指令按二进制位进行操作,操作数可以看成二进制位串。双操作数指令中,至少有一个操作数必须存放在寄存器中,另外一个操作数可以使用任意寻址方式

注意

  • 逻辑运算指令只会对部分标志位产生影响
  • NOT指令不影响任何标志位
  • 其他指令将使CF 和 OF为0,AF位无定义

AND

格式

  • AND DST , SRC

操作:

  • (DST) <— (DST)^ (SRC)

OR

格式:

  • OR DST , SRC

NOT

格式:

  • NOT DST , SRC

XOR

格式:

  • XOR DST , SRC

TEST

格式:

  • TEST OPR1 , OPR2

操作:

  • (OPR1) ^ (OPR2)
  • test指令的两个操作数相与的结果不保存,只根据结果置标志位

7.移位指令

  • SHL 循环左移
  • SAL 算术左移
  • SHR 循环右移
  • SAR 算术右移
  • ROL 循环左移
  • ROR 循环右移
  • RCL 带进位循环左移
  • RCR 带进位循环右移

移位指令均是双操作数指令,指令格式相同

SHL: 逻辑左移

格式

  • SHL OPR , 1
  • SHL OPR, CL (其中CL寄存器的值大于1)

注意:

  • 其中OPR为寄存器或者内存单元 , 移位次数可以是1或CL寄存器
  • 如果移位次数大于1,则可以在该移位指令前把移位次数送到CL寄存器中

左移:

  • 算术左移和逻辑左移,操作结果相同,均是最低位补0。移出的最高位送CF标志位

  • ROL循环左移时,OPR整体向左移一位,最高位移出,同时送CF标志位和最低位

  • RCL带进位循环左移时,OPR整体左移一位,此时最高位移出送CF标志位,而CF标志位原始的数值送OPR最低位

右移:

  • 逻辑右移时,最高位补0 , 移出的最低位送CF标志位。
  • 算术右移时,OPR被认为是有符号数,最高位补符号位自身移出的最低位送CF标志位。
  • ROR循环右移时,OPR整体向右移一位,最低位移出,同时送CF标志和最高位。
  • RCR带进位循环右移,OPR整体右移一位,此时最低位移出送CF标志位,CF标志位原始的数值送OPR最高位

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
AX = 13H = 00010011B , CF = 1
SHL AX , 1
SHR AX , 1
SAR AX , 1
ROL AX , 1
ROR AX , 1
RCL AX , 1
RCR AX , 1

SHL: 00010011B左移一位,得到00100110B = 26H CF = 0,相当于AX内容乘以2
SHR: 00010011B右移一位,得到00001001B = 09H CF = 1
SAR: 00010011B整体右移,最低位1送入CF标志位,最高位补符号位本身,即0,结果是00001001B = 26H,CF = 1
ROL: 00010011B整体左移,最高位0同时送入CF和最低位,结果是00100110 = 26H ,CF = 0
ROR: 00010011B整体右移,最低位1同时送入CF和最高位,结果是10001001 = 89H ,CF = 1
RCL: 00010011B整体左移,最高位0送CF,CF原始值1送最低位,结果是00100111 = 27H , CF = 0
RCR: 00010011B整体右移,最低位1送CF,CF原始值0送最高位,结果是00001001 = 09H , CF = 1

8.串操作指令

9.程序转移指令

  • 无条件转移指令
  • 条件转移指令
  • 循环指令
  • 子程序调用指令
  • 中断调用指令

无条件转移指令

  • JMP : 无条件转移到指令指定的地址去执行程序。指令中必须指定转移的目标地址
    • 根据目标地址,可以将无条件转移指令分为段内转移和段间转移

段内转移:

  • 转移的目标地址和本条跳转指令在同一个代码段。跳转后,CS寄存器的值没有发生转变只有IP寄存器有了改变

段间转移:

  • 转移的目标地址和本条跳转指令不在同一个代码段。跳转后,CS寄存器的值发生了改变

循环指令

  • LOOP 循环
  • LOOPZ/LOOPE 当为0/相等时循环 ZF = 1
  • LOOPNZ/LOOPNE 当不为0/不相等时循环 ZF = 0

循环指令的操作均是 首先执行CX寄存器减1,然后根据测试条件决定是否转移

1.(CX )=( CX )- 1

2.判断cx中的值

​ 不为0转到标号处执行程序

​ 为0则向下执行


习题5

  1. 设V是变量,指出下列错误的指令,说出错误原因并修改。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    MOV	AX,	[DX]	;	DX不能做内存指针,寄存器间接寻址方式有:BX、SI、DI、BP可以
    MOV DS, DATA ; 段不能直接送DS,需要先送AX,再由AX送DS
    MOV CS, AX ; CS不能修改
    MOV AX, DL ; 数据类型不一致
    PUSH AL ; 必须为16位,应改成AX 不能WORD PTR AL
    ADD [BX], [DI] ; 不能同问内存
    LEA [BX], V ; 不能对内存直接写立即数 要改成BX
    MOV [DX], OFFSET V ; DX不能做内存指针,去掉方括号
    MOV [SI], 2 ; 立即数位数不确定,需要加PTR运算符
    MUL BX, CX ; MUL 为单操作数 默认目的寄存器为AX、DX 或 AX
    DIV 5 ; 立即数不能作为除数,需要先存入另一寄存器
    MOV BYTE[SI], AX ; 类型不一致或用了保留字做标识符
    MOV AX, [SI+DI] ; 只能基址变址,需要将SI、DI其中一个改为BP/BX
    SHR AX, 4 ; 移位次数非1时,只能用CL计数
    CMP 6, AX ; 立即数不能出现在目的地址
    MOV [FFFF], AX ; FFFF会被当做标识符,需要加前缀0或后缀H
    MOV AX, BX + 4 ; 如果相对基址,加方括号
    JMP FAR PRO ; 需加PTR运算符
  2. 在数据段定义了ARRAY数组,其中依次存储了4个字数据,根据以下要求把第4个字送AX寄存器。

    1. 直接寻址

      1
      MOV	AX,	ARRAY+6
    2. 使用BX的间接寻址

      1
      2
      MOV	BX,	OFFSET [ARRAY+6]
      MOV AX, [BX]
    3. 使用BX和ARRAY的寄存器相对寻址

      1
      2
      MOV	BX,	0006H
      MOV AX, ARRAY[BX]
    4. 基址变址寻址

      1
      2
      3
      MOV	SI,	0006H
      LEA BX, ARRAY
      MOV AX, [BX][SI]
    5. MOV以外的其他指令

      1
      2
      SUB	AX,	AX
      ADD AX, ARRAY+6
  3. 溢出标志位OF与进位标志位CF有何作用和区别

1
处理器对两个操作数进行运算时,按照无符号数求得结果,并相应设置进位标志CF;同时,根据是否超出有符号数的范围设置溢出标志OF。应该利用哪个标志,则由程序员来决定。也就是说,如果将参加运算的操作数认为是无符号数,就应该关心进位;认为是有符号数,则要注意是否溢出。
  • 无符号数关心CF
  • 有符号数关心OF

第六章 伪指令

1.伪指令

定义

  • 在汇编程序对源程序进行汇编期间由汇编程序处理的操作
  • 指令是在程序运行期间由CPU执行

1)段定义伪指令

1
2
3
segment_name SEGMENT	; 段名
... ; 段定义的内容
segment_name ENDS

2)数据定义域存储器单元分配伪指令

数据定义:[变量名] 操作码 N个操作数 [;注释] // N个操作数字节大小全和操作码规定一样

1
2
3
4
5
6
7
8
9
10
11
12
// 重点
DB ; 伪操作定义字节 8位 BYTE
DW ; 伪操作定义字 16位 WORD
// 没那么重要
DD ; 双字 32位 DWORD
DF ; 6字节的字 48位 FWORD
DQ ; 4字 64位 QWORD
DT ; 10字节的字 80位 TBTYE
如:
D_BYTE DB 10, 10H ; 内存情况为 0A 10
D_WORD DW 14, 100H, -5, 0ABCDH ; 0E 00 00 01 FB FF CD AB
D_DWORD DD 4*8 ; 20 00 00 00

操作数为字符串。问号‘?’仅预留空间。

1
2
3
4
5
MESSAGE DB 'HELLO?',?	;	问号?通常被系统置0
DB 'AB',?
DW 'AB'
内存情况:
'H' 'E' 'L' 'L' 'O' '?' -- 'A' 'B' -- 'A' 'B'

用操作符复制操作数

1
2
ARRAY DB 2 DUP(1,3,2 DUP(4,5)) ; 循环2份DUP1的内容,DUP1内首先是1 3 ,然后循环两遍4 5
;即1 3 4 5 4 5 1 3 4 5 4 5

2)类型属性操作符

访问内存变量要指定地址,同时指定访问长度进行匹配,为避免出现两个长度不匹配的操作数使用类型属性操作符,进行访问。

WORD PTR ; 字类型

BYTE PTR ; 字节类型

1
2
3
4
5
6
OPER1 DB 3, 4 		; 03 04
OPER2 DW 5678H, 9 ; 78 56 09 00

MOV AX, WORD PTR OPER1 ; 从OPER1取1个字 即 AX = 0403H
MOV BL, BYTE PTR OPER2 ; 从OPER2取1个字节 即 BL = 78H
MOV BYTE PTR[DI], 0 ; 将常数0送到DS:[DI]一个字节单元

3)THIS操作符和LABEL伪操作

一个变量可以定义成不同的访问类型(比如word byte)方便访问,为此引入了THIS和LABEL。

1
2
3
[name=]THIS type ; buf = THIS WORD
name LABEL type ; VALUE LABEL BYTE
两者只是指定一个type 长度的访问方式,地址和下一个存储单元地址相同。
1
2
3
4
BUF = THIS WORD
DAT DB 8,9 ; (BUF,DAT)08 09 // 只是BUF访问的是用WORD
OPR_B LABEL BYTE
OPR_W DW 4 DUP(2) ; (OPR_B,OPR_W)02 00 02 00 02 00 02 00 // OPR_B访问这组数据的时候是用byte访问的

4)表达式赋值伪指令“EQU”和“=”

可以用赋值伪操作给表达式赋予一个常量或名字

  • 格式:①表达式名 EQU 表达式②表达式名 = 表达式

  • ```
    VALUE EQU 4
    DATA EQU VALUE + 5
    ADDR EQU [BP+VALUE]

    1
    2
    3
    4
    5
    6
    7
    8
    9

    - EQU和=区别,前者不能重复定义变量名,**后者可以重复定义**

    - ```
    VALUE = 54
    VALUE = VALUE + 89
    但是不能
    VALUE EQU 54
    VALUE EQU VALUE + 54

5)汇编地址计数器$与定位伪指令

  1. 地址计数器$

    $表示当前正在汇编的指令的偏移地址

    1
    2
    3
    4
    5
    ORG 0H
    ARRAY DW 3,$+7,7 ;$当前为2
    COU = $ ;$当前为6
    NEW DW COU
    ;内存模型为:03 00 09 00 07 00 06 00 (COU = 6,符号变量不占存储,NEW占了存储)
  2. ORG 伪操作

    ORG用来设置当前地址计数器$的值(理解为定位了一个开始地址)

    1
    2
    3
    4
    5
    6
    7
    ORG 0H	;	代表$ = 0 ,同时当前开始存储的地址为0H
    DB 3 ;
    ORG 4
    BUFF DB 6
    ORG $ + 6
    VAL DB 9
    ;内存模型为:03 -- -- -- 06 -- -- -- -- -- -- 09
  3. EVEN伪操作

    使下一个变量或指令开始于偶数地址。(方便16位)

  4. ALIGN伪操作

    使下一个变量的地址从4的倍数开始。(方便多字)

    1
    ALSI 8 ; 8字节对齐
  5. 基数控制

    1. 二进制:0101 0101B
    2. 十进制:默认数字均为十进制,23D
    3. 十六进制:0ABCD 9876H,同时要求第一个字符必须是0~9,若为A~F则补0。 如0FFFFH

6)过程定义伪指令

  1. 子程序又称过程,可以把一个程序写成一个过程或多个过程。

    1
    2
    3
    procedure_name	PROC	Attribute

    procedure_name ENDP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    程序名	PROC	类型属性(NEARFAR); NEAR 和 FAR 好像没要求很多 随便用吧
    程序名 ENDP
    ;;
    DATA SEGMENT
    STRING DB 'HELLO,WORLD$'
    DATA ENDS

    CODE SEGMENT
    ASSUME CS:CODE,DS:DATA
    MAIN PROC FAR
    MOV AX,DATA
    MOV DS,AX
    LEA DX,STRING
    MOV AH,9
    INT 21H
    MOV AH,4CH
    INT 21H
    MAIN ENDP
    CODE ENDS
    END MAIN ; 设置程序起点MAIN

2.语句格式

1
2
3
指令和有关数据定义的伪指令
[name] operation operand [; comment]
[名字] 操作 操作数 [;注释]

下面各项只能符号变量或常数直接计算,不能寄存器直接运算需要用对应的指令。

  1. 名字项

    • 字母:A~Z
    • 数字:0~9
    • 专用字符:? . @ - $
  2. 算术操作符:+ - * / MOD

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ORG	0
    VAL = 4
    DA1 DW 6,2,9,3
    DA2 DW 15,17,24
    COU = $ - DA2


    MOV AX , DA1*4 ; 地址乘除没有意义
    MOV AX , DA1*DA2 ; 地址乘除没有意义
    MOV AX , DA1+DA2 ; 地址加减没有意义
    MOV AX , BX+VAL ; BX+VAL需用指令实现
    ----------------------------------------------
    MOV AX , [BX+VAL] ; MOV AX , [BX + 4]
    MOV AX , DA1+VAL ; MOV AX , [4]
    MOV AX , [DA1+VAL] ; MOV AX , [4]
    MOV AX , VAL*4/2 ; MOV AX , 8
    MOV AX , [VAL*A/2] ; MOV AX , 8
    MOV CX , (DA2-DA1)/2 ; MOV CX , 4 取到DA1区数据个数
    MOV BX , COU ; MOV BX , 6 取到DA2区的字节数


  3. 逻辑与逻辑位移操作符

    逻辑操作符 AND , OR , XOR , NOT

    位移操作符SHL , SHR

    都是按位操作符

    格式:

    • expression 操作符 number

    逻辑操作符的使用

    1
    2
    3
    4
    5
    6
    7
    8
    ARY	DW	8
    VAL = 4

    MOV AX , BX AND 0FFH ; BX AND VAL须要指令实现
    MOV AX , ARY AND 0FFH ; ARY AND VAL须要指令实现
    -----------------------------------------------------------
    MOV AX , VAL AND 0F0H ; MOV AX , 0
    AND AX , VAL OR 0FOH ; MOV AX , 0F4H

    移位操作符的使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ARY DW 8
    VAL = 4

    MOV AX , BX SHL 2 ; BX左移需用指令实现
    MOV AX , ARY SHL 2 ;ARY左移需用指令实现
    -----------------------------------
    MOV AX , VAL SHL 2 ;MOV AX , 10H
    MOV AX , 8 SHL 2 ;MOV AX , 20H
    MOV AX , VAL SHL 15 ;MOV AX , 00H
  4. 关系操作符

    用于对两个操作数的大小关系作出判断。

    为真则FFFFH,为假则0H

    • EQ相等
    • NE不等
    • LT小于
    • GT大于
    • LE小于等于
    • GE大于等于
    1
    2
    3
    4
    5
    VAL = 4
    MOV AX , BX GT 2 ; BX是否大于2须要用指令实现
    -----------------------------------------------------
    MOV AX, VAL GE 2MOV AX , FFFFH
    MOV AX, 8 LE VAL ; MOV AX , 0H
  5. 数值回送操作符

    1. TYPE:

      格式:

      • TYPE expression(表达式)
        • 如果该表达式是变量,则汇编程序将回送该变量的以字节数表述的类型
          • DB为1,DW为2,DD为4,DF为6,DQ为8,DT为10。
          • DB 定义字节,DW定义字,DD定义双字,DF定义6个字节的字,DQ定义4个字,DT定义10个字节
        • 如果表达式是标号,则汇编程序将回送代表标号类型的数值:
          • NEAR为-1,FAR为-2。如果表达式为常数则回送0。
    2. LENGTH:

      格式:

      • LENGTH 变量
        • 变量用DUP复制的,则回送总变量数
        • 不是DUP复制的为1,但嵌套的DUP不计
        • 对于使用嵌套的DUP复制的数据不能据此得到正确的总变量数。
    3. SIZE:
      格式:

    • SIZE 变量

      • 变量用DUP复制的,则回送总字节数
      • 其他为单个变量的字节数但嵌套的DUP不计。所以,对于使用嵌套的DUP复制的数据不能据此得到正确的总字节数。
    1. OFFSET:OFFSET 变量或标号

      • 回送变量或标量的偏移地址
    2. SEG:SEG 变量或标号

      • 回送变量或标号的段地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
数据定义
ORG 0
VAL = 4
ARR DW 4 DUP(3)
BUF DW 4 DUP(4 DUP(3))
DAT DW 15,17,24
STR DB 'ABCDEF'

MOV AX ,TYPE ARR ; MOV AX,2(DW 2)
MOV AX ,LENGTH ARR ; MOV AX,4
MOV AX ,LENGTH BUF ; MOV AX,4
MOV AX ,LENGTH DAT ; MOV AX,1
MOV AX ,SIZE ARR ; MOV AX,8
MOV AX ,SIZE BUF ; MOV AX,8
MOV AX ,SIZE DAT ; MOV AX,2(单个变量的字节数)
MOV AL ,SIZE STR ; MOV AL,1
------------------------------------------------------------------------
MOV AX ,OFFSET ARR ; 不完整机器指令
MOV BX ,SEG ARR ; 不完整机器指令

3.习题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
画图说明下列数据定义语句所示内存空间的数据,并回答寄存器的值
ORG 0
ARRAY LABEL BYTE
DA1 DW 2,9,14,3,315H,-6
DA2 DB 7,'ABCDEFG'
LEN = $ - DA2
ORG 100H
DA3 DW DA4
DA4 DB 4 DUP(2 DUP(1,2,3),4)
.........

MOV AL , ARRAY + 2 (AL) =
ADD AL , DA2 + 1 (AL) =
MOV AX , DA2 - DA1 (AX) =
MOV BL , LEN (BL) =
MOV AX , DA3 (AX) =
MOV BX , TYPE DA4 (BX) =
MOV BX , OFFSET DA4 (BX) =
MOV CX , SIZE DA4 (CX) =
MOV DX, LENGTH (DX) = 0004H
MOV BX,WORD PTR DA4 (BX) =

定义数据段满足如下要求
(1)array为字符串变量:’inspire a generation!’
(2)data1为十六进制数:0FEDCBAH
(3)data2为二进制数:10101010B
(4)data3为100个为0的字节变量:
(5)分配500个字的空间待用

1
2
3
4
5
6
7
DATA	SEGMENT
array db 'inspire a generation!'
data1 df 0FEDCBAH
data2 db 10101010B
data3 db 100 DUP(0)
dw 500 DUP(?)
DATA ENDS

第七章 分支与循环程序设计

1.分支程序设计

1)分支程序结构

  • IF-THEN-ELSE结构

2)单分支程序

  • IF-THEN

3)复合分支程序

  • 处理分段函数

4)多分支程序

  • 通过JMP brach[BX]指令间接寻址方式转向对应分支

2.循环程序设计

1)循环程序结构

  • DO - WHILE结构

    • 把循环控制条件放在循环的入口,先判断控制条件是否成立,再决定是否进入循环
  • DO - UNTIL结构(至少执行一次)

    • 先执行循环体,然后判断控制条件是否成立,再决定是否进入循环

第八章 子程序设计

1.子程序结构

定义

  • 把一段完成相对独立功能的程序设计成子程序,供主程序调用

操作:

  • 主程序通过指令CALL启动子程序执行
  • 指令执行时,先把它下一条指令的地址压入堆栈保存
  • 再把子程序的入口地址置入IP(CS)寄存器,以便实现转移
  • 子程序执行完毕后,用放回指令(RET)回到主程序,放回指令把堆栈里保存的返回地址送回IP(CS)寄存器,实现程序的返回
  • 子程序执行之后,返回到主程序接着执行

CALL指令

格式:

  • CALL DST

注意:

  • 与JMP指令不同,先向堆栈保存放回地址,再实现程序转移
  • 对于段内调用,只向堆栈保存IP寄存器的值
  • 对于段间调用,先向堆栈保存CS寄存器的值,再保存IP寄存器的值

RET指令

格式

  • RET
  • RET EXP
    • EXP为表达式,为一个常数。除了完成RET指令的操作外,还让SO再加上这个常数,修改SP寄存器的值

过程定义与过程结构

1
2
3
4
5
procedure_name	PROC	Attribute
.....
procedure_name ENDP

procedure_name为标识符,也是子程序入口的符号地址。Attribute为属性,可以是NEAR或者FAR

确定属性

  • 如果调用程序和该过程在同一个代码段,则用NEAR属性
  • 如果调用程序和该过程不在同一个代码段,则用FAR属性

保护和恢复现场寄存器

定义:

  • 再进入子程序后,先保存寄存器的值,在子程序退出前恢复这些寄存器的值
1
2
3
4
5
6
7
8
subr	proc	far
push ax
push bx
....
pop bx
pop ax
ret
subr endp

2。子程序的参数传递

定义:

  • 主程序调用子程序时,要传递参数给子程序,这个参数称为入口参数
  • 子程序执行完毕后,返回参数给主程序,这个参数叫出口参数

类型

  • 值传递
    • 把参数的值放在约定的寄存器或内存单元
      • 寄存器有限,不能传递很多参数
  • 地址传递
    • 把参数的地址传递给子程序
      • 参数较多时使用

汇编语言
https://ahaostillcoding.github.io/2023/11/22/汇编语言/
作者
a_hao
发布于
2023年11月22日
许可协议