微机系统原理及应用
Sponsored Links
This presentation is the property of its rightful owner.
1 / 215

第一章 概述 第一节 引言 PowerPoint PPT Presentation


  • 127 Views
  • Uploaded on
  • Presentation posted in: General

微机系统原理及应用. 第一章 概述 第一节 引言. 从 8088 、 8086 到 80386 以上直至 奔腾 ,只有 16 位与 32 位的区分,没有本质区别。芯片的指令 80% 以上是完全相同的,芯片的实地址工作方式几乎完全一致,所以 8088 、 8086 是 Intel x 86 系列的基础,要学习 x86 系列的最好办法就是从 8088 、 8086 入手。 PC 机的存储器( M )容量很大,但基本存储单元的工作原理不变;存储器与 CPU 的接口原理、方法没有变。 本书从 8088 、 8086 入手学习 PC. 第一节 引言. 一、计算机中的数制

Download Presentation

第一章 概述 第一节 引言

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


微机系统原理及应用

第一章 概述

第一节 引言


  • 从8088、8086到80386以上直至奔腾,只有16位与32位的区分,没有本质区别。芯片的指令80%以上是完全相同的,芯片的实地址工作方式几乎完全一致,所以8088、8086是Intel x 86系列的基础,要学习x86系列的最好办法就是从8088、8086入手。

  • PC机的存储器(M)容量很大,但基本存储单元的工作原理不变;存储器与CPU的接口原理、方法没有变。

  • 本书从8088、8086入手学习 PC

第一节 引言


  • 一、计算机中的数制

  • (一)二进制数的基本特点

  • 1.具有两个不同的数字符号,即0和1。

  • 2.逢二进位。

  • 任意一个二进制数可以按“权”展开


  • 1. 0至9 和 A至F。

  • 2. 逢16进位。

  • ① 16进制数转化为2进制数。

    ② 2进制数转换为16进制数。

(二)16进制数


  • 一)二进制编码的十进制数(BCD) 计算机的输入与输出是用十进制表示

  • 二)字母与字符的编码ASCⅡ:实用标准信息交换码,用7位二 进制编码,可表示128个字符。 用一个字节来表示一个ASCⅡ字符0至9的ASCⅡ码为 30H至39H大写字母A至Z的ASCⅡ码为 41H至5AH小写字母a至z的ASCⅡ码为 61H至7AH

  • 三) 汉字的编码 这个字符集中的任何一个图形、符号及 汉字都是两个7位字节表示的(每个字节的 最高位置为0)。

二、二进制编码字符是用若干位二进制编码的组合表示字符、数,这称为二进制编码。

P507


  • 逻辑运算:

  • 1. “与”运算(AND) 3. “非”运算(NOT)

  • 2. “或”运算(OR) 4. “异或”运算(XNOT)

  • (一)二进制加法

  • 它的运算规则如下:

  •  0+0=0 例如:

  •  0+1=1+0=1

  •  1+1=0 进位1

  •  1+1+1=1 进位1

  • (二)二进制减法

  • 它的运算规则如下:

三、二进制的运算计算机可进行两种基本的算术运算:加法和减法。利用这两种方法就可以进行乘法、除法以及其它数值运算。


  • (三)二进制乘法

  • 它的运算规则如下:

  •  0*0=0 例如:

  •  0*1=0

  •  1*0=0

  •  1*1=1

  • 由于此乘法的重复性差,不便

  • 于在机器中实现,现在下面

  • 用另外两种方式将运算实现。

 0-0=0 借位  1-1=0 例如:  1-0=1  0-1=1 借位


1. 被乘数左移法

乘数 被乘数 部分积

1101 1111

乘数最低位 11110

为1,把被乘数

加部分积, 再

把被乘数左移

乘数为0,不加, 111100

被乘数左移

同上 1111000

同上

n*n2n位

2n位加法器


  • 2. 部分积右移法

  • 乘数 被乘数 部分积

  • 1101 1111

  • 乘数为1,加被乘

  • 数部分积右移

  • 0,不加部分积

  • 右移

  • 1,加被乘数部分

  • 积右移

  • 1,加乘数右移

  • 2个n*n乘积2n位

  • 此种方法只需要n位加法器。


  • (四) 二进制的除法

  • 例如:

  • 四、带符号数的表示法

  • (一)机器数与真值

  • 数有正、有负,那么负数的符号是怎么表示的呢?

  • 通常一个数的最高位为符号位,若字长为8位,则


  • 为符号位。符号位用“0”表示正,用“1”表示负。

  • 例如:

  • 连用一个符号位在一起的一个数,称为机器数。

  • 它的数值称为机器数的真值。在机器数中符号有三种

  • 表示法:原码,反码和补码。

  • (二)原码

  • 正数的符号位用“0”表示,负数的符号位用“1”表示的

  • 表示法称为原码。

  • 例如: 

  • 符号值 数值

  • 

  • (三)反码

  • 正数的反码与其原码相同,负数的反码是它的正数按位


  • 取反(连同符号位)而形成的。

  • 例如:

  • 注: 符号位 取反的部分

  • 反码的特点:

  • 1. “0”有两种表示法

  • 2. 8位二进制反码所表示的数值范围为+127-127。

  • 即 ,

  • 3. 当一个符号数由反码表示时,最高位为符号数。

  • 当符号数为“0”时,后面的七位为数值部分;

  • 当符号数为“1”时,后面的七位一定要把它们按位取反,以

  • 表示它的二进制值。


  • (四)补码 :

  • 正数的补码表示与原码相同;

  • 负数的补码表示为它的反码,且在最后位(即最低位)加1所形成。 例如:

  • 8位带符号位的补码特点:1. ;

  • 2. 8位二进制补码所表示值为+127  -128;

  • 3. 一个用补码表示的二进制数

  • 当符号位为“0”时,其余7位即为此数的真值; 当符号位为“1”时,其真值为其余7位按位取反,且在最 低位处加1后最终所得的结果。 例如:


  • 采用补码表示的目的在于可以把减法转换成加法。

  • 补码的加法规则: ;补码的减法规则: 。例如:下面举一个钟表的例子:将钟从10点拨至6点有正拨、倒拨两种方式。既可倒拨4个小时,亦可顺拨8个小时。

  • 10-4(倒拨)=10+8 (顺拨) 则12称为模。 


  • (10-4)与(10+8)对模12是同余的,-4与+8对模12互补。将两者分别用二进制加、减法计算释例:

  • 自然丢弃 一般说来,若Z=nK+Y(n为整数),则称Z与Y对模K互补,记为ZY。


第三节 计算机基础


  • 第三节 计算机基础一、计算机的基本结构

  • 二、名词术语1. 位(Bit)

  • 位是计算机所能表示的最基本最小的数据单元,位就是一个 二进制位,有0、1两种状态。

  • 2. 字(Word)和字长

  • 字是计算机内部进行的数据处理的基本单位,每个字的位数 为字长。

  • 3. 字节(Byte)

  • 1Byte=8Bit三、指令程序和指令系统 指令:计算机执行的各种操作的命令的形式写下来的方式。 一条指令对应着一种操作。它由两部分组成:操作码字段和 操作数字段。 操作码表示计算机所要执行的操作;操作数表示参加 操作的数的本身或操作数所在的地址。


  • 指令的格式为 一地址 二地址

  • 8088指令的格式大多数为双操作指令。因为计算机只识别二进制数,所以计算机的指令系统中的所有指令都必须以二进制编码的形式来表示,这就是指令的机器码。例如 数据传送指令mov AL,7它的二进制机器码为 1011 0000 (mov AL,n) 0000 0111 ( n=7 )用助记符来表示操作码,用符号或符号地址来表示操作数地址的方式 称为汇编语言,它与机器指令是一一对应的。(例如 Mov,Add,Jmp等指令)当机器开始执行程序,给PC程序计数器赋以程序第一条指令所在的地址,然后每取出一个指令,PC中的内容自动加1,并指向下一条指令的地址,以保证指令顺序执行。值得注意的是只有在执行Jmp,Call,Interrupt时,PC才转到所需要的地方。

操作码

操作数...

操作数...


  • 四、模型机(一) CPU结构 (P18 如图1-9 1-10) (二) 存储器

  • 不同二进制数 地址 内容

  • 00H 01H DB FFHCPU控制 信号注意:每一个存储单元的地址和这个地址中存放的内容是 完全不同等概念,千万不能混淆。

  • 确定单元后就可以对这个单元的内容进行读或写的操作。 下面举例说明:1. 读操作

00H单元

01H单元

.

.

FFH单元

控制器


  • 将04H单元格中的内容读出送至DR(数据寄存器)。 内容AR 00H 04H 04H FFH DB 读

00H单元

84H

1000 0100

FFH单元

控制器


  • 2. 写操作AR 内容 00H DR 10H FFH DB 写 (三) 执行过程 简单说来就是取指令加执行指令。当机器开始执行指令时,把第一条指令所在地址赋给PC,然后就进入取指阶段,在取 指阶段从内存中读出的内容必为指令,由DR把它送至IR,然 后由指令译码器译码。开始执行将第一条指令的地址送PC 取指读内存(由DR) IR ID 译码PLA

00H

10H

26H

0010 0110

FFH

控制器


  • 取指的基本格式为在一条指令执行完以后就可以立即执行下一条指令,减少了CPU为等待的时间,提高了运行速度。8088CPU功能上分为BIU和EU,即分别是总线接口和执行单元。它们可以重叠。举例:把两个十进制数7和10相加。Mov AL, 7 Add AL,10 HLT第一条指令 1001 0000(Mov AL, 7) 0000 0111 ( n=7 )

取指

执行

取指

执行

…...

取指

取指

取指

取指

…...

等待

执行

执行

执行

…...


  • 第二条指令 0000 0100 (ADD AL, n) 0000 1010 ( n=10 )第三条指令 1111 0100 ( HLT ) 三条指令5个字节。 将三条指令放入存储器,若是从00H开始的存储单元。 二进制 地址(十进制数) 内容0000 0000 00 mov AL,7 0000 0001 01 n=7 0000 0010 02 Add AL,7 0000 0011 03 n=10 0000 0100 04 HLT取第一条指令 取立即数 取第二条指令 取第二条指令第二字节及执行指令的过程五、软件

1011 0000

0000 0111

0000 0100

0000 1010

1111 0100


  • 各种语言和它们汇编、编译、解释程序。  机器的监控管理程序(Moniter),调试程序 系统软件 (Delug),故障检查,诊断程序。 程序库。 操作系统。 软件 应用软件: 编制解决用户所碰到的各种实际问题的程序。 数据库及数据管理系统

由机器提供,为了使用和管理计算机


第四节 Intel 8088的结构


  • Intel 8088的结构CPU: 准16位微处理器

  • DB : 8条 AB : 20条 采用40条引线封装 电源+5V 1M直接寻址

  • 一、8088的寄存器结构 寄存器:由多个触发器可以组成一个多位寄存器。存储器:看作是一个寄存器堆,每个存储单元实际相当于一 个缓冲寄存器。二、8088存储器8088有20条地址总线, 220=1M,( 210 =1K),地址从00000FFFFF。 其寄存器为16位,8088对地址的运算只能是16位,寻址范围是0000 FFFFH 。1M存储器以64K为范围分为若干段。00000,00001,…. 0000E,0000F;64K个行 00010,00011,…. 0001E,0001F;

  • 00020,00021,…. 0002E,0002F;


  • 00000,00001,…. 0000E,0000F;00010,00011,…. 0001E,0001F;

  • 00020,00021,…. 0002E,0002F;

  • 64K个行 

  • FFFF0, FFFF1, …. FFFFE, FFFFF

  • 16个列

  • 00000H 由于它为小段的首地址,其低4位一定为0

  • 00010H 段地址只取段起始地址高16位。64K个 这样,每一个存储单元都有唯一的20位地

  • 段首地址 42230H 址,此地址称为该存储单元的物理地址。

  • 42240H 0000 (左移4位)

  • +

  • FFFE0H

  • FFFF0H

16位段地址

16位偏移地址

20位物理地址

计算方法


  • 16位段地址存放在段寄存器中,偏移量存放在IP、SP、DI、SI、BP(基数)中。当取指令时CS的地址+IP的16位偏移量=要取的指令的物理地址 当堆栈操作时SS的地址+SP的16位偏移量=堆栈操作的20位物理地址 当涉及到操作数时 在不改变段寄存器DS或ES地址+16位偏移量 的情况下,寻址最大=操作数的20位物理地址 范围是64K。64K 代码段64K 堆栈段64K 数据段64K 附加数据段

CS

SS

DS

ES


  • 第一节 8088的寻址方式

第二章 8088的指令系统


  • 一、指令的格式

  • 寻找操作数的方式称为寻址方式。

  • 1. 操作数包含在指令中,即指令的操作数场就包含在操作数本 身中。此寻址方式称为立即寻址,这种操作数就称为立即数。2. 操作数包含在CPU的某一内部寄存器中,这种寻址方式称为 寄存器寻址。3. 操作数在内存的数据区中,此时指令中的操作数场包含着此 操作数的地址。 存储单元所在基地址(段寄存器)

  • 8088内存地址

  • 段内偏移量EA

  • 指令的操作数场中规定的地址就是这个段内偏移量,又称为 有效地址EA。

  • EA的构成有以下5种:直接地址:包含在指令中的16位地址偏移量构成EA

  • ————直接寻址方式

操作码

操作数

操作数

…...


  • 间接地址:EA由CPU内某一个寄存器的16位内容构成————间接寻址方式 基址方式:基址寄存器BX或BP加上指令中的包含8位或16位位移量构成EA ————基址寻址方式 变址方式:由变址寄存器DI或SI和包含指令中的8位或16位

  • 位移量构成EA

  • ————变址寻址方式

  • 基址加变址方式:由一个基址寄存器BX或BP加变址寄存器SI或DI再加包含指令中的一个8位或16位 位移量构成EA

  • ————基址加变址寻址方式一、立即寻址

  • 此方式所提供的操作数 例如 直接放在指令中,紧跟在 mov AX,im操作码一起放在码段区 域中。

imL

imH

AH

AL


  • 立即寻址主要用来给寄存器赋初值。

  • 二、直接寻址

  • 操作数的地址的16位偏移量直接包含在指令中,它与操作码 一起被放在码字段区域中,但操作数一般在数据段。它的地 址为数据段寄存器DS加上它16位地址偏移量。 例如: mov AX,[2000H]

  • 注意:在例题中我们遇到的[2000H]。当我们用AXBX或AXBX时,表示将AX中的内容送BX或将BX中的内 容送AX。而用AX[BX]或AX[n],表示[ ]中的是操

操作码

DS

00H

30

00

0

20H

30000

AX

AH

AL

32000

50

20


  • 作数地址,把此地址单元的内容(操作数)送至AX中。

  • 物理地址=16d  DS+EA

  • 三、寄存器寻址 操作数包含在CPU内部寄存器中,如AX、BX、CX、DX。

  • 例如 已知 AX ,BX ,求执行程序后的AX。

  • mov AX, BX

  • 四、寄存器间接寻址 其操作数是在存储器中,操作数的地址16位偏移量包含在SI、DI、BX、BP之一中。(一)以SI、DI、BX间接寻址 其操作数在数据段区域中 物理地址=16d(DS)+BX或SI或DI (二)以寄存器BP间接寻址

最终AX

30

64

12

34

12

34


  • 其操作数在堆栈段区域中

  • 物理地址=16dSS+BP

  • 五、变址寻址 变址寻址是以指定的寄存器内容加上指令给定的8位或16位 位移量和段地址作为操作数的地址。 物理地址=16d(DS) + (BX) + 8位或16位位移量

  • 或(SI)

  • 或(DI)

  • 或= 16d(SS) + (BP) + 8位或16位位移量

  • 六、基址加变址的寻址方式8088常把BX、BP看作基址寄存器,把SI、DI看作变址寄存器。 寻址方式:一个基址寄存器的内容+变址寄存器的内容+指令中8位或16位位移量+段地址

  • 物理地址=16d(DS) +(BX) + (SI) + 8或16位位移量

  • 或(DI)或=16d(SS) + (BP)+ (SI) + 8或16位位移量 或(DI)


  • 在正常情况下,由基地址决定哪一个段寄存器作为地址指针。 用BXDS,BPSS。


第二节 8088中的标志寄存器


  • 1. 辅助进位标志A在字节操作时,则由低半字节(一个字节的低4位)向高半字节有 进位或借位; 在字操作时, 低位字节向高位字节有进位或借位, 则A=1, 否则A=0。 此标志用十进制算术运算指令中。2. 进位标志C当结果的最高位产生一个进位或借位,则C=1, 否则C=0。主要 用于多字节数的加法、减法,移位和循环指令也能够把存储器 或存储器中的最高位(左移)或最低(右移)放入C中。3. 溢出标志O在算术运算中, 带符号数的运算结果, 如果超出以下范围:

  • 字节 字 则O=1, 否则O=0。溢出和进位是两个不同的概念。溢出判断:

15


  • 同号相加, 若结果的符号位相反, 则溢出。 异号相减, 若结果的符号位与被减数相反, 则溢出。4. 符号标志S S的值与运算结果的最高位相同, 若最高位为1,则S=1,否则S=0。 由于8088中, 符号数是用补码表示的, S=0为正, S=1为负。5.奇偶标志P若操作数结果中“1”的个数是偶数, 则P=1, 否则P=0。6. 零标志Z若运算的结果为0, 则Z=1, 否则Z=0。7. 方向标志D若用指令置D=1, 则引起串操作指令为自动减量指令;

  • 若用指令置D=0, 则引起串操作指令为自动增量指令。

  • 8. 中断允许标志I若指令中置I=1, 则允许CPU去接收外部的可屏蔽的中断请求; 若指令中置I=0, 则屏蔽上述的中断请求。I对CPU内部产生的中断不起作用。9. 追踪标志T


  • 补充内容:操作码和寻址方式的机器语言表示方法操作码的机器语言表示

  • W位 是指示本指令是对字(W=1)还是对字节(W=0)操作;d值 在双操作数指令中才有效。8088指令规定双操作数指  令的两个操作数必须有一个操作数放在寄存器中;d位 指定寄存器用于目的操作数(d=1)还是源操作数(d=0)(8  16,高位字节按低位字节的最高有效位作符号扩展)。  当立即方式寻址时,S位表示符号扩展  当指令字节操作时,SW=00;当指令有16位立即数且作字操作时,SW=01;当指令有8位,但需要经符号扩展成16位,立即数作字操作时,  则SW=11。 寻址方式的机器语言表示8088用一个字节表示操作数的确寻址方式  它通常是机器指令的第二个字节

op

d

W


  • 表示为

  • 在双操作数指令的情况下规定必须有一个操作数在寄存中,该 寄存器由reg字段指定。mod与r/m是另一种操作数寻址方式。mod=11, 为寄存器方式, 由r/m的内容确定选用哪个寄存器;mod=00, 为元位移量字节的存储器寻址方式——直接寻址;mod=01, 为带一个位移量字节的存储器寻址方式; 指令中应有

  • mod=10, 为带两个位移量字节的存储器寻址方式;

  • 如果出现段跨越,则必须加001 ,再加上110。

mod

01

10

reg

reg

reg

r/m

r/m

r/m

D16低位

D16高位

操作数

存储器

间接

寻址

D8

SEG


  • 上面的寻址方式是指无段跨越前缀的情况下所用的隐含的段 寄存器,如果指令中指定段跨越前缀,则在机器语言中使用放在 指令之前的一个字节来表示, 如下:

001

seg

110

segment

SEG

00

01

10

11

ES

CS

SS

DS


  • 置T标志, 使处理进入单步方式,以便于调试。在这个方式, CPU在每条指令执行以后产生一个内部的中断, 允许程序在每条执 行完以后进行检查。


第三节 8088的指令系统


  • 8088的指令系统可分成6个功能:

  • • 数据传送

  • •算术运算

  • •逻辑运算

  • •串操作

  • •控制传送

  • •处理器控制

  • 指令符号:8位寄存器 AH,AL; BH,BL; CH,CL; DH,DL16通用寄存器 AX ; BX ; CX ; DX SP ; BP ; DI ; SI 堆栈指针 SP指令指针 IP (指向下一次要取出的指令)或PC(指向下一条即将要执行的指令)标志位 F目的和源变址寄存器 DI 、 SI


  • 段寄存器 CS 、DS 、SS、ES通用寄存器 rAL或AX a源和目的操作数 src dst (存储单元) [ BX+SI+n ] [ BX+DI+n ] [ BP+SI+n ] [ BP+DI+n ] [ SI+n ] [ DI+n ] [ BP+n ] [ BX+n ] [ n ]---------- 直接r ---------- 寄存器源操作数地址 ADR ( src)存储单元的内容 [ ]OPRD 操作数


  • 附加存储器段的内容 ES[ ]段寄存器 seg立即数 im 8位 n 16位 nn 32位 nnnn一、数据传送指令 分为4种: • 通用传送指令• 累加器专用传送指令

  • • 地址—目的传送指令 • 标志传送指令 此类指令, 除了标志寄存器传送SAHF和恢复标志寄存器POPF指令以外, 对标志位无影响。(一)通用传送指令 此指令是唯一允许以段寄存器作为操作数的指令。(XCHG除外)

  • 1. Mov OPRD1, OPRD2

目的


  • 它把一个字节B或字W操作数从源地址传送至目的地址。

  • 它能实现以下4种数据传送: CPU内部寄存器之间传送(除CS和IP以外)如

  •  立即数传送CPU内部通用寄存器组给寄存器赋初值。 如 mov CL, 4 mov SI, 057BH

mov [nn], a B/W [nn]=a

mov a, [nn] B/W a=[nn]mov seg, src W seg=src

mov dst, seg W dst=seg

mov r, src B/W r=srcmov dst, r B/W dst=rmov r, im B/W r=immov dst, im B/W dst=im

mov AL, BL

mov CX,BX

mov DS,BX

mov DX,ESmov SI,BP


  • CPU内部寄存器(除CS和IP以外)与存储器之间的传送

  • () 通用寄存器与存储器之间 如 mov AX, [SI]

  • mov [DI], CX 寄存器间接

  • mov SI, BLOCK[BP] 变址

  • () 段寄存器(除CS外)与存储器之间 如 mov DS, DAT[SI+BX] seg M

  • mov DEST[BP+DI], ES

  • 注意:mov指令不能实现存储单元之间的数据传送, 也不允许 两个段寄存器之间直接传送。 若需要把地址(段内地址位移量)为ARE1的存储单元的 内容, 传送至同一段内的地址为ARE2的存储单元可以 用CPU内部寄存器为桥梁来完成。 如 mov AL, ARE1 mov ARE2, AL

  • 如 mov BX, offset TABLE

通用rM

seg M


  • 把TABLE的偏移地址而不是内容送到BX寄存器。

  • 若传送100个数据mov SI, OFFSET AREA1 mov DI, OFFSET AREA2 mov CX, 100 AGAIN: mov AL, [SI] mov [DI], AL INC SI INC DI DEC CX JNZ AGAIN

  • 其中OFFSET AREA1是指地址单元AREA1在段内地址偏移量。 又如 mov AX, Y[BP][SI]地址16d(SS)+(BP)+(SI)+Y的存储单元的内容送给AX。 其中OFFSET为属性操作符, 表示应把其后跟着的符号 地址的值(不是内容)作为操作数。能实现用立即数给存储单元赋初值(Mim)如 mov mask [BX] [SI], 2CH


  • 2. 堆栈操作指令 在主程序中往往要调用子程序或要处理中断就要暂停主程序 的执行, 转去执行子程序(中断服务程序), 则机器必须把主程序 中调用子程序指令的下一条指令, 若第X1条指令为调用子程序 ,则它的下一条指令为X2的地址, 即PC或IP保留下来才能保 证当子程序执行完成以后返回主程序继续执行。另外, 还必须 保留调用子程序的主程序的中间结果标志位的状态。

  • 口诀:先进后出, 后进先出。

  • 8088中规定堆栈设置在堆栈段(SS)内, 用堆栈指针SP始终指向堆栈的 顶部, 即始终指向最后推入堆栈的 信息所在的单元。SP的初值规定 了所用堆栈的大小, 8088中所设置 的SP的初值, 逐渐靠近SS,堆栈的 最大容量为SP的初值与SS间的距             离。入栈指令 它是把一个字的源操作数, 送至栈的顶部。  

主程序

转向子程序

X1

IP

X2

通用主程序


  • PUSH OPRD(W)  在传送数据前SP-2SP  具体指令如下:PUSHrw SP=SP-2, [SP]=r PUSHsegw SP=SP-2, [SP]=seg PUSH src w SP=SP-2, [SP]=src源操作数可以是CPU的内部寄存器, 段寄存器(除CS外)内存操 作数。出栈指令POP OPRD(W) 在传送数据后SP+2 SP 把现行SP指向的堆栈顶部的一个字,送至指定的目的操作数, 然 后再进行修改指针, SP+2 SP。

  •  具体指令如下:

  • POPrwr=[SP] SP=SP+2

  • POP segw seg=[SP] SP=SP+2 POP dstw dst=[SP] SP=SP+2注意:堆栈是“后进先出”方式工作的(一个)存储区。它必须     在于堆栈段中, SS存放段地址。进栈:先移指针, 后放入内容。出栈:先拿内容, 后移指针。


  • PUSH AX         指令分两步执行:

  • PUSH BX     第一步:SP-1 SP

  • 然后把AH(寄存器中的高位字节)送至SP所指的单元;          第二步:SP-1 SP然后把AL(寄存器中的低位字节)              送至SP所指的单元。              如 PUSH AX

SP 

AH

SP-1 

指令执行前

AL

SP-1 

指令执行后

BH

高地址

高地址

BL

低址SP

21

SS

低地址

低地址

SP

07

(AX)=2107H


  • 出栈指令举例

  • 如 POP AX

指令执行后

指令执行前

高地址

高地址

SP

21

21

07

07

SP

低地址

低地址

(AX)=2107H


  • 3. 交换指令XCHG OPRD1, OPRD2目的操作数 源操作数

  • 把一个字节或一个字的源操作数与目的操作数相交换。rAX, r r, r M段寄存器不能作一个操作数。 具体指令如下:XCHGAX,rwr=AX, AX=r XCHG r ,srcB/w r=src, src=r

  • (二)、累加器专用传送指令1. IN输入指令 把一个字节或一个字由一个输入端口(Port)传送至AL或AX。端口地址若是由指令中的n(8位)所规定 则寻址Port0Port255, 共256个输入端口。 端口地址若是由寄存器DX规定 则寻址范围64K个输入端口(8088采用间接寻址方式,I/O端口地址可扩展到64K)具体指令如下:


  • IN AL, nBAL=[n] IN AX, nWAX=[n+1][n] IN AL, DXBAL=[DX] IN AX, DXWAX=[DX+1][DX] 2. OUT输出指令 把AL中的一个字节或AX中的一个字, 传送至一个输出端口。 具体指令如下:OUT n, AL B AL [n] OUT n, AX W AX [n],[n+1] OUT DX, AL B AL [DX] OUT DX, AX WAX [DX],[DX+1] 3. XLAT查表转换 指令完成一个字节的查表转换, 寄存器AL的内容 为一个256个字节的表的下标。这个表的基地址在寄存器 BX中, 转换后的一个字节的操作数放在AL中。XLATB(AL=[BX+AL]) (0 9转换7段数码)经常把一种代码转换为另一种代码。(三)、地址——目的传送


  • 1. LEA把源操作数的地址偏移量, 传送至目的操作数。

  • LEAr,srcr=ADR(src)

  • 如movSI,OFFSETAREA1等价于LEASI,AREA1 不等价于movAX,AREA12. LDS此指令是传送一个目标指针(段地址+地址偏移量, 32位)从源操 作数(为内存操作数)传送至一对目的寄存器。16位地址偏移量1个16位的指针寄存器(SP,BP)或变址寄存器(DI, SI)目的段地址DS寄存器 指令格式:LDS r, srcDW r [EA] DS [EA+2]

内存操作数

16位的通用寄存器


  • LDS指令示意图:

  • LDS

  • 3. LES除了把目标段地址送至段寄存器ES以外, 其它与LDS指令类似。

  • LES reg, srcr [EA], ES [EA+2]

操作码

DI, BP,SP

偏移量

EA

变址

SI

2个字节

2个字节

DS


  • 举例来说: 1. LEA BX, [BX+SI+0F62H]

  • 指令执行前 (BX)=0400H, (SI)=003CH

指令执行后 (BX)=0400+003CH+0F62H=139EH

BX寄存器得到的是偏移地址而不是该存储单元内容

2. LDS SI, [0010H]指令执行前(DS)=C000H, [C0010H]=0180H, [C0012H]=2000H

指令执行后(SI)=0180H, (DS)=2000H

3. LES DI, [BX]指令执行前(DS)=B000H, (BX)=080AH [0B080AH]=05AEH, [0B080CH]=4000H

指令执行后(DI)=05AEH, (ES)=4000H


  • (四)、标志寄存器传送1. LAHF

  • 2. SAHF此指令与LAHF相反, 是把AH的指定位送至FLAG中的S、Z、A、P、C 3. PUSHF

  • 把FLAG中的(全部9个标志)推入栈堆指针所指的堆栈的顶 部。传送数据前 SP SP-2。此指令不影响标志位。4. POPF把现行堆栈指针所指的一个字,传送至FLAG。 然后SP+2 SP。PUSHF和POPF可以保存和恢复标志寄存器。在子程序调用 和中断服务中可利用这两个指令。

6

4

2

15

    

O D I T

不影响F


  • 二、算术运算指令2进制运算可以是双操作数, 10进制运算可以是单操作数。 若是符号数用补码表示。(一) 加法:共有5种。1.ADD OPRD1, OPRD2 OPRD1+OPRD2 OPRD1目的操作数 :累加器、通用寄存器、存储器操作数。 指令格式:ADD r, src B/W r+src r ADD a, im B/W a+im a ADD dst, im B/W dst+im dst ADD dst, r B/W dst+r dst

  • 如: ADD AX, 3000H ADD AX, SI ADD SI, AX ADD AL, DATA[BX] ADD BETA[SI], DX ADD BETA[SI], 100

这些指令对FLAG中C、O、P、S、Z、A有影响。


  • 2. ADC在两个操作数相加时, 把进位标志C的值加上去, 结果送至一个 操作数。 格式: ADC DST, SRC (DST) (SRC)+(DST)+C具体如下:ADC r, src r+src+cr ADC a, im a+im+c a ADC dst, im dst+im+c dst ADC dst, r dst+r+c dst ADC主要用于多字节运算, 先进行低两字节相加, 然后进行高两 字节相加,若两个四字节的数相加,分别放在FIRST和SECOND

  • 存储区中, 每个数占四个存储单元。最低字节在地址最低处。 如:

Mov AX, FIRST

Add AX, SECOND

Mov THIRD, AX

Mov AX, FIRST+2

Adc AX, SECOND+2

Mov THIRD+2, AX

也影响FLAG中C、O、P、S、Z、A


  • 3. INC格式: INC OPR(OPR) (OPR)+1完成对指定的操作数加1, 再返回此操作数。 影响标志位A、O、P、S、Z。不影响标志位C 具体如下:INC rWr+1r INC srcB/Wsrc+1src4. AAA加法的ASCII调整指令(非压缩BCD)。。 执行这条指令之前必须执行ADD或ADC指令。加法指令把两 个非压缩BCD码相加, 结果放在AL中。 执行的操作:

  • AL把AL中的和调整非压缩BCD格式

  • AH AH加调整产生的进位值(对应步骤中的)以下是具体步骤:

  • 如果AL的低4位在09之间, 且A=0, 则跳过, 执行; 如果AL的低4位在AF之间或A=1, 则AL加上6, 且A=1;


  • 清除AL的高4位(AL&0FH);

  •  AHAH+1  A的值送至C。

  • AAA影响标志位C、A。

例如ADDAL,BL AAA执行前 AX=0535H , BL=39H

可见 AL、BL的内容分别为

5和9的ASCII码

执行完第一条指令后(AL)=6EH A=0

执行完第二条指令后

ASCII调整后 (AX)=0604H 6E+06=74H

A=1, C=1

5. DAA

加法的十进制调整指令(压缩BCD)。

在执行此指令之前, 先执行ADD或ADC加法指令。必须把两个压 缩的BCD码相加, 结果放在AL中。


  • 调整方法如下:(参见P82例)若A=1, 或AL低4位是A  F, 则AL+06HAL, 且A=1;若C=1, 或AL高4位是A  F, 则AL+60HAL, 且C=1。

  • (二) 减法指令1.SUB (减法指令) SUBOPRD1, OPRD2 (OPRD1)(OPRD1)-(OPRD2)具体形式如下:SUB r, src B/Wr-src r SUB a, im B/wa-im a

0010 1000

0110 1000

+

A=1

1001 0000

0000 0110

+

1001 0110

9

6

例 ADDAL,BL

DAA

执行前 (AL) =28H, (BL)=68H

第一条指令执行后 (AL)=90 C=0, A=1

第二条指令执行后 因为A=1,所以(AL) (AL)+06得 (AL)=96

C=0, A=1


  • SUB dst, r B/W dst-r dst

  • SUB dst, im B/Wdst-im dst此指令影响标志为A、C、O、P、S、Z。2. SBB (带借位减法指令)

  • SBB OPRD1, OPRD2 (OPRD1)(OPRD1)-(OPRD2)-C具体形式如下:SBB r, src r-src-C r SBB a, ima -im-C a SBB dst, rd st-r-C dst SBB dst, imdst-im-Cdst此指令影响标志位A、C、O、P、S、Z。3. DEC (减1指令)

  • DEC OPR 把操作数作为无符号数2进制数处理(OPR)  (OPR)-1此指令影响标志位A、O、P、S、Z, 不影响C。OPR可以是r, 也可以是M。4. NEG (求补指令) NEG OPR(OPR)0FFFFH-(OPR)+1


  • 即把操作数按位求反, 末位加1, 因而亦可表示。 此指令影响A、C、O、P、S、Z。注意:只有当操作数为“0”时,求补运算结果使C=0, 其它情况C=1。

  • 5. CMP (比较指令) CMP OPR1, OPR2 (OPR1)-(OPR2) 完成两个操作数相减, 并使结果反映在标志位上, 不回送。 具体形式如下:

  • CMP r, src CMP a, im CMP dst, r CMP dst, im比较指令主要用于比较两个数之间的关系, 即两者是否相等,或 两个中哪个大, 指令通过比较结果置标志位,表示操作数的关系。 下面以CMP A, B为例:若两个操作数相等 即A=B则比较后Z=1, 否则Z=0 两个无符号数判大小


  • 若AB, 则不会产生借位, C=0若A<B, 则产生借位, C=1因此根据C标志位来判断两个无符号数的大小。两个有符号数判断大小 要结合O、S两个标志位(I)若A、B为同号(A、B>0或A、B<0)则两数相减绝对值变小不会溢出, 此时可用S判断大小。AB S=0 A<B S=1 (II)若A、B为异号数(A>0,B<0 或 A<0,B>0)则两数相减有可能溢出

  • 简化:若SO=0时 , A>B

  • 若SO=1时 , A<B

AB S=0

A<B S=1

A>B S=1

A<B S=0

无溢出

有溢出

若O=0时

S=0 则A<B

S=1 则A>B

若O=1时

S=0 则A>B

S=1 则A<B


  • 例1 SUB [SI+0014H], 0136H

  • 例2SUB DH, [BP+4]

执行后

4336-0136

求补

0100 0011 0011 0110

0100 0011 0011 0110

-0000 0001 0011 0110

+1111 1110 1100 1010

1  0100 0010 0000 0000

补码时, 借了模10000H

执行前 (DS)=3000H, (SI)=0040H(30054H)=4336H

(30054H)=4200HS=0, Z=0,C=0,O=0

执行前 (DH)=41H, (SS)=0000H (BP)=00E4H, (000E8)=5AH


  • 例3 若自BLOCK开始的内存中, 有100个带符号数, 要找出其中 的最大值, 把它存放到MAX单元。

执行后

41-5A

0100 0001

0100 0001

-0101 1010

+1010 0110

1110 0111

补码时, 借了位

(DH)=E7HS=1, C=1,O=0

求补

Mov BX OFFSET BLOCKMov AX, [BX]Inc BXInc BXMov CX, 99

AGAIN:CMP AX, [BX] JG NEXT Mov AX, [BX]


NEXT: INC BX INC BX DEC CX JNZ AGAIN Mov MAX, AX HLT


  • 6. AAS (减法的ASCII调整指令, 非压缩BCD)执行的操作:

  • (AL)把AL 中的差调整到非压缩BCD格式(AH)  (AH)—调整产生的借位值 此指令之前必须执行SUB或SBB指令。

  • 调整步骤如下:

  • 如果AL的低4位在09之间, 且A=0则跳过执行 ; 如果AL的低4位在AF之间或A=1则AL-6 AL, AH-1 AH, 将A=1;

  • 清除AL的高4位(AL AL&0FH); A的值送至C。

  • AAS影响标志位A、C, 其余标志位无定义。7. DAS (减法的十进制调整指令, 压缩BCD)执行的操作:(AL) 把AL中的差调整到压缩的BCD格式 此指令之前必须执行SUB或SBB指令。


  • 调整方法:

  • 若A=1或AL的低4位是AF则使AL-06H AL, 且A=1; 若C=1或AL的高4位是AF则使AL-60H AL, 且C=1。DAS影响A、C、S、Z、P, 对O无定义。 例如 SUB AL, AH 执行指令 (AL)=86H, (AH)=07H

执行SUB (AL)=7FH, C=0,A=1

执行DAS 因为A=1, 所以(AL)=(AL)-06H=79 C=0, A=1

(三) 乘法指令8088中有三条乘法操作指令1.MUL (无符号数乘法)格式: MUL SRC执行的操作:(AX) (AL)*(SRC)字操作数 : (DX, AX) (AX)*(SRC)相乘时的另一操作数可以是寄存器操作数或内存操作数。


  • 若结果的高半部分(AH, DX)不为0则标志C=1,O=1; 否则C=0, O=0。 本指令对A、P、S、Z无定义。2. IMUL(带符号数乘法)格式 :IMUL SRC执行的操作:与MUL相同, 但必须是带符号数, 而MUL是无符 数。 对于IMUL指令, 如果乘积的高一半(AH, DX)是低一半的符号 扩展 , 则C=0, O=0; 否则 C=1, O=1.那么所谓符号扩展是指一个数从位数较少扩展到位数较多的 数(8位16位;16位32位), 对于用补码表示的数, 正数的符 号扩展应该在前而补0, 而负数的符号扩展应该在前面补1。[+46]补=0010 1110 [+46] =0000 0000 0010 1110 [-46] =1101 0010 [-46] =1111 1111 1101 00103. AAM(乘法的ASCII调整指令)执行的操作: (AX)把AL中的积调整到非压缩BCD格式 此指令之前必须执行MUL指令把两个非压缩的BCD相乘(其高4位为0)结果放在AL中。


  • 调整方法如下:

  • AHAL/0AH (AL被0A除的商 AH)AL  AL%0AH(AL被0A除的余数AL)如6(0000 0110)7(0000 0111)——AL积(0010 1010)则乘积的十进制数值的调整:0000 0100 AH 0000 0010 AL(四)除法指令1.DIV(无符号数除法指令)格式为 DIV SRC执行的操作:(AL) (AX)/(SRC)的商 字节操作 (AH) (AX)/(SRC)的余数AX:16位 SRC:8位(AX) (DX,AX)/(SRC)的商 字操作 (DX) (DX,AX)/(SRC)的余数DX、AX:32位 SRC:16位2. IDIV(带符号数除法指令)


  • 此指令除了完成带符号数相除以外, 与DIV类似。

  • 格式为 IDIV SRC注意:对乘法、除法指令SRC不能为立即数。 除法指令对A、C、P、Z、S、O各种标志位均无定义。3. AAD(除法的ASCII调整指令)

  • 若被除数是放在AX中的二位非压缩BCD,AH中存放十位数。AL中放个位数。而且要求AH和AL高4位均为0,除数是一 位非压缩BCD,要求其高4位为0。在这两个数用DIV指令以 前,必须先用AAD指令把AX中的被除数调整成二进制数,存 放在AL中。 调整操作:(AL) AH*0AH+AL (AH) 0此指令影响S、Z、P ,对A、C、O无定义。4. CBW 格式为 CBW执行的操作:AL的内容符号扩展到AH AL<80H , AH 0


  • AL80H , AH FFH 5. CWD格式为 CWD执行的操作:AX的内容符号扩展到DX AX<8000 , DX 0否则DX FFFFH三、逻辑运算指令 逻辑操作分为:单操作数操作 两个操作数操作(一)单操作数操作1. 逻辑非指令

  • NOTsrcB/W(src 的反码src) 2. 移位指令 格式SAL 算术左移指令 SAL OPR, Count SHL 逻辑左移指令 SHL OPR, Count SAR 算术右移指令 SAR OPR, Count SHR 逻辑右移指令 SHR OPR, Count


  • OPR: 通用寄存器存储器操作数(8位或16位)Count:表示移位的次数。移位一次count=1,移位多次count=CL. CL为移位的次数。(1)SAL/SHL(用一指令的两种表示方法)在移位次数为1时, 当新的操作数最高位与C不同时,则O=1, 表明有符号数操作产生溢出,不再符合倍增关系。 对无符号数,当移位后使C=1, 则不再符合倍增关系。

OPR

OPR

C

 0

C

左移指令SAL SHL

算术右移SAR

OPR

0

C

逻辑右移SHR


  • 例1 AL=0100 0010B 66 / +66

  • 例2 mov CL , 2 SHL SI , CL已知(SI)=1450H

对有符号数 O=1 不符合倍增关系 +662=-124

左移一位

AL=1000 0100B

132 / (-124) , C=0, O=1

对无符号数 C=0 符合662=132

执行指令前 (SI)=1450H 它的二进制形式是 0001 0100 0101 0000

则执行指令后它的二进制形式是 0101 0001 0100 0000

另 执行指令前 (SI)=5200d 执行指令后(SI)=20800d

则 5200d 4d=20800d


  • (2) SAR(算术右移)指令常用于有符号数的减半运算。若右移使C=1,则减半结果 不精确。(3) SHR(逻辑右移)本指令可以作为无符号数的除2运算, 右移一位, 相当数值下降 一级。若右移后C=1,表明移位前的数是奇数, 减半结果不精确。 移位指令根据移位后的结果设置S、Z、P , 对A无定义。 3.循环指令 共有以下4个:

  • 格式ROL 循环左移指令 ROL OPR , COUNT

  • ROR 循环右移指令 ROR OPR , COUNT

  • RCL 带进位循环左移指令 RCL OPR , COUNT

  • RCR 带进位循环右移指令 RCR OPR , COUNT

  • OPRD :通用寄存器或存储器操作数(8位 / 16位) COUNT :移位次数 移位1次 COUNT=1 移位多次 COUNT=CL


  • 循环移位指令不影响除C和O以外的其它条件标志。(二)两个操作数操作1. AND 逻辑与指令AND OPRD1 , OPRD2 B/W OPRD1OPRD1OPRD2用于:两个数要保持不变的位和“1”与, 要置为“0”的位和“0”与。2. TEST 测试指令TEST OPRD1 , OPRD2 OPRD1OPRD2完成与AND指令同样的操作, 结果反映在表示位上,并不回

OPR

C

ROR

OPR

OPR

C

C

RCL

RCR

OPR

C

ROL


  • 送目的操作数。通常用于检测一些条件是否满足,但不希望改 变原操作数。例如:

  • 3. OR 或指令

  • OR OPRD1 , OPRD2 OPRD1OPRD1vOPRD2

TEST AL , 01HJNZ THERE

THERE

TEST CX , 0FFFFHJZ THERE

THERE

检测AL中的最低位是否为1,若为1则转移。

JZ 结果为零(或相等),则转移 Z=1JNZ 结果不为零(或不相等),则转移 Z=0

检测CX中的内容是否为0, 若为0则转移。


  • OPRD1可以是累加器、寄存器、内存;OPRD2可以是立即数、寄存器、内存。 “或”操作用于要求使一个操作数的若干位保持不变,而另外 若干位置为1的场合。保持不变的位和“0”或,要置为“1”的位 和“1”或。一个操作数和自身相“或”,不改变其值, 但C=0。 (参看奇偶校验例题) 4. OR 异或操作 OR OPRD1 , OPRD2 OPRD1OPRD1OPRD2当一个操作数对自身进行“异或”操作,结果为0, C=0。 常用于要置操作数初值为0的情况中。(参看例题)四、串操作指令 所有的基本的串操作指令,用SI(段地址寄存器为DS)寻址 源操作数, 用DI(对应的段寄存器为ES)为寻址目的操作数。 若D=0, 则每次操作后SI和DI增量(字节操作加1,字操作加2); 若D=1, 则每次操作后SI和DI 减量1. 串传送指令 格式 MOVS OPRD1 , OPRD2


  • MOVS DST , SRC [ DI] [SI] 指针指示地址内容 MOVSB 字节操作 [ DI] [SI] SI SI1 DI DI1当D=0时用加法 当D=1时用减法 MOVSW 字操作 [ DI] [SI] SI SI 2 DI DI 2当D=0时用加法 当D=1时用减法 之前的传送100个操作数的例子可用上述指令改写为:

mov SI , OFFSET SOURCE mov DI , OFFSET DEST mov CX , 100

AGAIN: movs DEST , SOURCE DEC CX JNZ AGAIN

又可以REP movs DEST , SOURCE (CX-1CX)当CX=0时不重复


  • REP: CX=0 , 则退出REP , 否则往下执行; CX-1CX; 执行其后的串指令; 重复、。2. COMPS 串比较指令 格式 CMPS SRC , DST [SI]-[DI] CMPSB 字节操作(SI) (SI) 1 (DI) (DI) 1 CMPSW 字操作(SI) (SI)  2 (DI) (DI) 2当D=0时用加法 当D=1时用减法 不保存结果, 只根据结果置标志位。(参看 例题)

格式 REP MOVS MOVSB MOVSW


  • 3. SCAS 搜索串指令 格式 SCAS 串扫描指令

  • SCASB 字节操作AL-[DI] (DI) (DI) 1 SCASW 字操作AX-[DI] (DI) (DI) 2 AL、AX、[DI]的内容并不改变。 而标志位A、C、O、P、S、Z反映AL/AX的值与串元素之间 的关系。(参看P102 例题) 4.LODS 从串取指令 格式LODS SRC LODSB 字节操作AL[SI] SISI1LODSW 字操作


  • AX[SI] SISI2当D=0时用加法 当D=1时用减法 5. STOS 存入串指令 格式

  • STOS DST STOSB 字节操作[DI]AL DI DI  1 STOSW 字操作[DI]AX DI DI  2当D=0时用加法 当D=1时用减法(参看 P103例题)五、控制传送指令(一)调用Call 、转移JUMPS、返回returns。1. Call格式 Call DST 1)段内直接调用 操作:


  • SPSP-2 [SP+1 , SP] IP

  • IP (IP)+D16指令的第一步:把子程序的返回地址(即Call指令的下一条指令 的地址)存入堆栈中, 以便子程序返回主程序。指令的第二步:转移到子程序的入口地址继续执行。DST给出转向地址(子程序的入口地址), D 为指 令中的位移量, 它是转向地址和返回地址之间的 差值。2)段内间接调用 操作:SPSP-2 [SP+1 , SP] IP

  • IP [ EA]由DST的寻址方式所确定的有效地址3)段间直接调用 操作:SPSP-2 [SP+1 , SP] CS

IP指向下一次要取出的指令

16


  • SPSP-2 [SP+1 , SP] IP

  • IP  偏移地址 (指令的2、3个字节)

  • CS 段地址 (指令的4、5个字节)4)段间间接调用 操作:SPSP-2 [SP+1 , SP]CS

  • SPSP-2 [SP+1 , SP] IP

  • IP[EA ] CS [EA+2]

  • 2. RET 返回指令 放在子程序的末尾, 使子程序执行完后返回调用程序继续执行,返回地址是Call时存放在堆栈中。1)段内返回 格式 RET操作:


  • IP[SP+1, SP] SP SP+2 2)段内带立即数返回 格式 RET EXP操作:IP[SP+1, SP]

  • SP SP+2 SP SP+D由EXP的值计算出D 。 此指令允许返回地址出栈后修改堆栈的指针, 以便在调用程 序在用call调用子程序以前把子程序所需要的参数入栈, 以 便子程序运行时使用这些参数。当子程序返回后, 这些参数 已不再使用了, 可以修改指针使其指向参数入栈以前的值。3)段间返回 格式 RET操作:IP[SP+1, SP]

  • SP SP+2

16

16


  • CS[SP+1, SP] SP SP+24)段间带立即数 格式 RET EXP操作:IP[SP+1, SP] SP SP+2CS[SP+1, SP] SP SP+2 SP SP+D CALL, RET不影响标志位A、C、O、P、S、Z。3. JMP 跳转指令 无条件转移指令, 不要求返回。1)段内直接短转移 格式 JMP SHORT OPR操作:IP IP+D (8位偏移量) 2)段内直接近 转移

16

8


  • 格式 JMP NEAR PTR OPR操作:

  • IP IP+D (16位偏移量) 3)段内间接转移 格式 JMP WORD PTR OPR操作: IP (EA) 属性操作符 4)段间直接转移 格式 JMP FAR PTR OPR操作:IP OPR 的段内偏移地址CSOPR 所在段的段地址 (二)条件转移指令 条件转移指令是以某些标志位或其逻辑运算为依据。 若是满足所规定条件, 则程序转移到指定目标;若不满足条件, 则程序顺序执行条件转移指令的下一条指令。 目标地址是采用相对寻址方式, 即以转移指令为基准的+127或-128字节范围内寻址。

16


  • (1)根据标志位的条件转移指令JCC=1 JNCC=0

  • JE/JZ 相等或结果为0, 即Z=1 JNE/JNZ 不相等或结果非0,即Z=0

  • JSS=1转移JNSS=0转移

  • JO O=1转移JNOO=0转移

  • JP/JPEP=1转移JNP/JPOP=0转移(2)用于无符号的条件转移指令JA/JNBE 为 高于 / 不低于或等于时转移 即ZVC=0 JNA/JBE 为 不高于 / 低于或等于时转移 即ZVC=1 (3)带符号数的条件转移JG/JNLE 为 大于/ 不小于或等于时转移 即(SO)VZ=0 JGE/JNL 为 大于或等于/不小于时转移 即SO=0 JL/JNGE 为 小于/不大于或等于时转移 即 SO=1,Z=0


  • JLE/JNG 为 小于或等于/不大于时转移 即(SO)vZ=1(三)重复控制 重复控制指令是当CX不为零时,循环至目的地址。 若CX=0时,则顺序执行重复控制指令的下一条指令。它的相 对寻址是在控制指令的+127-128字节的范围内。1.LOOP CX-1CX若CX0 则循环到目标操作数——IP+偏移量(16位); 若CX=0 则退出循环, 往下执行。 2.LOOPZ CX-1 CX若CX0 且 Z=1 则循环;否则退出循环。3.LOOPNZ CX-1 CX若CX0 且 Z  1 则循环;否则退出循环。4.JCXZ若CX=0 则转移到目标操作数——IP+偏移量(扩展到16位)(四)中断


  • 当系统运行或程序运行期间在遇到特殊情况, 需要计算机自 动执行专门的程序来进行处理, 这种情况称为中断。 它分为2种:

  • 内部中断指令 , 除0产生的中断 外部中断指令 , I/O与CPU中断向量:中断程序的入口地址 03FF单元,1024个字节为中断向量区, 存放256种类型 。每个 中断向量占有4个字节单元,分别是CS(2个) IP(2个) 1.INT 中断指令

  • INT TYPE——中断类型号(可以是常数或常数表达式P335)执行操作:SPSP-2 [SP+1 , SP]FSPSP-2 [SP+1 , SP] (CS)SPSP-2 [SP+1 , SP] (IP) (IP)  [ TYPE*4 ] CS  [ TYPE*4+2 ]


  • 2. INTO 若溢出中断指令 格式 INTO操作: 若O=1 , 则SPSP-2 [SP+1 , SP] FSPSP-2 [SP+1 , SP] (CS)SPSP-2 [SP+1 , SP] (IP) IP[0010H] CS[0012H] 3.IRET 从中断返回指令 格式 IRET操作: IP [SP+1, SP] SPSP+2CS[SP+1, SP]

  • SPSP+2F [SP+1, SP] SPSP+2

型号=4的中断44=10H4  4+2=12H12H的一个字的内容CS


  • 六、处理器控制指令(一)标志操作1. CLCC=0 2. CMC CC 3. STCC=1 4. CLDD=0 5. STDD=1 6. CLII=0 7. STII=1 (二)CPU暂停

  • HLT (三)CPU脱离ESC——交权指令(四)CPU等待Wait (五)总线锁定Lock


第三章 汇编语言程序设计

第一节 汇编语言语句


  • 一、语句类别 汇编语言的基本语句:指令语句 伪指令语句 宏指令语句 源程序是用汇编的语句编写的程序。 格式为NAME1 Segment NAME1 ENDS NAME2 Segment NAME2 ENDS ENDS指令语句格式为[标号:]助记符操作数1,操作数2 [;注释]

  • 伪指令语句格式为


  • [符号名]定义符参数1………..参数n [;注释] 宏指令语句格式为 [标号:]宏指令名参数1………..参数n [;注释] 1. 标号表示一条指令所在地址, 也是指令语句的地址符号, 最多 允许使用31个字符。不能以数字开头。符号名用在伪指令语句前面, 不是每一条伪指令都必须有一个 符号名的。2. 助记符及定义符由系统定义。3. 宏指令名由程序员定义,但不能用系统已经定义过的符号名。4.操作数用于指令语句, 参数用于伪指令和宏指令中。 5. 注释不是汇编语句的必须部分。


第二节 语句行的构成


  • 一、标记(一)字符集:字母、数字、特殊字符(+、-、*、/、{、;等)。(二)界符 : , < - + >

  • (三)常量 1.数字常量:二进制数、十进制数、八进制数、十六进制数2.字符串常量:由包含单引号内的1至2个ASCII字符构成。

  • (四)标识符 由程序建立的, 由最多31个字母, 数字及字符组成, 且不能 用数字开头。 如 : MY_DATA , SUM

  • THIS_DONE和THISDONE是不同的。(五)保留字:指令助记符, 伪指令, 寄存器名称。(六)注释二、符号 它是一种标识符, 符合标识符的组成规则。 寄存器、变量、标号、数、其它。(一)寄存器:AX 、AL。


  • (二)变量 存放在存储单元的操作数是变量, 存储单元的地址符号就是 它们的名字。 任何变量都有三种属性:

  • 1.段值(segment) 2.偏移量(offset):变量单元地址与段的地址之间的偏移量(16位) 3.类型(type):B(字节)、(W字)、(DW双字)(三)标号 与变量相似, 是存储单元的符号地址。 它在存储单元中存放指令, 变量存放数据。 类型 : FAR(CS、IP) 或 NEAR(IP)(四)数 源程序的常数, 常以符号形式出现,便于修改。 如 CountEQU100又如 把端口地址定义为一个符号PORT—VAL PORT—VAL EQU 3(五)其它(伪指令部分)除上述寄存器,变量,标记,数外都是伪指令segement/ENDS


  • 三、表达式 表达式是由标记、符号通过运算符组合起来的序列。 一个表达式是一个由操作数和运算符组合的序列。(一)操作数r , m , im(立即数) 1.常量操作数(-2 -1 , 2 -1), 即(-65535 , +65535) 2.存储器操作数 两种:标号——指令语句符号地址 如 JMP, Call变量——4种寻址方式--直接--基址--变址--基址加变址 可存放在M中的值 三种属性--段值--段内偏移量--类型(二)运算符

16

16


  • 有以下五种:算术运算符 逻辑运算符 关系运算符 分析运算符 合成运算符1. 算术运算符    mod当算术运算符用于存储器时, 只有当结果有明确的、有意义 的物理解释时才有效。 如 SUM+2 地址加2,而不是内容加2 CYCLE-5 NOT_DONE-GO 同段 而SUM-CYCLE 前者是数据段,后者是码段 在不同段,相减无意义 2. 逻辑运算符 按位操作的AND、OR、OR、NOT。其操作数只能是数字的, 且结果是数字, 存储器操作数不能进


  • 行逻辑运算。 如 NOT 1111 1111=0000 0000又如 1111 0000 1111 0000 OR SUM 无效的IN AL,PORT-VAL OUT PORT-VAL AND OFEH,AL若PORT是-VAL是偶数, “与”后仍是同一端口 若PORT-VAL是奇数, “与”后是PORT-VAL低的下一个端口作为汇编的运算符是在程序汇编时计算,而作为指令的助记符,则在程序执行时计算的.如 AND DX , PORT-VAL AND OFEH程序执行时计算3.关系运算符 相等EQ 不等NE 小于LT 大于GT 小于等于LE 大于等于GE关系运算的两个操作数或者都是数字,或者都是同段存储器地址,

汇编时计算


  • 结果是数值。0——关系假 , 0FFFFH——关系真。 如 mov BX , PORT-VAL LT 5若PORT-VAL的值<5 , 关系为真,则汇编程序在汇编程序后产生的语句为mov BX , OFFFFH否则 mov BX , 0一般把关系运算符与逻辑运算组合使用。 又如 mov BX , ((PORT-VAL LT 5) AND 20) OR((PORT-VAL GE 5) AND 30) 若PORT-VAL的值<5 汇编程序为

  • mov BX , 20否则mov BX , 30


第三节 指示性语句 ——伪指令


  • 一、符号定义语句(一)等值语句 EQU定义一个值、别的符号名、可执行指令 格式 NAME EQU Expression如 buffer-size EQU 32 count EQU CX 定义为寄存器CX的同义语CBD EQU ADD 定义为加法New-port equ port-VAL 在解除EQU以前, 不能重新定义。(二)等号语句 EMP能对符号进行再定义emp=6 , emp=7 , emp=emp+1 (三)解除语句 PURGE用于已经用的EQU语句的情况下 格式 Purge 符号1 , 符号2 , … , 符号n用purge解除后的符号可以再定义。 如 purge NEW-PORT NEW-PORT EQU PORT-VAL+2二、数据定义语句


  • 为一个数据项分配存储单元, 且并赋符号名和初值。 如 THING DB ? ; 定义一个字节BIGGER-THING DW ? ; 定义一个字BIGGEST-THING DD ? ; 定义一个双字THING DB 25 ; 一个字节把25放入和BIGGER-THING DW 4142H; 与THING相联系的存储单元 同样 biggest-thing DD 12345678H当汇编程序汇编时遇到“?”, 则它仍然为数据项分配相应存 储单元,以便存放指令执行的中间结果,并不产生一个目标码 来初始化存储单元。

biggest-thing

+1

+1

+1

78

56

34

12


  • 如POWERS-2 DB 1 , 2 , 4 , 8 , 16 ALL-ZERO DB 6 DUP(0) DB 100 DUP(0) DB 100 DUP(0) 又如 ALPHA DW 2 DUP(3 DUP((1,2 DUP(4,8),6),0)

POWERS-2

1

2

4

8

16

5个

1

4

8

4

8

6

1

4

8

4

8

6

1

4

8

4

8

6


  • 字符串(每个字符用ASCII表示, 为一个字节)如 EXAM1 DB ‘THIS IS AN EXAMPLE’或者 DB ‘ T , H , I , S ’ 字符串的定义必须是DB命令 一个存储单元的类型:

  • 1.数据字节SUB DB ? ; 定义一个字节2.数据字BIGGER DW ? ; 定义一个字3.数据双字BIGGEST DD ? ; 4.NEAR指令单元5. FAR 指令单元 一个指令单元能出现在JMP或CALL语句中。 若类型是near, 产生一个段内JMP、CALL,2个字节。 若类型是far , 产生一个段间JMP、CALL,4个字节。分析运算符把存储器地址分为5个:


  • seg

  • offset type size length 指令所在段的段地址加偏移量 一个存储单元地址加或减形成的新的存储单元与原来的存储 单元有相同的类型。seg功能:可用seg返回变量或标号所在段的段基址。 如 mov AX, seg ABC 把变量ABC的段地址AX offset功能:offset可返回变量或标号的所在段的偏移量。 type功能:返回一个表示变量或标号类型的数值。 变量 标号DB 1 NEAR -1 DW 2 DD 4 FAR -2


  • 如 ALFA DW 20 DUP(?) mov AL , type ALFA ; (2AL)Length分配单元长度操作符 功能:返回给该变量的单元数 仅对DUP项返回变量单元数,对其它情况均返回值1。 如 ALFA DW 20 DUP(?) BATA DB 12 mov AL, Length ALFA; (20 AL) mov AH, Length BATA; (1 AH) size功能:返回分配给该变量的字节单元数。 如 mov AL , size ALFA ; (40 AL) mov AH , size BATA ; (1 AH)显然size ALFA=(Length ALFA)*(type ALFA)合成运算符(PTR、THIS) type PTR variableconstant expression


  • 在PTR左边的操作数有3种:byte , word , Dword。 在PTR右边的操作数生成与原存储器操作数段地址、段内偏 移量相同, 类型不同的新的存储器操作数。 如 OPER1 DB 1 , 2 OPER2 DW 1234H , 5678Hmov AX , OPER1+1 mov BL , OPER2

请考虑一下指令中的斜体部分是否表示正确

正确的应该改为mov AX , WORD PTR OPER1+1 mov BL , BYTE PTR OPER2对于 mov AX , WORD PTR OPER1+1 OPER1+1的内容AX , 即OPER1+1的内容AL 02 AL所以(AX)=3402H


  • 而对于 mov AL , BYTE PTR OPER2把OPER2的第一个字节的内容BL , (AL)=34H THIS与PTR类似 其段地址加上段内偏移量就是汇编时当前值 段地址 + 段内偏移量

  • WBUFFER1 EQU THIS WORD BUFFER2 EQU THIS BYTE DWBUFFER3 EQU THIS DWORD三、段定义语句 它的主要命令有4个:segment ENDS assume 定义CS、ES是什么段 org 规定段内的起始地址 下面我们来看一个例子:my_DATA segment x DB?


  • y DW? z DD? My_DATA ENDS my_EXTRA segment ALPHA DB? BETA DW? GAMMA DD? my_EXTRA ENDS my_stack segment DW 100 DUP(?) TOP EQU THIS WORD my_stack ENDS my_CODE segment assume CS:my_CODE , DS:my_DATA

  • ES:my_EXTRA , SS:my_stack


  • start : mov AX , seg x mov DS , AX mov AX , seg ALPHA mov ES , AX mov AX , my_stack mov SS , AX mov SP , offset TOP my_CODE ENDS END start在汇编语言的源程序中,定义CS、SS、DS、ES每一个段必须 有一个名字。一个段由命令segment开始, ENDS结束,成对出现。 最后用END结束源程序。四、过程定义语句 在8088中调用过程和返回的指令是call和ret过程定义语句。PROC和ENDP是在说明call和ret是NEAR还是FAR型。 如 procedure_name proc [NEAR]


  • . ret procedure_name ENDP谨记proc和ENDP成对出现。 一个过程定义的例子:my_code segment my_code ENDS up_count proc near END ADD CX,1 RET up_count ENDP start : call up_count call up_count


  • 五、结束语句segment—ENDS proc—ENDP END END <表达式>表达式为第一条要执行的指令的地址


第四节 指令语句


  • 指令助记符 指令前缀 操作数寻址方式 串操作指令一、指令助记符(一)NOP:保留一些单元为以后填入指令时用,放慢速度。 (AX自行交换) (二)NIL:保留空格 如 CYCLE:NIL CYCLE:INC AX INC AX二、指令前缀1.段超越:由assume语句的信息选择段寄存器。 如 mov BX , ES :SUM

  • 由汇编程序决定在用选择的 段寄存器是否超越2.重复:rep repE 当相等时重复repNE 当不相等时重复

指令语句


  • repZ Z=1时重复repNZ Z=0时重复3.锁定:LOCK三、操作数寻址方式 共有8种:立即 寄存器 直接 基址 变址 基址变址 基址或变址+位移量 基址变址+位移量

  • 如 SUM DB ? 字节INC SUM 一个字节增量 如 mov AL , [BX]字节 由目的指定[BX]也是字节型 而 INC [BX] 是错误的INC BYTE PTR [BX] 一个字节增量INC WORD PTR [BX] 一个字增量四、串操作指令


  • 请回忆一下之前学过的指令 。COMPS (SI) -(DI)

  • 指令语句 指示性语句:符号定义、分存储单元、分段 码段 栈段 数据段 如两个未压缩的BCD码相加。 先数据段、再堆栈段、码段DATA segment stri1 DB ‘1’ , ‘7’ , ‘5’ , ‘2’ stri2 DB ‘3’ , ‘8’ , ‘1’ , ‘4’ count equ $-stri2 $表示当前地址计数的值

MOVS (DI) (SI) DI1,2 SI 1,2SCAS AL/AX-(DI) DI1,2 SI 1,2

LODS AL/AX(SI) SI 1,2STOS AL/AX(DI) DI 1,2

源程序

程序

关于$


  • DATA ENDS stack segment stack para stack ‘stack’ stapN DB 100 DUP(?) TOP EQU Length stapN stack ENDS CODE segment assume CS:code , SS:stack , DS:DATA , ES:DATA start proc FAR PUSH DS mov AX , 0 PUSH AX go: mov AX , DATA mov DS , AX mov ES , AX mov AX , stack mov SS , AX mov AX , TOP mov SP , AX

在堆栈中推入一个段地址DS和IP

返回DOS


  • CLC CLD mov SI , offset stri1 mov DI , offset stri2 mov CX , count cycle: LODS stri1 ADC AL , [DI] AAA STOS stri2 LOOP cycle RETSTART ENDPCODE ENDS END start定义数据 , 堆栈段 , 代码段 , 过程定义语句。RET返回DS , IP(0000H) DOS源——目标——连接——程序前缀


第五节 汇编语言程序设计及举例


  • 一、概述1.汇编语言源程序的结构NAME数据段名 segment变量定义 数据空间预量 数据段名 ENDS堆栈段名 segment para stack ‘stack’堆栈空间预量 堆栈段名 ENDS代码段名 segment assume段寄存器地址说明start : 段地址装填 主程序 过程名1 proc类型 过程体 过程名1 ENDP


  • 过程名N proc类型 过程体N过程名N ENDP代码段名 ENDS END start2. 段寄存器的装填CS由系统在加载程序后由系统自动装填SS也可以由系统自动装填 , 但必须将参数写全 如stack、segment、para、stack、‘stack’当程序装入内存时,系 统把堆段地址和栈指针置入SS和SP ,因而不必在代码段装填SS和SP。DS、SS、ES的装填mov AX , 数据段名mov DS , AX3.返回DOS DOS下运行汇编程序 , 当程序执行结束后返回DOS。 过程名 proc far push DS


  • mov AX , 0 push AX ret 过程名ENDP ENDP 过程名(INT 20H)是返回DOS的系统调用 , 系统将执行INT 20H系统(装入程序时)放在程序段前缀的头二个字节(100H字节的信息区, 放在程序段前)当执行程序后 , DS和偏移量CS、IP, 从而执行INT 20H4.编写程序步骤(1)建立数学模型

  • (2)确定解决模型的算法(3)画流程图 工作框 : 一个入口,一个出口 判断框 : 一个入口,几个出口


  • 子程序框: 一个入口一个出口 程序走向:

  • (4)分配内存单元和寄存器(5)写程序二、直线运行程序 两个32位无符号数乘法

A B

C D

BD

16位

AD

BC

AC

+

最后乘积


  • name data segmentmulnum dw 0000 , ffff , 0000 , ffff , 4 dup(?) data ends stack segment para stack ‘stack’

  • db 100 dup(?) stack ends code segment assume cs:code , ds:data , ss:stack , es:data start proc far being: push ds ; mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax lea bx , mulnummulu32: mov ax , [bx] ; BAX

DS中包含的是程序段前的起始地址 设置返回至DOS的段值和IP值

置段寄存器初值


  • mov si , [bx+4] ; D SI mov di , [bx+6] ; C DI mul si BD (DX , AX) mov [bx+8] , ax mov [bx+a] , dx mov ax , [bx+2] A AX mul si ; AD(DX , AX) 乘积2 add ax , [bx+a] adc dx , 0 mov [bx+a] , ax mov [bx+c] , dx mov ax , [bx] B AX mul di B C(DX , AX) 乘积3 add ax , [bx+a] 与乘积3的相应部分积相加adc dx , [bx+c] mov [bx+a] , ax mov [bx+c] , dx pushF 保存C(保存后一次相加的进位)

保存乘积1

乘积2与乘积1的相应部分相加

乘积3与乘积2的相应部分相加


  • mov ax , [bx+2] AAX mul di AC(DX , AX) 乘积4 popF adc ax , [bx+c] 与乘积4相应部分相加adc dx , 0 mov [bx+c] , ax mov [bx+e] , dx ret start endP code ends end beginP127 例: 32位有符号数乘法name data segment

  • sign db ?mulnum dw X1 , X2 , X3 , X4 , 4 dup(?) data ends


  • stack segment para stack ‘stack’ db 100 dup(?)code segment assume cs:code , ds:data , ss:stack , es:datastart proc farbegin:push ds mov ax , 0 push ax mov ax , data mov ds , ax mov sign , 0 置符号初值lea bx , mulum mov ax , [bx] B AX mov dx , [bx+2] A DX mov si , [bx+4] D  SI mov di , [bx+6] C  DI cmp dx , 0 检验正、负jns other 若为正(即S=0)转至other

返回至DOS


  • not ax not dx add ax , 1 adc dx , 0 not sign 改变符号mov [bx] , ax mov [bx+2] , dxother: cmp di , 0 检验乘数符号jns go mul 若S=0则转移到go mul not si not di add si , 1 adc di , 0 not signgo mul: call mulu32 调用无符号乘数cmp sign , 0 检验S位je done Z=1(相等)乘积为正 , 结束not word ptr [bx+8]

若为负则求补

保存被乘数

乘数求补


  • not word ptr [bx+a] not word ptr [bx+c] not word ptr [bx+e] add word ptr [bx+8] , 1 adc word ptr [bx+a] , 0 adc word ptr [bx+c] , 0

  • adc word ptr [bx+e] , 0 done: ret start endPmulu32三、分支程序设计

  • ( P129 )

<0

>0

x

=0

y-1

y0

y1

出口

乘数求补

1 X>0

y= 0 X=0

-1 X<0


  • sigef mov AX , buffer OR AX , AX 执行一个判断JE ZERO Z=1 转移至zero JNS plusS=0 转移至plus mov BX , FFFFH y-1 JMP conti zero : mov BX , 0 JMP conti plus : mov BX , 1 conti :例:数据AL的被置位的情况控制转移到8个子程序中。AL :

0000 0001

0000 0010

0000 0100

0000 1000

0001 0000

0010 0000

0100 0000 1000 0000

R1R2R3R4R5R6R7R8


  • name data segment brtab dw R11 子程序R1入口地址的IP值dw R12 子程序R1入口地址的码段值dw R21 同上dw R22 同上

  • dw R81 dw R82 data ENDSstack segment para stack ‘stack’ DB 100 DUP(?)TOP equ $-STACKstack endscode segmentstart proc far assume cs:code , ds:data , ss:stack , es:data begin : push DS

启动

Y

R1

D0=1?

Y

N

R2

D1=1?

N

Y

R7

R8


  • mov AX , 0 push AX mov AX , data mov DS , AX mov AX , stack mov SS , AX mov AX , TOP mov SP , AX lea BX , brtab 设跳转地址的地址指针gtbit: RCR AL , 1 JC getad C=1时转移 INC BX INC BX INC BX INC BX JMP gtbitgetad:JMP Dword ptr [BX] ;段间间接转移 start ENDP

C

BXBX+4


  • 四、循环程序设计

  • 例1.用计数器控制循环 寻找一串给定个数的数中的最大值,并放入指定单元中。 每个数用16位表示。name data segment buffer dw X1 , X2,…, Xn count equ $-buffer max dw ? data endsstack segment para stack ‘stack’

工作部分 控制部分

循环体 结构 循环结束条件 循环初态

循环工作初态:如标志位、寄存器清零 结束条件初态:CX的初态


  • DB 64 (?) top equ $-stackstack endscode segment assume cs:code , ds:data , ss:stack , es:databegin : push DS mov AX , 0 push AX mov AX , data mov DS , AX mov AX , stack mov SS , AX mov AX , top mov SP , AX mov CX , count SHR CX , 1 lea bx , buffer mov AX , [BX]


  • INC BX INC BX dec cxagain: cmp AX, [BX]

  • JGE next mov AX , [BX]next: INC BX INC BXLOOP againstart endPcode ENDS END start 例2. 条件控制循环 求16位无符号数的整数平方根X2=(N/X1X1)/2 X1=(N/200+2)若X1是数N的平方根的近似值,则X2是数N的平方根的最近   似值,这个称为逐次逼近法


  • name data segment num dw 2710H result dw ? digit equ 200 data ends stack segment para stack ‘stack’ db 100 dup (?)stack endscode segment assume cs:code , ds:data , ss:stack , es:databegin: mov ax , data mov ds , ax mov ex , ax lea bx , num mov ax , [bx] axN mov si , ax SIN


  • mov di , digit DI200 cwd双字扩展 AX(DX , AX) div di N/200 add ax , 2 N/200+2 AX=X1conti: mov cx , ax mov ax , si cwd div cx add ax , cx shr ax , 1 mov dx , ax sub dx , cx je done cmp dx , 1 jne contidone:mov [bx+2] , ax retstart endP

Q


  • code ends end begin3.多重循环delay : mov DX , 3FFH time : mov AX , FFFFH time1 : dec AX NOP JNE time1 dec DX JNE timeret————延时程序4.用开关量控制循环name data segment buffer dw 05…05 , 05…05 block dw 12 dup(?)

第一循环支路 第二循环支路


  • count1 equ 5 count2 equ 7 mov dx , 0 mov cx , count1+16CX lea bx , buffer lea si , blockagain : mov ax , [bx] cmp dx , 0开关量是否为零jne another 不为零则转移到another call fun1 为0 loop next mov dx , 1 mov cx , count2+1 8CX jmp again next : mov [SI] , ax inc bx inc bx


  • inc SI inc SI jmp againanother : call fun2 loop next ret start endP

  • fun1 proc add ax , ax ret fun1 endP fun2 proc add ax , ax add ax , ax ret fun2 endPcode ends end begin


  • 5.逻辑尺


  • 五、字符串处理程序设计  常用的字符编码是ASCII码字符。09为ASCII码的30 H39H AZ为ASCII码的41H5AH 常用的控制字符(不同系统有不同控制字符)

  • 0AH 换行 LF 0DH 回车 CR  字符串的长度常以某个特殊字符作为结束标志,如$、CR。 例 从头搜索字符串的结束标志,统计字符个数。(P141) name length-of-string data segment string db ‘abcduvwxyz’ , 0dH LL db ? Cr equ 0dH data endS stack segment para stack ‘stack’

  • stack endS code segment


  • assume cs:code , ds:data , es:data , ss:stack start proc far begin: push ds mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax lea di , string ;设串的地址指针mov dL , 0 置串长度初值=0 mov AL , cr      串结束标志AL again: scasb         搜索串je done inc DL jmp again done: lea bx , LL mov [bx] , dL ret


  • start endP code endS end begin为避免出现cr丢失,进入死循环,设循环次数>字符串长度data segment string db ‘abcdefghij’ , odh count equ $-string LI db ? data ENDS stack segment para stack ‘stack’ db 100 dup(?) stack ends code segment assume cs:code , ds:data , es:data , ss:stack start proc far begin: push ds mov ax , 0

  • push AX

返回DOS


  • mov ax , data mov ds , ax mov ES , ax lea di , string mov dL , 0     串长度初值为零mov aL , 0dh mov cx , count+10  置循环次数>串长度again: scasb je done inc dL

  • dec cx jne again jmp error  由计数停止循环,则出错,转至出错处理程序

  • done: mov LL,dL retstart endPcode ends end begin

给段寄存器赋初值


  • (二)找串中的第一个非空格字符P142 例 从一个给定的字符串中,从头开始,找到第一个非空格      字符。name data segment string db ‘abcdefghij’ , ‘$’ count equ $-string string2 db count dup(?) string3 db 0dh , 0ah , ‘$’ data ends stack segment para stack ‘stack’

  • db 100 dup(?) stack ends code segment assume cs:code , ds:data , es:data , ss:stackstart proc farbegin: push ds mov ax , 0


  • push ax mov ax , data mov ds , ax mov es , ax lea di ,string mov cx , count mov Al ,20H repe scasb

  • inc cx

  • mov bx, count

  • sub bx, cx

  • lea di, string2

  • lea si, string

  • add si, bx

  • rep movsb

关于rep


  • lea dx , string

  • mov ah , 9int 21H

  • lea dx , string3mov ah , 9int 21Hlea dx , string2mov ah , 9int 21H retstart endPcode ends end begin注:ah=9的功能是显示字符串,要求被显示输出的字符必须以$字 符作为定界符,以$为标记计算串的长度。

显示串1

显示串3

显示串2


  • (三)用空格代替前导零

  • namedatastring1 db ‘0000abcderty876’ , ‘$’count equ $-string1-1string2 db count dup(?) , ‘$’string3 db 0dh , 0ah , ‘$’data endsstack db 100 dup(?)stack endscodelea di , string1mov cx , countmov aL , ‘0’repe scasb


  • inc cx mov bx , count sub bx , cx lea di , string2 push cx mov cx , bx mov aL , 20h rep stosb pop cx lea si , string1 add si , bx rep movsb lea dx , string1 mov ah , 9 int 21h lea dx , string3 mov ah , 9 int 21h

        用空格填满串2

     显示串1

        显示回车、换行


  • lea dx , string2 mov ah , 9 int 21h start code End begin(四)加偶校验到ASCII字符  若有一个ASCII字符串,放在单元string内,要求从串中取出每  一个字符,检查其中包含“1”的个数,若已为偶数,则它的最高有  效位置“0”,否则最高有效位置“1”。name data string db ‘1234567890’ count equ $-string data ends stack db 100 dup(?) stack code begin:push ds

     显示串2


  • mov AX , 0 push AX lea si , string mov cx , countagain : lodsb and al , al jpe next or aL , 80hAL最高低置1mov [si-1] , aLnext : dec cx jnz again ret


  • 六、码转换程序设计硬件查表软件(一)16进制ASCII  若一个二进制数码串,把每一个字节中的二进制转换成2位16进制数的ASCII码,高4位ASCII码放在地址高的单元。

六、码转换程序设计硬件查表软件(一)16进制ASCII  若一个二进制数码串,把每一个字节中的二进制转换成2位16进制数的ASCII码,高4位ASCII码放在地址高的单元。4位2进制0~15,可用1位16进制(0 ~ 9,A~F)ASCII码,0 ~9的ASCII码只要将16进制数加上30H、A ~F的ASCII码加上37H就可得到对应的ASCII码。 根据是否大于10来判断是加30H还是加37H,完成16进制(2进 制)向ASCII码的转换。name data L1 dw 2 string db 34h , 98h L2 dw ? buffer db 2×2 dup(?)


  • data ends stack seg para stack’41-A’ db 100 dup (?) stack ends mov cx , L1 lea bx , string lea si , buffer mov ax , cx sal cx , 1 mov L2 , cx mov cx , axagain : mov AL , [bx] mov dL , aL and AL , 0FH call change mov aL , DL push cx mov cL , 4 shr aL , cl pop cx

高4位 右移4位


  • call change inc bx loop again ret start endP change proc cmp aL , 10 jL add-0 add AL , ‘a’-‘0’-10 add-0 : add aL , ‘0’ (AL+30H)AL<10 mov [si] , al (AL+37H) AL>10 inc si ret change endP code ends end begin


  • (二)ASCII码到十进制(BCD)的转换 若有一输入的ASCII,要把其中的数码( ‘0’~‘9’之间)取出来 ,转 换为未组合的BCD码,存放另一区,并统计串长度,放入此区的第 一个字节。502D 0101, 0000,0010未组合BCD 0101 0000, 0010数字的ASCII码是一种未组合BCD name data L1 db 10 string db ‘123asdfgki’ buffer db ? db 10 dup(?) stack db 100 dup (?) stack ends code


  • assume start proc farbegin : push ds mov ax , 0 push ax mov ax , data mov ds , ax mov es , ax mov CL , L1 mov CH , 0 lea si , string 一区lea di , buffer 另一区inc di 目的是首地址放DL的值mov dL , 0 数码计数器置0

  • again : lodsb cmp aL , ‘0’ jL next cmp aL , ‘9’

返回DOS

段寄存器赋值


  • jg next and aL , 0fh stosb inc dLnext : loop again mov buffer , dL ret start code End begin


  • (三)把BCD码转换为二进制

  • 若有一个16位存储单元,存放4位BCD数,要把它转换成二进制,并 放在另一存储单元中。( (千位数×10+百位数) ×10+十位数) ×10+个位数参见流程图

data dnum dw 9999h bnum dw ? data mov ax , dnum mov di , ax mov dx , ax mov bx , ax and bx , 000fh and dx , 00f0h mov cL , 4 shr dx , cL

and di , 0f00h mov cL , 8 shr di , cL and ax , f000h mov cL , 12 shr ax , cL

add ax , ax mov cx , ax add ax , ax add ax , ax add ax , cx add ax , di


  • (四)二进制到BCD转换关键:找出二进制包含1000,1000,100,10的个数,这样即可将二进 制转换为相应的BCD码。 例:有一个16位二进制数要转换为相应的十进制数ASCII码。Tips : 数字的ASCII码是一种非压缩的BCD码。参见其流程图

bnum dw 270FH strg db 5 dup(?) mov ax , bnum lea bx , strg mov dL , 0again1 : sub ax , 2710H ; AX-10000 js next1 inc dL jmp again1

next1 : add ax , 2710H add dl , 30H mov [bx] , dL inc bx mov dL , 0again2 : sub ax , 03e8H next2 : add ax , 03e8H


  • (五)从二进制到ASCII码串的转换 若要把1个二进制位串显示,要把串中每一位转换为它的ASCII码。 例:16位二进制数,每一位转换为相应ASCII存入string。num dw 4f78h string db 16 dup(?) lea di , string mvo cx , length string push di push cx mov aL , 30h rep stosb pop cx pop di mov aL ,31H mov bx , numagain : rcl bx , 1


  • jnc next mov [di] , aL next : inc di loop again ret七、列和表的程序设计  列-由数据单元组成;表-特殊目的数据结构。  有关列和表的主要操作:  查找、增加、删除、对其进行分类或排序。(一)无序列    加一个项至一个无序列,判断列中有无    若无,则把它加在列的最后。参见其流程图


name

data seg

buffer db 10, ‘abcdefghij’

db ?

key db ‘$’

data ends

stack seg para stack ‘stack’

code segment

assume:cs:code,ds:data,

es:data,ss:stack

start pro far

begin: push ds

mov ax,0

push ax

mov ax,data

mov ds,ax

mov es,ax

lea di,buffer

mov ax,data

mov ch,0

mov cl,[di]列长度→cx

inc di

mov al key

repnz scasb

je done

move [di],al

inc buffer

done ret

start endp

code ends

end begin


buffer db 10, ‘abcdefghij’

key db ‘f’

……

lea di,buffer

mov ch,0

mov cl,[di] 串长度→cx

inc di 指向第一元素

mov al,key

repnz scasb

jne done 未找到,结束

dec buffer 若找到,串长度-1

mov si,di ‘f’的下一个地址→si

dec si si-1→si,原来‘f’的地址

xchg si, di

rep movsb (di)←(si)

done: ret

start endp

code ends

end begin

2.删去一个元素—找到要删去的元素,列长度-1,元素上移


P156/例3-21.找出元素序列的最小值和最大值

2

取列长度→cx

Y

3

取列中第1元素

al<max

N

al→min

送min

al→max

1

送max

4

修改地址

取下一元素

完成否

Y

4

al=min

Y

N

1

N

al>min

3

Y

2


buffer db10,22,-12,80,-6,-70,

-9,127,-10,00,40

minval db ?

maxval db ?

lea bx, buffer

mov ch,0

mov cl, [bx]

inc bxbx指向列中第一个元素

dec cx

mov al, [bx]

mov minval, al

mov maxval, al

inc bx

dec cx

again: mov al, [bx]

cmp al, minval

je next相等→next

jg a1若到元素大,转a1

mov minval,alal<现在值

→minval

jmp next

a1:cmp al, maxval

jl next

mov maxval,al

next:inc bx

dec cx

jne again

ret


  • (二)气泡分类法   如下的10个数:22、-12、80、-6、-70、-9、127、           -10、00、40。

   如果按数的大小排列:    两者的比较办法:第N个数e 与第N-1个数e  相比较,若e > e ,则不变换;若e <e , 则变换。e N –1>e N-2 e2>e1若数组长度为N,最多经过N-1趟,可使数组大小排列有序。当第一趟比较结束,数组中的最小值冒到了顶部,为了除 去不必要比较,每次开始置标志为0(若交换-1;若不交换0)下次比较若为-1,就说明尚未排好;若为0,说明排好,便 停止循环。


  •    如果按数的大小排列:    两者的比较办法:第N个数e 与第N-1个数e  相比较,若e > e ,则不变换;若e <e , 则变换。e N –1>e N-2 e2>e1若数组长度为N,最多经过N-1趟,可使数组大小排列有序。当第一趟比较结束,数组中的最小值冒到了顶部,为了除 去不必要比较,每次开始置标志为0(若交换-1;若不交换0)下次比较若为-1,就说明尚未排好;若为0,说明排好,便 停止循环。参见流程图程序如下:

  • buffer dw 22 , -12 , 80 , -6 , -70 , -9 , 127 , -10 , 00 , 40 count equ $-buffer conti : mow bL , 0 mov cx , count

N-1

N

N

N-1

N

N-1


初始化

交换标志为0

修改变址值

取数组长度为N

N

比较完

设变址值

Y

N

变换标志=0?

取ej

Y

ej>e j-1

Y

返回

交换

标志为-1


  • mov si , cx dec si dec si shr cx , 1again : mov ax , buffer [si] cmp ax , buffer [si-2] jge next xchg ax , buffer [si-2] mov [si] , ax mov bL , -1 next : dec si dec si loop again cmp bL , 0 jne conti ret


  • 简化之:第二趟e2,e1比较多余 大循环(趟)I=2,每趟后I+1I小循环(次)每一趟中的小循环变量为N(数组长度)每两两比较一次N减量,N-1N当N<I,停止小循环。 若到某一趟,只发生eN,e N-1交换,或无交换 无需要比较,前N-2个元素已经有序,整个eN,e N-1交 换后,数组有序了。 若标志=N(每趟小循环的初值不变,则停止排序)


string dw 10,-80,-50, 00, 20,30,

40,100,2000,10000,

25000

key dw 2000

sflag dw ?

lea di, string

mov cx, [di] 列的长度→cx

inc di

inc di

mov ax, key

cmp ax, [di]

jl none 若<第一元素,列中无关键字

mov bx, cx

sal bx, 1 bx←有序列的元素

cmp ax, string [bx] 与最后一个

元素比较

jg none 无字

repne scasw 否则搜索

jne none 未找到,结束

dec di 若找到,DL指向关键字

dec di

mov sglag di

jmp done

none:mov ax, -1

mov sflag, ax 未找到,

-1→sflag

done: ret

(三).有序列操作:p160


  • (四).连接队列

  • 列中每一项除了数据元素外,还包括指向下一列元素的地址指针,占有内存空间,不用重新排列.

  • (五).表

  • P166例.有一个0度—90度的三角函数表,给定一个角度值,

  • 查出相应的正弦函数值.

元素2

元素3

元素1

第1个元素

第2个元素

最后元素

6020→

6060→

60A0→

6000

60A0→

6060

6000


符号sign=0

1

取角

查表得到正弦值

Y

角〈181

符号作为最高有效值

N

sign=1

ret

角=角-180度

角〈91度

角=180度-角

1


sintab db 0,2,4,6,8,0AH

rest db ?

mov al, 5

xon dl, dl 置0,符号为正

cmp dl, 180

jb simpos c=1,小于为正

or dl, 80 否则符号置为负

sub al, 180

sinpos:cmp al, 91

js getsin

neg al 角度取补,-al→al

add al, 180 变为180-角

getsin:lea bx, sintab

xlat

or al, dl

mov rest, al

ret


  • table dw 1,1,2,6,24,120,720,5040

  • result dw ?

  • digit db x

  • mov bh, 0

  • mov bl, digit

  • add bx, bx

  • lea si, table

  • mov ax, [si] [bx]

  • mov result, ax

P168例.有一个0!~7!阶乘法,在某一单元中给定一个值(0~7) 通过查表,找到它的阶乘值。


  • 八.参数传送技术

  • 子程序:说明含有下面的信息

  • 子程序名称、功能、子程序入、出口参数、子程序使用寄存器、存储区、子程序调用其他子程序的名 称、方式。

  • 一般调用程序向子程序传递有关参数是指:

  • 子程序操作时需要的数据或数据的地址,以便子程序根据这些参数完成有关操作。

  • 1.寄存器方式

  • 参数传递方式 2.存储器方式

  • 3.堆栈方式


  • (一)寄存器(调用程序与子程序之间通过寄存器传送参数)

  • 若一个子程序要对2个长度相同的数据区进行操作

  • 那么在主程序中:把长度首地址→内部寄存器

  • mov cx, length buffer

  • mov bx, offset buffer1

  • mov si, offset buffer2

  • call subr

  • (二)存储器(要传送的参数直接放在子程序调用指令之后)

  • call subr

  • dw bufl: 缓冲区长度

  • dw bufa:区A起始地址

  • dw bufb:区B起始地址

  • 此法取参数,必须从堆栈中取出返回地址(call下一条指令地址)

  • 取出参数,修改返回地址以指向其真正要执行的指令地址。

-L-

-A-

-B-


  • 子程序:push bp

  • mov bp, sp

  • mov bx, [bp+2] 从栈中取出返回地址(即参数所在地址)

  • mov cx, CS:[bx] cx←长度

  • mov s1, CS :[bx+2] A→s1

  • mov d1, CS:[bx+4] B→d1

  • add bx, 6 6=3*2个字节

  • mov [bp+2], bx 修改返回地址,使子程序能返回至所传送参数后

  • 面的指令

  • ret


  • (三)利用堆栈传送参数

  • date seg

  • buffer1 dw BUFA

  • buffer2 dw BUFB

  • buf dw BUFL

  • date ends

  • 主程序:lea bx, buffer1

  • push [bx]

  • push [bx+2]

  • push [bx+4]

  • call subr

  • 子程序:push bp

  • (subr) mov bp, sp

  • mov cx, [bp+4] cx←BUFL

  • mov d1, [bp+6] d1←BUFB

  • mov s1, [bp+8] s1←BUFA


  • 九.子程序设计

  • 若一个子程序能够被中断或被中断程序调用,称此子程序为能 重入。

  • 系统利用堆栈和寄存器来存放临时的数据就能够实现重入。

s

子程序1

SR1 PROC

主程序

start

Call SR1

ret

子程序2

SR2 PROC

Call SR2

Call SR1

ret

返回点地址的入栈和出栈都是自动实现的。子程序调用自己称为递归,递归必须是重入的。

END


stack

db 100 dup (?)

stack ends

code segment

assume cs: code, ss: stack

start proc far

begin: push ds

mov ax, 0

push ax

call add64

num1 dd x1, x2

num2 dd y1, y2

buffer dd ?, ?

ret

start endp

add64 proc

push bp

mov bp, sp

pushf 保存f

push ax

push cx 保存寄存器

push bx

mov bx, [bp+2] bx←num1首地址

push bx 首地址入栈

add bx, 18H bx←首地址+24

修改返回地址

mov [bp+2], bx 存入修改地址

P172.例. 64位加法


Pop bx 首地址出栈

Mov cx, 4 一次取16位,64位

取4次

Clc c=0

Again: mov ax, cs: [bx]

adc ax, cs: [bx+8]

mov cs: [bx+10H], ax

inc bx

inc bx

loop again

pop bx

pop cx 恢复寄存器

pop ax

popf 恢复f

pop bp

ret

add64 endp


push cx

mov ah, 0

mov al, num

call factor

mov fnum, ax 积存入

pop cx

Ret

Start endp

Factor proc

push ax

sub ax, 1

jne f-cont

pop ax

注意:1)定义须考虑段地址,段内偏移量(默认DS)2)取地址是在程序段定义的,故用CS:[BX] 3)主程序的调用子程序指令指入的是CALL指令的下一单 元地址(不是正确返回地址),所以要修改返回地址, 以指向真正要执行的指令地址。P175.例. n*(n-1) n>0 1 n=0

n!=

ax←num


jmp retam

f-cont:call factor

pop cx

mul cx

retam:ret

factor endp


name ----

data segment

num db 3

faum dw ?

data ends

stack segment para stack ‘stack’

db 100 dup (?)

stack ends

code segment

assume: cs: code, ds:data,

es:data, ss: stack

stack proc far

Begin: push ds

mov ax, 0

push ax

mov ax, data

mov ds, data

mov es, data

push cx

mov ah, 0

mov al, mun

call factor

mov faum, ax

pop cx

ret

数的阶乘: n*(n-1)! 1

n!=


start endp

f-cont:call factor

pop cx

mul cl

:ret

factor proc

push ax

sub ax, 1

jne f-cont

pop ax

jmp return

return:ret

factor endp

end begin


  • 无条件转移

  • JMP SHORT DST

  • 段内直接短转移,-128~+127范围相对转移,

  • DST为标号

  • 1. 如:JMP SHORT OVER

  • JMP NEAR PTR DST

  • 段内直接近转移,-32K~+32K范围相对转移,

  • DST为标号

  • JMP DST 段内间接转移

  • 64KB范围绝对转移,DST为寄存器

  • 2. 如:JMP CX

  • JMP WORD PTR DST 段内间接转移

  • 64KB范围绝对转移,DST为存储单元

  • 如:JMP WORD PRT [1234H]

段内直接转移

段内间接转移


  • 段间直接转移:JMP FAR PTR DST 段外绝对转移

  • DST为另一个代码段中的标号

  • 把DST所在段的值→CS

  • DST偏移量的值→IP

  • 段间间接转移:JMP DWORD PTR DST 段外绝对转移

  • DST为存储单元

  • 如:JMP DWORD PTR [1234H] 低字内容→IP

  • 高字内容→CS

  • 条件转移指令均为段内短转移,范围为:-128~+127

习题:

  • JMP WORD PTR [DI] 是 ( )

  • 2. JMP FAR PTR ABCD(符号地址)是 ( )

  • 段内间接转移 B. 段间间接转移

  • C. 段内直接转移 D. 段间直接转移


  • 十. I/O的DOS功能调用

  • 调用:把子程序的号(系统功能调用号)→AH

  • 把子程序规定的入口参数送至指定寄存器

  • 再由中断指令 INT 21H

  • 如:lea dx string

  • mov AH 9 显示字符串DS:DX

  • int 21H

  • 如:mov dl, outpot-char

  • mov AH, 2

  • int 21H 它要求把要输出的字符的ASCII码送至DL

  • DOS功能调用向CRT输出一个字符的子程序

  • lea DX,buffer 输入缓冲区的指针

  • 从键盘输入的一个字符串 mov AH,10

  • int 21H

DX→

规定长度

实际长度

字符


buffer db 10规定缓冲区长度为10字节

db ? 实际输入长度单元

db 10 dup (?) 存放输入字节

mov ax, data

mov ds, ax 置初值

mov es, ax

mov dl, ‘:’

mov ah, 2 显示“:”

int 21H

lea dx, buffer (DS:DX)=缓冲区最大

mov ah, 10 字符数,(DS:DX+1)

int 21H =实际输入字符数

lea bx, buffer+2 存放输入字符首地

址→buffer+2

mov al, [bx]

and al, 0FH

mov [bx], al

inc bx ASSII→BCD

mov al, [bx] 码,××(时)

and al, of

mov [bx], al

inc bx

inc bx

P179.例.软件时钟程序

跳过冒号字符

……………….

××分

跳过

××秒


lea bx, buffer+2

mov al, [bx]

call m0110

mov ch, al ch为时值

inc bx

inc bx

mov al, [bx]

call m0110

mov dh, al dh为分值

dl为秒值

again: call delay

mov al, dl al←秒值

add al, 1

daa

mov dl, al 秒值增1

cmp al, 60 是否为60

jne dispy 否,转显示

mov dl, 0 是,秒值为0

dispy: lea bx, buffer

mov al, 0DH 回车

mov [bx], al[bx]→回车

inc bx

mov al, 0AH

mov [bx], al 换行

inc bx

mov al, ch 时

call tran BCD→ASCII

inc bx

mov al, ‘:’

mov [bx], al

inc bx

取××时的第一个×

……

跳过

…….


mov al, dh 分

call tran

inc bx

mov al, ‘:’

mou [bx], al

inc bx

mov al, dl 秒

call tran

inc bx

mov al, ‘$’

mov [bx], al

push bx

push cx

push dx

lea dx, buffer

mov ah, 9

int 21H

pop dx

pop cx

pop bx

jmp again

start endp

m0110 proc

add al, al al*2

daa

mov cl, al

add al, al al*4

daa

add al, al al*8

显示字符串DS:DX


daa

mov cl, al 十位数→cl

inc bx

mov al, [bx]

add al, cl

ret

m0110 endp

tran proc

mov cl, al

shr al, 1

shr al, 1

shr al, 1

shr al, 1

or al, 30H 把十位数→ASCII码

mov [bx], al

mov al, cl

and al, of

or al, 30H 把个位数→ASCII

mov [bx], al

ret

tran endp

delay proc

push cx

push ax

mov cx, 0FFFFH

goon: dec cx

jne goon

pop ax

pop cx

ret

delay endp


  • 十一.结束用户程序返回DOS方法

  • 1.mov AH, 4CH

  • int 21H

  • 用功能调用4CH(程序结束后插入以上语句)

  •   2.int 20H

  • 返回DOS子程序,用中断调用20H

  •   3.jmp 0

  • 转移到0单元(程序段前缀的开始处,0单元放的是一条

  • int 20H)

  • start proc far

  • begin: push DS

  • mov AX, 0

  • push AX

  • ret

  • start endp

同 int 20H

弹出开始推入的AX(0000)和DX


  • 4.用功能调用00H

  • mov AH, 0

  • int 21H

  • 十二. 宏汇编与条件汇编

  •  (一).宏指令的用途

  •    1.宏指令可代替源程序重复使用的程序段

  • mov cl, 4

  • sal al, cl

  • 由于要多次使用,用一条宏指令代替如下:

  • SHIFT MACRO

  • mov cl, 4

  • sal al, cl

  • ENDM

=JDMP 0

定义符

宏定义的名

宏定义的体:宏指令代替的程序段

结束符


  • 指令语句(执行语句)

  •          伪指令(管理语句)

  •    凡要实现mov cl, 4; sal al, cl 的内容,可以用SHIFT

  • (宏汇编程序调用时,产生目标代码)

  •   2.宏定义不仅简洁方便,而且具有接受参量的能力

  • SHIFT MACRO *   (*是形式参量)

  • mov cl, *

  • sal al, cl

  • ENDM

  • SHIFT 4 实现移位4次

  •      若SHIFT MACRO *, Y Y代替需要以为的寄存器

  • mov cl, *

  • sal Y, cl

  • ENDM

宏定义的体


  • SHIFT 4, AL SHIFT 6, BX

  • mov cl, 4 mov cl, 6

  • sal, AL, cl sal BX, cl

  • 汇编时分别产生目标代码

  • 3.形式参量可以在操作码部分中出现

  • 如:SHIFT MACRO X,Y,Z

  • mov cl, X

  • S&Z Y, cl 定义为形式参数,前面必须加上符号&

  • ENDM

  • 参数Z用来指示操作码的操作

  • MOV CL, 4

  • SAL AL, CL

  • MOV CL, 6

  • SAR BX, CL

  • MOV CL, 8

  • SHR SI, CL

SHIFT 4, AL,AL

SHIFT 6, BX, AR

SHIFT 8, SI, HR


  • (二)宏操作伪指令

  • 1. MACRO/ENDM 宏定义伪指令

  • 格式: 宏定义名 MACRO 〈形式参量表〉

  • MACRO与ENDM成对出现

  • 2. PURGE 取消宏定义

  • 格式: PURGE 宏定义名 [,……]

  • 3. LOCAL 形式参量表 宏定义体内允许使用标号

  • CHANGE MACRO AL中有一位16进制数转换ASCII

  • CMP AL,10

  • JL ADD-0

  • ADD AL,’A’-’0’-10

  • ADD AL,0

  • ENDM

  • 格式:LOCAL 形式参量表

  • 必须是MACRO后的第一个语句,其间不允许分号和注释

错误

重复定义

重复定义在宏汇编内是不允许的


  • CHANGE MACRO

  • LOCAL ADD-0

  • 展开时为: + CMP AL, 10

  • + JL ?? 0000

  • + ADD AL, ’A’-’0’-10

  • + ?? 0000 ADD AL,’0’

  • + CMP AL, 10

  • + JL ?? 0001

  • + ?? 0001

  • 4.REPT/ENDM 重复块伪指令

  • 格式:REPT 〈表达式〉

  • ENDM

插入

指令体(重复体)


  • 重复执行指令体所包含的语句,重复次数为〈表达式〉值决定

  • 如: 把1-10分配给十个连续的存储单元

  • X=0

  • REPT 10

  • X=X+1

  • DB X

  • ENDM

  • 5. IRP/ENDM 常参数重复块伪指令

  • 格式: IRP 形式参量(参数表 )

  • 指令体

  • ENDM

  • 重复次数由参数的个数所决定,每重复一次,用表中参数代

  • 替形式参量

  • 如: IRP X 〈1,2,3,4,5,6,7,8,9,10〉

  • DB X

  • ENDM 把1-10分配给10个连续的存储单元


  • 6. IRPC/ENDM 串重复块伪指令

  • 格式: IRPC 形式参量,字符串(或〈字符串〉)

  • ENDM

  • 重复次数取决于字符串中字符的个数,且每次重复,依次把

  • 字符串中的字符代替形式参量

  • 如: 把1-10分配给10个连续单元

  • IRPC X,0123456789

  • DB X+1

  • ENDM

  • (三)宏定义嵌套

  • 可以嵌套在宏定义中利用宏调用(先定义)

  • DIF MACRO N1,N2

  • MOV AX,N1

  • SUB AX,N2

  • ENDM

指令体


  • DIFSQR MACRO N1,N2,RSULT

  • PUSH DX

  • PUSH AX

  • DIF N1,N2

  • IMUL AX

  • MOV RESULT,AX

  • POP AX

  • POP DX

  • ENDM

  • 另外,宏定义还可以包含宏定义

  • DIFMALOT CACRO OPNA,OPRAT

  • OPNA MACRO X,Y,Z

  • PUSH AX

  • MOV AX,X

  • OPRAT Z,AX


  • POP AX

  • ENDM

  • ENDM

  • 若有宏调用: DIFMALOT ADDITION,ADD

  • 汇编展开为:ADDITION MACRO X,Y,Z

  • PUSH AX

  • MOV AX,X

  • ADD Z,AX

  • POP AX

  • ENDM

  • 同样,它可以用于定义算术与逻辑运算指令

  • (四)宏指令与子程序的区别

  • 子程序:汇编后产生目标代码少,即目标程序占用的内存

  • 空间少,节约内存,但每次调用需要恢复保护,

  • 恢复现场,执行时间长,速度慢。


  • 宏指令:汇编时,把宏指令体插入到宏调用处,有多少次宏

  • 调用,在目标产许需要同样多次的目标代码输入。

  • 所以,宏指令目标程序长,占用内存多,但不需要

  • 保护断点,执行时间短,速度快。

  • (五)条件汇编

  • IF XX ARGUMENT ←条件

  • 语句体1

  • ELSE 任选

  • 语句体2

  • ENDIF

  • IF 〈表达式〉≠0 为真

  • IFE 〈表达式〉=0 为真

  • IF1 扫描第1遍的过程中 为真

  • IF2 扫描第2遍的过程中 为真

真 假


  • IFDEF 〈符号〉 指定符号被定义为真

  • IFNDET 〈符号〉 指定符号未被定义为真

  • INB 〈参量〉 空格

  • IFNB 〈参量〉

  • IFIDN 〈参量1〉 〈参量2〉 =2 为真

  • INDIF 〈参量1〉 〈参量2〉 ≠2 为真

  • (六)举例

  • P200.例3-36 64位加法

  • add64 macro n1,n2,buffer

  • lea bx,n1

  • mov cx,4

  • clc

  • again: mov ax,[bx]

  • adc ax,[bx+8]

  • mov [bx+10H],ax


  • inc bx

  • inc bx

  • loop again

  • endm

  • data

  • add64 num1,num2,buffer

  • ret

  • begin: push as

  • mov ax,0

  • push ax

  • mov ax,data

  • mov ds,ax

  • mov es,as

  • add64 num1,num2,buffer 宏调用

……


  • Login