870 likes | 1.03k Views
献给正为信息化建设事业作出杰出贡献的人们。. 计算机组成原理与汇编语言. “ 四个现代化,哪一化也离不开信息化。”. ……. 江泽民. Part 1 8086/8088 指令系统. 汇编语言部分 目 录. 1 、 8086/ 8088 的 CPU. 2 、 主存储器. 3 、 堆栈. 4 、 指令系统 5 、 提高性能的新技术. 第四章 8086/88CPU 与指令系统. 4.1 8086/8088 CPU
E N D
献给正为信息化建设事业作出杰出贡献的人们。献给正为信息化建设事业作出杰出贡献的人们。 计算机组成原理与汇编语言 “四个现代化,哪一化也离不开信息化。” …… 江泽民
Part 1 8086/8088指令系统 汇编语言部分 目 录 1、8086/8088的CPU 2、主存储器 3、堆栈 4、指令系统 5、提高性能的新技术
第四章 8086/88CPU与指令系统 • 4.1 8086/8088 CPU • 8086是16位微处理器,即CPU的内外数据总线为16位,一个总线周期可以传送一个字(16位)数据。 • 而8088是准16位微处理器,其CPU的内部总线为16位,外部数据总线为8位,因此一个总线周期只能传送一个 • 字节。但是两者的内部结构基本上是相同的,其地址引脚均为20位,可寻址1M字节(Byte)主存空间。 • 8086/8088的指令系统完全相同,在软件上是完全兼容的。
4.1.1 8086/8088CPU的结构 • 1.内部结构 • 8086/8088的内部结构如图4-2所示。下面分别讨论EU与BIU部件。 • (1)执行部件EU • 包括一个16位算术逻辑运算部件ALU(arithmetic logic unit)、一组通用寄存器、暂存器、标志寄存器,以及EU控制器。各寄存器和内部数据通路都是16位。EU的主要任务是执行指令.其功能为: • .从指令队列中取出指令代码,由EU控制器进行译码后产生对应的控制信号到各部件以完成指令规定的操作。 • .对操作数进行算术和逻辑运算,并将运算结果的特征状态存放在标志寄存器中。 • .由于EU不直接与系统总线连接,因此当需要与主存储器或I/O端口传送数据时,EU向BIU发出命令,并提供给BIU16位有效地址与传送的数据。
(2)总线接口部件BIU . • 包括-组段寄存器、指令指针、6字节的指令队列(8088是4字节)、20位总线地址形成部件,以及总线控制逻辑。BIU的主要任务是完成CPU与主存储器或I/O端口之间的信息传送,其功能为: • .从主存取出指令送到指令队列中排队。 • .从主存或I/O端口取操作数或存放运算结果。 • .计算并形成访问主存的20位物理地址。
2. 8086/8088主存地址的形成 • 将1M字节主存空间划分为若干段,每个段的最大长度为64K字节。相应地在BIU中设置段寄存器,用以存放20位段起始地址的高16位,称为段基值(segment base value)。由EU或指令指针lP提供段内的偏移量,即一个主存单无与所在段的段基址之间的字节距离。当CPU访问某个主存单元时,必须指明由哪个段寄存器提供段基值,同时又给出偏移量。然后由BIU将16位段基值左移4位后与16位偏移量相加,形成20位主存单元的物理地址,如图4-3所示。段基值左移4位后,得到一个20位的物理地址称为段基址(segment base address)。显然,段基址为xxxx0H,其低4位二进制数为0,即能被16整除的主存物理地址才可作为段基址。
4.1.2 8086/8088寄存器 • 8086/8088CPU中的寄存器包括段寄存器、通用寄存器以及用于控制的寄存器,如图4-4所示。下面介绍它们的功能。 • 1.段寄存器(Segment Register) • CS(代码段寄存器)——代码段(code segment)用来存放程序的指令代码序列。CS用来存放当前代码段段首址的高16位,即段基值。 • DS(数据段寄存器)——数据段(data segment)中存放程序的有关数据。DS用于存放当前数据段的段基值。 • SS(堆栈段寄存器)——堆栈段(stack segment)用于存放按后进先出顺序存取的信息。SS中存放当前堆栈段的段基值。 • ES(附加段寄存器)——附加段(extra segment)中常存放运算结果或辅助数据。ES中存放当前附加段的段基值。
2.通用寄存器(General Register) • EU中设置有8个16位通用寄存器,如图4一4所示,按使用情况可分为二种。 • (1)地址指针寄存器(Address Pointer Register) • 8086/8088访问主存单元的20位物理地址是由两个16位地址合成的:由16位的段寄存器给出段基址的高16位;由EU或指令指针给出相对该段基址的偏移量。执行部件EU中的4个16位地址指针寄存器通常用来提供全部或部分偏移量。
堆栈指针SP和基址指针BP通常用来作地址指针。堆栈指针SP和基址指针BP通常用来作地址指针。 • SP是特定用于存放堆栈段中栈顶字单元相对堆栈段基址的偏移量。在执行堆栈指令操作时,隐含使用的就是堆栈指针SP。在指令中用BP作地址指针时,如果未另外说明,它也是用于指向堆栈段内某一主存单元(字或字节)。BP除了作地址指针外,还可以用来存放参加运算的16位操作数或运算结果。 • 源变址寄存器SI和目的变址寄存器DI通常也用来作地址指针。在变址寻址中,SI和DI 的内容作为段内偏移量的组成部分。在多数情况下,源变址寄存器和目的变址寄存器可互换使用。但是在串操作指令中,SI和DI的使用是不同的。源串操作数必须用SI提供偏移量,目的操作数则必须用DI提供偏移量。对于串操作指令,SI和DI的作用不能互换,并且隐含规定使用哪一个或两个。与BP类似,SI和DI除了作地址指针外,也可用于存放16位操作数和运算结果。
(2)数据寄存器(Data Register) • EU中设置有4个16位的寄存器AX,BX,CX,DX,用以存放16位数据;也可以将每个寄存器的高8位和低8位分开,变成8个8位寄存器AH,AL,BH,BL,CH,CL,DH,DL(H表示高字节,L表示低字节),以便于处理字节数据。 • (3).用于控制的寄存器 • 8086/8088中用于控制的16位寄存器有两个:指令指针IP和标志寄存器FR。 • A 指令指针IP(Instruction Pointer) • IP作为指令的地址指针,其作用类似于其它汁算机中的程序计数器PC,当现行指令执行完毕,由IP提供下一条指令地址。在指令按顺序执行时,每当CPU按CS:IP内容合成的指令地址从主存读取一条指令后,就自动修改IP中的值,使IP内容为下一条指令起始字节所在主存单元的偏移量。如图4-6所示,CS的内容左移4位后(即得代码段段基址)与IP中的偏移量相加,将形成下一条指令首字节的主存单元地址。
B 标志寄存器FR(Flag Register) • 在EU中设有一个16位的标志寄存器FR,用来记录程序执行时的状态。FR中共有9个标志位,如图4-7所示。其中状态标志位6位包括CF、PF、AF、ZF、ZF、OF,用于记录EU执行算术逻辑运算指令后的结果特征,它们将影响某些指令(如条件转移指令)的执行。另外,控制标志位有3位为TF、IF、DF,它们在执行某些指令时起控制作用。 • .进位标志位CF(Carry Flag) • .奇偶标志位PF(Parity Flag) • .辅助进位标志位AF(Auxiliary Carry Flag) • .零值标志位ZF(Zero Flag) • .符号标志位SF(Sign Flag) • .溢出标志位OF(Overflow Flag) • .单步(或跟踪)标志位TF(Trace Flag) • .中断标志位IF(Interrupt-enable Flag) • .方向标志位DF(Direction Flag)
4.2 主存储器 • 4.2.1 8086/8088主存储器的特点 • 8086/8088CPU有20条地址引出线,因此具有lM字节的寻址能力,即可以在1M个字节单元中寻找出所需的一个存储单元。在机器内部是用20位二进制无符导数表示存储单元地址,为了方便书写和编程,在汇编语言程序中常用5位十六进制数或符号地址表示存储单元地址,十六进制的存储单元地址范围为0000H~FFFFH,如P122图48所示。 • 在8086/8088主存中,一个字节数据占用一个存储单元。一个字数据(16位)则占用二个相邻的存储单元,数的低8位(低字节)存放在低地址单元;高8位(高字节)存放在高地址单元,并以此数低字节所在存储单元地址作为字数据的单元地址。例如.图4-9中10000H字节单元存放数据56H,10001H字节单元内容为34H,10002H字节单元内容为12H;如把相邻单元字节组成一个字,则10000H字单元存放内容为3456H,10001H字单元内容为1234H。显然同一个主存单元地址既可看作字节单元地址,又可看作字单元地址,这要根据访主存指令中指明的是访问字节单元还是访问字单元决定。
8086/8088的访问主存指令中,将表示出是字节访问还是字访问。 • 程序中常使用符号地址,在定义符号地址(也称为变量名)时,就规定了它具有字节或字的类型属性。如在某指令中需临时修改其符号地址的字节或字的类型属性,可以选用适当的运算符或伪指令来说明。 • 在书写时,如果用X表示某存储单无的地址,则X单元的内容可以表示为(X),X也可用来表示寄存器地址。例如: • (10000H)=56H ;字节单元内容 • (10000H)=3456H ;字单元内容 • (AX)=1234H ;AX寄存器内容
4.2.2 主存储器的段结构 • 8086/8088把1MB主存空间按需要划分为若干段(Segment)。每个段都由连续的字 节单元组成,最大长度为64K(即65526),可作为独立寻址的逻辑单位。在程序中,段的个数、段的长度以及段的用途完全由编程者确定。并且一个段中的代码或数据,可以存放在该段内的任意单元中。 • 一个段起始单元的地址,称为对应段的段基址(20位)。8086/8088对段基址是有所限制的,不能起始于任意地址,要求其低4位必须为0(可被16整除)。在1M字节的地址空间中,可作为段基址的共有64K(65536)个,可表示如下: • 00000H,00010H,00020H,…512AOH,512B0H,…,FFFE0H,FFFF0H • 在程序中设置的段称为逻辑段。
4.2.3 逻辑地址与物理地址 • 在8086/8088系列微机中,每个主存单元对应二种地址:物理地址(Physical Address)与逻辑地址(Logical Address)。 • 1. 逻辑地址 • 2. 物理地址 • 由于允许逻辑段的重叠,因此一个存储单元可能对应若干个逻辑地址。如图4-12所示,物理地址为2201OH的存储单元可以对应两个逻辑地址,它们分别为2000H:201OH、2100H:1010H。经过逻辑地址到物理地址的转换,均转换为同一物理地址。 • 这说明,存储单元22010H既可对应在段基值为2000H的逻辑段中,也可对应在段基值为2100H的逻辑段中。
3. 逻辑地址的来源 • CPU在执行指令时,是按指令所需的操作类型从不同的来源获得存储单元的逻辑地址,然后形成对应的物理地址以访问主存。P124表4-2给出了不同操作类型获得段基值和偏移量的不同来源。 • 当CPU执行从存储器取指令的操作时,段基值必须由代码段寄存器CS提供,而偏移量从指令指针IP中获得。如指令执行的是堆栈操作,则必须由SS提供当前段段基值,而堆栈指针SP给出栈顶单元的偏移量。如指令执行时,需要存取存储器中的操作数,操作数通常存放在当前数据段中,则隐含由DS提供段基燎(即指令中不给出段寄存器名);如操作数在其它当前段中,则用其它段寄存器(如CS,SS,ES)来提供操作数所在段的段基值(即允许替代或超越),这时指令中必须要给出对应的段寄存器名,而存放操作数单元的偏移量是由EU根据指令提供的寻址方式计算得到的。按寻址方式计算出来的偏移量又称为有效地址(Eeffective Address)。
4.3 8086/8088堆栈 • 4.3.1 堆栈组织 • 8086/8088的堆栈是由SS指定的一段存储区(≤64KB)构成,并采用向上(地址码减小)生成方式,由堆栈指针SP指向栈项,如图4-13所示。SS提供堆栈段的段基值,SP的内容为栈顶单元相对堆栈段段基址的字节距离(偏移量)。当SP初始化时,其值为堆栈的长度(这时SP指向栈底+2电元)。由于SP是16位的寄存器,所以堆栈的最大深度是64K个字节(一个段的长度),最多存放32个字数据。 • 8086/8088堆栈规定以字(2个字节)为单位进行存取,字数据在堆栈中的存放格式是低字节在低地址单元,高字节在高地址单元,如图4-13中栈顶单元的内容为1234H。
4.3.2 堆栈操炸 • 首先要设置堆栈,主要是对堆栈段寄存器SS和堆栈指针SP赋初值。具体实现是在程序中安排G一个段作为堆栈段。如: • … • STACK1 SEGMENT PARA STACK • DB 40H DUP(0) • STACK1 ENDS • … • 对堆栈的操作都是在栈顶进行的
其基本操作有两个:压栈操作与出栈操作。 • 1. 压栈 • 用压栈指令PUSH可以将通用寄存器、段寄存器或字存储单元内容压入堆栈。 • 执行压栈指令PUSH的操作过程分二步进行: • ①(SP)-2→SP;首先修改栈顶指针,SP减2以指向空字单元(即新栈顶) • ② 数据→(SP) ;将寄存器或存储单元内容送入SP指向的空字单元中。 • 压栈指令“PUSH AX”的操作执行过程如图4---15
2.出栈 • 用弹出指令POP可以将当前栈顶字单元内容取出送到通用寄存器、段寄存器或字存储单元中。 • 执行出栈指令POP的操作过程分二步进行: • ①((SP))→寄存器/字单元 ;将栈顶宇单元内容送到指定寄存器或字单元中 • ②(SP)+2→SP ;修改栈顶指针,SP加2以指向新栈顶 • 出栈指今“POP”的操柞执行过程如图4--16所示。
4.4 8086/8088指令系统 • 8086/8088的指令采用变字长格式,指令由1~6个字节组成。第1个字节包含操作码,大多数指令的第2个字节表示寻址方式,第3~6个字节表示存储器操作数地址的位移量、立即操作数。 • 4 .4.1 8086/8088寻址方式 • 8086/8088各指令中的操作数有4种:寄存器操作数,立即数操作数,存储器操作数,I/0端口操作数。对不同的操作数,8086/80888有不同的寻址方式对它们进行存取。
1.寄存器寻址方式(Register Addressing) • 寄存器寻址方式是指:指令所需的操作数存放在CPU的寄存器(通用寄存器或段寄存器)中,通过指令中给出寄存器地址去找到操作数。其寻址过程如图4-17所示,“REG”是指令代码中的寻址字段,它表示操作数的寄存器地址。 • 在汇编指令中,寄存器地址直接用寄存器名表示,如用AX,BX,AL,BH,DS,ES等,这些寄存器可以是8位的,也可以是I6位的。 • 例如有一条传送指令: MOV AX,BX • 这是一条采用寄存器寻址的传送指令,它有两个操作数地址:BX是源操作数地址(即源操作数存放在其中);AX是目的地址。该指令完成把BX中的源操作数传送到目的地址AX中; • 若(BX)=I234H,则执行该指令后(AX)=1234H。
又如; • MOV BL,AL ;将AL中的内容送到BL中 • MOY CH,DL • MOV DX,CX • MOV DS,AX • 寄存器寻址方式表示寻找的操作数就在CPU内部的寄存器中不需要执行总线周期,因此,执行速度快。
2.立即数寻址方式(Immediate Addressing ) • 立即数寻址方式是指:指令所需的操作数直接在指令代码中,随着取指令一起取到BIU的指令队列中。在指令执行时立即数作为指令的一部分直接从指令队列取出,不需另外占用总线周期,因此执行速度快。立即数可以是8位,也可以是16位如图4--18所示。 • 在汇编指令中,立即数如是数值常数可直接书写,如是字符常数则应加上引号。指令中的立即数经常用于给寄存器或存储单元赋初值,并且只能作为源操作数,不能作目的操作数。例如: • MOV CX,0B3CAH • MOV AL,25 • MOV BX,“AB” • MOV AH,`C` • 在汇编指令中,立即数若是以A~F开始的十六进制数则必须在数前面加上0,如上述的 第一条指令,否则汇编程序会将立即数当作符号处理。
3.存储器导址方式 • 上述两种寻址方式,操作数在寄存器或指令中。而以下几种寻址方式,操作数都是在主存储器中。在汇编语言程序中,一个存储单元的地址采用逻辑地址来表示,其形式为: • 段基值:偏移量 • 段基值由某个段寄存器提供,P124表4--2给出了存储器操作数逻辑地址中的段基值的隐含来源和替代来源。通常指令中不明显给出逻辑地址中段基值的来源(即段寄存器名),而是在执 • 行指令时使用隐含来源作为段基值。既然段基值是由指令隐含给出,因此J又下寻址方式讨论 • 的重点是如何确定操作数逻辑地址的偏移量。 • 偏移量是指存放操作数的存储单元与段起始地址(段基址)之间的字节距离,它由CPU的 • 则按指令中操作数的寻址方式计算而得到.又称为有效地址EA。
EA是由三个地址分量的某种组合求得的,它们分别是; • .位移量:它是指令代码中的一个8位或16位二进制数。通常在源程序中,位移量以符号地址(变量名或标号)的形式出现,也可以是常数,经汇编后,这些符号地址的偏移量或常数就转换为指令代码中的位移量。 • .基地址:即基址寄存器BX或基址指针BP的内容。 • .变址量:即变址寄存器SI或DI的内容。 • 这三个地址分量的组合不同,使形成有效地址EA的方法不同,相应有几种不同的存储器操作数的寻址方式。
(1)直接寻址方式(Direct Addressing) • 直接寻址方式是指:指令所需的操作数存放在存储单元中,操作数的有效地址EA直接由指令代码中的位移量提供,其寻址过程如P130图4-19所示。在源程序中,直接寻址方式可以用数值地址或符号地址来表示。 • .用数值地址表示 • 在采用直接寻址方式的汇编指令中,如用数值表示操作数的有效地址,则操作数所在段的段寄存器必须指明,不能缺省。 • 例如,传送指令源操作数的有效地址用数值地址表示: • MOV BX,DS:[1000H] • 这条指令完成将当前数据段偏移1000H个字节的字单元内容I234H送入BX中,如图4-20所示,其中源操作数的有效地址EA是1000H。
.用符号地址表示 • 在源程序中,常用符号地址表示存放操作数的存储单元,因此在汇编指令中,可用符号地址表示的直接寻址方式来存取操作数。操作数知果存放在数据段中,则指令中不必给出数据段寄存器名(即隐含使用DS);如果操作数不是存放在数据段中,则必须给出段寄存器名。例如: • MOV BX,VAR ;将VAR指向的字单元内容送到BX中,如图4-21所示 • MOV DA_BYTE,0FH ;将立即数0FH置入DA_BYTE指向的字节单元 • MOV CL,DA+3 ;把由DA地址偏移3个字节的字节单元内容送到CL中 • 上述3条指令分别等价于: • M○V BX,DS:VAR • MOV DS:DA_BYTE,0FH • MOV CL,DS:DA+3
(2)寄存器间接寻址方式(Register Indirect Addressing) • 寄存器间接寻址是指:指令所需的操作数在存储单元中,操作数的有效地址EA直接从基址寄存器(BP或BX)或变址寄存器(SI或DI)中获得。这种寻址方式实际上是将有效地址事先存放在一个寄存器中,因此这个寄存器就如同一个地址指针。如P131图4-22所示,“MOD R/M”是指令代码中的寻址字段。若以BX,SI或DI间接寻址时,隐含使用的段寄存器是DS;以BP间接寻址,则隐含使用的段寄存器是SS。
由于用寄存器作地址指针. • 因此在程序中只要修改间址寄存器的内容,就可以用同一条指令访问不同的存储单元。这种寻址方式的所用格式如下: • MOV CH,[SI] • MOV「DI],BX • MOV AL,[BX] • MOV CX,[BP] • 上述指令分别等价于: • MOV CH,DS:「SI] • MOV DS:[DI],BX • MOV AL,DS:「BX] • MOV CX,SS:[BP]
(3)变址寻址(Indexed Addressing)和基址(Based Addressing)寻址方式 • 指令所需的操作数在存储单元中,操作数的有效地址EA是基址寄存器(BP或BX)或变址寄存器(SI或DI)的内容与指令中给出的位移量(8位或16位)两个地址分量之和。使用SI或DI称为变址寻址,使用BX或BP则称为基址寻址。其寻址过程如P131图4-23所示。 • 如寻址所用寄存器是SI、DI或BX,则隐含使用的段寄存器是DS;如是BP,则隐含使用的段寄存器是SS。在汇编指令中,位移量部分可用数值表示,也可用符号地址表示(此时用符号地址的偏移量作为位移量),其寻址方式的使用格式为: • MOV AX,10H「SI] • MOV TABLE「DI],12H • MOV AX,ARRY[BX] • MOV TAB1「BP],CL • 上述指令分别等价于: • MOV AX,10H[SI] • MOV DS:TABLE[DI],12H • MOV AX,DS:ARRY「BX] • MOV SS:TABI[BP],CL
变址或基址寻址方式 • 常用来访问顺序存放在主存中的一维数组、表格,字符串等。其典型的用法是将指今中不能修改的位移量作为基准地址,而变址或基址寄存器内容作为修改量。例如数组的起始单元位置是固定的,因此由指令中的位移量给出;而被访问的数组元素相对其起始单元的距离由变址或基址寄存器提供,通过修改寄存器的内容就可以访问数组中不同的元素。 • P132 例4-1 如图4-24所示,一维数组ARY存放在主存的数据段中,数组的每个元素长度相同且占2个字节单元。从数组的首址起依次存放各数组元素ARY(0),ARY(I),ARY(2), • …ARY(I)。指令:MOV AX,ARY[SI]可用来访问数组中的元素,指令中的符号地址ARY指向该数组的首址;变址寄存器SI内容表示所访问元素与数组首址之间的字节距离,则所访问元素的有效地址:EA=ARY的偏移量+(SI)。当SI内容为0时,将访问ARY(0)元素;SI内容为1*2时,访问ARY(1)元素;SI内容为I*2时,访问ARY(I),即通过修改SI的内容可以访问数组中任何一个元素。图4-24给出了访问数组元素ARY(2)的寻址过程。 • 从上例可以看出,这种寻址方式中的位移量表示基准量,如数组首址,而变址寄存器的内容表示相对基准量的一个值,如某数组元素相对首址的字节数,因此这种寻址方式也称为寄存器相对寻址方式。
(4)基址变址寻址(Based Indexed Addressing) • 指令所需的操作数在主存单元中,操作数的有效地址EA是三个地址分量之和,即基址寄存器(BX或BP)内容、变址寄存器(SI或DI)内容与指令中的位移量(8位或16位)之和,称为基址变址寻址方式,如图4-25所示。若基址寄存器选用BP时,隐含使用的段寄存器是SS;若选用BX时,则隐含使用的段寄存器是DS。 • 这种寻址方式的位移量可用数值或符号地址表示,其使用格式为: • MOV AX,200H「BX]「SI] • MOV TABLE「BX]「DI] ,0FFH • MOV AX,ARRAY「BP ] [SI ] • MOV TAB1[BP]「DI],DL • k述指令分别等价于: • MOV AX,DS:200H「BX]「SI] • MOV DS:TABLE「BX][SI],0FFH • MOV AX,SS:ARRAY「BP][SI] • MOV SS:TAB1「BP]「DI],DL
由于基址变址寻址方式中 • 有两个地址分量可以在程序执行过程中进行修改,因此常用来访问存放在主存中的1维数组。 • P133例4-2 如图4-26所示,ARRAY数组是10行10列的二维数组,按行存放在主存堆栈段中。从数组的首址ARRAY起依次存放各数组元素:第0行元素为ARRAY(0,0)~ARRAY(0,9)共10个,第一行元素为ARRAY(1,0)~ARRAY(1,9),依此类推。每个元素占用一个字节单元。可以用指令: MOV AL,ARRAY[BP][SI] 访问数组中的某个元素ARRAY(i,j),指令中的位移量ARRAY指向数组首址,Bp存放被访问行的起始位置相对数组首址的距离ix 10,SI存放被访问数组元素相对本行首址的距离j,则要访问元素的有效地址EA=ARRAY的偏移量+(BP)+(SI),段基值隐含由SS给出。 • P134图4-26中给出了访问数组第1行第8列元素ARRAY(1,8)的寻址过程。ARRAY指向数组起始位置,BP内容为1x10以指向该数组中第1行起始点,SI内容为8以指向该行内第8个元素,三者之和即为被访元素ARRAY(1,8)的有效地址EA。显然,修改BP就可以访问数组的不同行,而修改SI则可以访问同一行中不同的元素。
存储器操作数,寻址方式地址计算小结: • P135图4-27表示了4种存储器操作数寻址方式计算有效地址EA的过程。图中上半部表示,由CPU的执行部件EU根据寻址方式计算有效地址EA;下半部表示,由总线接口部件BIU形成操作数的物理地址:将段基值左移4位得段基址与有效地址EA相加。按操作数的物理地址就可直接访问存放操作数的存储单元。 • 通常存储器操作数存放在隐含指定的段中,因此指令中不必给出段寄存器名。操作数也可以存放在非隐含指定段中,这时就必须用段超越前缀来指出操作数所在的段。在使用段前缀时应遵循P124表4-2中有关允许替代段寄存器的约定。例如: • MOV AX,ES:TAB[SI] • 段前缀“ES”表示数组元素在附加段中,而不是在数据段中。应注意,操作数在非隐含段内时,段超越前缀是不能省去的。
4.串操作寻址方式(String Addressing) • 8086/8088提供专门的串操作指令,这些指令所用的操作数也在存储器中,但它们不能使用上述寻址方式,而是隐含使用变址寄存器SI与DI,如图4-28所示。串操作指令规定,隐含使用SI作为在数据段中的源串(即源操作数)的地址指针;隐含使用DI作为在附加段中的目的串的地址指针。在完成一次串操作后,指令自动修改SI,DI两个地址指针,使SI,DI指向下一个串元素的存储单元。由标志寄存器中的方向标志位DF的值来确定指针的修改方向,若DF=0,则SI,Dl自动增量;否则SI,DI自动减量。若串操作指令处理的是字节串,增量/减量均为1,若处理的是字串,则增量/减量均为2。 • 5. I/O端口寻址 • 有关I/O端口寻址的内容将在以后的章节中介绍。
4.4.2 8086/8088指令 • 8086/8088指令按操作数地址个数可划分为3种类型: • (1)双操作数指令:OPR DEST,SRC • OPR表示指令操作码。指令中给出2个操作数地址,SRC表示源操作数地址,简称源地址;DEST表示目的操作数地址,简称目的地址。 • (2)单操作数指令:OPR DEST • 指令中只给出1个操作数地址DEST。若指令只需1个操作数,则该地址既是源地址又是目的地址。若指令需2个操作数,则另一操作数地址由指令隐含指定。 • (3)无操作数指令:OPR • 一种情况是指令未给出操作数地址,但隐含指定了操作数的存放处。另一种情况是指令本身不需要操作数。 • 在8086/8088指令系统中,除串操作指令以外,其余所有指令最多只能有一个操作数存放在存储器中。对于双操作数指令而言,两个操作数不能同时是存储器操作数。
8086/8088指令按功能可分为6大类: • (1)传送类指令(transfer instructions) • (2)算术运算类指令(arithmetic instructions) • (3)位操作类指令(bit manipulation instructions) • (4)串操作类指令(string instructions) • (5)程序转移类指令(program transfer instructions) • (6)处理器控制类指令(processor control instructions) • 下面就分别介绍这几类指令(其中的第5类指令在以后的章节中介绍),下述指令均采用汇编指今格式描述。
一、传送类指令 • 这类指令又可以分为4种:数据传送指令、交换指令、标志位传送指令、地址传送指令。这类指令除了SAHF,POPF指令以外,其余指令对标志位均无影响。 • 1. 数据传送指令(Move) • 指令格式:MOV DEST,SRC • 指令功能:DEST←(SRC),即将源地址的内容(源操作数)传送到目的地址中。传送指令执行完后源操作数保持不变。 • 受影响的状态标志位:无。 • MOV指令中的两个操作数可以同时是字节或字,但两者位数必须一致。源操作数可存放在通用寄存器、段寄存器、存储器中,也可以是立即数;目的操作数则不能为立即数。并且两个操作数不能同时为存储器操作数。在MOV指令中数据的传送方向如P137图429所示。 • 请见P136例 • 由于指令中只允许一个操作数在存储器中,因此用一条MOV指令不能完成两个存储单元之间的数据传送,但可以用两条指令来实现。见P137例4-3,例4-4
2.交换指令(Exchange) • 指令格式:XCHG DEST,SRC • 指令功能:(DEST) ←→ (SRC),即将源地址的内容(源操作数)与目的地址的内容(目的操作数)相互交换。 • 受影响的状态标志位:无。 • XCHG指令所交换的数据可以是字节或字。数据交换只能在通用寄存器之间或通用寄存器与存储单元之间进行,如P138图4-30所示。交换指令不能使用段寄存器,也不能使用立即数。 • P138 例4-5
3.标志位传送指令 • 这种指令用于对标志寄存器进行存取操作,共有4条指令且都是无操作数指令。 • (1) 取标志指令(Load Register AH from Flag) • 指令格式:LAHF • 指令功能;AH←(FR)-7~0,即将标志寄存器FR低8位内容传送到AH寄存器中,也就是把标志位SF,ZF,AF,PF,CF送至AH中的第7,6,4、2,0位,如图4-31所示。 • 受影响的状态标志位:无。
(2)存标志指令(Store Register AH into Flag) • 指令格式:SAHF • 指令功能:FR-7~0←AH,即将AH寄存器的内容传送给标志寄存器FR的低8位。 • 受影响的状态标志位:SF,ZF,AF,PF,CF。 • SAHF指令用以设置或恢复SF,ZF,AF,PF,CF5个标志位。它只影响标志寄存器的低8位即OF,DF,IF,TF标志无影响。 • 例4-6 将标志位SF,ZF置1,将AF,PF,CF置0,可用以下两条指令实现: • MOV AH,11000000B • SAHF
(3)标志压栈指令(Push Flag) • 指令格式:PUSHF • 指令功能:①SP←(SP)-2 • ②栈顶字单元←(FR) • 受影响的状态标志位:无。 • PUSHF指令先将栈顶指针SP内容减2指向空字单元,然后把16位标志寄存器FR的所有内容送到SP指向的新栈顶字单元中。
(4)标志出栈指令(Pop Flag) • 指令格式: POPF • 指令功能:①FR←(栈顶字单元) • ②SP←(SP)+2 • 受影响的标志位:所有标志位。 • POPF指令先将SP指向的栈顶字单元的内容弹出到标志寄存器FR中,然后SP内容加2指向新的栈顶。各标志位的状态由堆栈弹出字的对应位内容决定。 • 标志寄存器中只有CF,DF,CF3个标志位有专门的标志位操作指令,而其余标志位则没有专门的指令直接对它们进行没置或修改。例如要修改ZF,可先用LAHF指令将标志寄存器的低8位送入AH,然后对AH的第6位进行修改,再用SAHF指令将修改后的内容送回标志寄存器。若要修改TF,则必须使用PUSHF和POPF指令。
4.地址传递指令(Address Trnsfer) • 这种指令完成传送存储器操作数的地址到指定的寄存器,而不是传送操作数。 • (1) 装入有效地址指令(Load Effective Address) • 指令格式:LEA DEST,SRC • 指令功能;DEST←SRC的EA,即将源操作数的有效地址EA传送到目的地址(16位通用寄存器)中。 • 受影响的状态标志位:无。 • LEA指令的源操作数必须是存储器操作数(可以是字节或字),而目的地址只能是16位通用寄存器名。 • 如P139图4-32所示,设指令“LEA SI,BUF”中BUF的有效地址EA是100H,因此该指令完成将100H送入SI中,而不是把DS:100H所指向字单元的内容00FFH送入SI中。
(2)装入地址指针指令 • 在前面曾介绍,一个存储单元的逻辑地址是由16位段基值和16位偏移量组成。因此可用4个字节单元来存放这个逻辑地址。用4个字节单元构成32位的地址指针,段基值I存放在2个高字节单元中,偏移量则存放在2个低字节单元中,如P140图4-33所示。 • 指令LDS(LES)的功能就是从作地址指针的4个存储单元中,同时取出段基值与偏移量(即源操作数),分别送到段寄存器DS(ES)和通用寄存器中。 • 指令格式:LDS DEST,SRC ~l • LES DEST,SRC • LDS指令功能:DEST←(SRC) • DS←(SRC+2) • 受影响的状态标志位:无。 • LDS指令是将SRC指定的32位地址指针中的偏移量送入DEST所指定的通用寄存器中,而将地址指针中的段基值送入DS中。LES的功能与LDS类似,不同的只是用ES代替DS。 • 这两条指令中的源操作数必须是存储器操作数,源地址SRC给出32位地址指针的首字节地址;而目的地址DEST则只能是16位通用寄存器名。
例4-7 • P140图4-34给出了指令“LDS SI ,ADR[BX]”的执行情况。由源地址ADR[BX]可以计算出源操作数在数据段的有效地址EA。这时EA及EA+2指向的字单元作为32位地址指针。EA指向的字单元存放的是偏移量,应送到指令指定的SI中;EA+2字单元存放的是段基值,应送到DS中。该指令执行完后,DS的内容为新的段基值。 • LDS,LES两条指令常用于处理不在当前数据段和附加段的串操作数。在串操作指令中,隐含使用DS:SI指向源串,ES:DI指向目的串。如程序中需处理的串不在当前数据段或附加段中,就必须修改DS,ES,这时可用LDS与LES指令来实现,并且在指令中使用SI,DI作目的地址,让SI,DI分别存放源串与目的串的偏移量。
二. 算术运算类指令 • 算术运算类指令包括加减乘除4种指令。这类指令可以对字节或字数据进行运算,参加运算的数可以是无符号数或带符号数。由于8086/8088提供十进制数运算校正指令,因此参加运算的数也可以是BCD码表示的十进制数。
1. 加法运算指令 • (1)加法指令(Addition) • 指令格式:ADD DEST,SRC • 指令功能:DEST←(SRC)+(DEST),即源操作数与目的操作数相加,其和送入目的地址中。并根据相加结果设置标志寄存器的OF,SF,ZF,AF,PF和CF标志位。该指令执行后,源操作数保持不变。 • 该指令的操作数可以是字节或字,源操作数可以存放在通用寄存器或存储单元中,也可以是立即数;而目的操作数只能在通用寄存器或存储单元中,不能是立即数。并且两个操作数不能同时为存储器操作数。 • P141 例4-8 加法指令的常用格式有: • ADD BX,SI • ADD DA_WORD,0F8CH • ADD DL,TAB[BX] • 下面以指令“ADD DL,OA4H”为例给出该指令的相加及标志位设置过程。设DL的内容为0E5H:见P141。
(2)带迸位加法指令(AddWi山C~) • 指令格式:ADCDEST,SRC • 指令功能:DEST←(SRC)+(DEST)+CF,即在完成2个操作数相加的同时,将标志位CF加上,求出的和数送入目的地址中。并根据相加的结果设置标志位OF,SF,ZF,AF,PF和CF。 • ADC指令主要用于大于16位数的相加运算。 • P141 例4-9 有一个32位无符号数存放在DX(高16位)、AX(低16位)中,若要加上常数76F1A23H,则用以下指令来实现: • ADD AX,1A23H • ADC DX,76FH • 其中第一条指令完成把16位常数加在AX中,若产生进位,则记录在CF中。由ADC指令在完成高16位相加的同时,将低16位的进位也加上。