例3.1 指出下列各指令中源操作数和目的操作数的寻址方式。
①MOV BX,WORD PTR[2200H]
②AAA
③JMP 2200H
④IDIV WORD PTR[DI]
⑤STI
⑥LES DI,[2100H]
⑦MOV[BX+SI+8],BX
⑧LAHF
⑨WAIT
⑩OUT DX,AL
解
①源操作数:直接寻址。目的操作数:寄存器寻址。
②源操作数:寄存器寻址AL(也称隐含寻址)。目的操作数:寄存器寻址AL。
③程序转移段内直接寻址方式。
④源操作数:寄存器间接寻址。目的操作数:寄存器寻址。
⑤源操作数:标志寄存器寻址。目的操作数:标志寄存器寻址,也可称为bit(IF)寻址。
⑥源操作数:直接寻址。目的操作数:寄存器寻址。
⑦源操作数:寄存器寻址。目的操作数:基址加变址寻址。
⑧源操作数:标志寄存器寻址。目的操作数:寄存器寻址,或统称为隐含寻址。
⑨无(操作数)寻址方式。
⑩源操作数:寄存器寻址。目的操作数:寄存器间接端口寻址。
讨论
8086 CPU有24种寻址方式,常用的有立即寻址、寄存器寻址、寄存器间接寻址、直接寻址、变址寻址、基址加变址寻址等。本题的10种寻址方式中既有常用的寻址方式,也有不常用的寻址方式。这说明CPU寻址方式一定要分清源操作数寻址和目的操作数寻址。
还有一些寻址方式上文没有介绍,例如,PUSHF指令的寻址方式是一种隐含寻址,源操作数隐含在FR中,目的操作数隐含在堆栈中,而堆栈(内存)地址在寄存器SP中,也就是说目的操作数的地址是由寄存器间接提供的,这种通过堆栈指针SP的寻址方式也称为堆栈寻址。
有些指令如DAA、CBW、HLT、INT n、RET、CLC等,都是特殊的寻址。DAA与CBW是隐含寻址,因为操作数隐含在AL与AX中。HLT为无操作数指令,所以不存在操作数寻址问题。INT n为中断向量寻址,这种寻址方式是通过中断向量号寻找到操作数的。RET为堆栈寻址,返回的断点地址是通过SP和堆栈实现的。CLC为标志位寻址,指令是针对标志位操作的。分析某一指令到底为何种寻址方式,要看操作数在什么地方,如何寻到源操作数和目的操作数。寻找操作数的方式就称为寻址方式。
例3.2 若AX=0ABCDH,BX=7F8FH,CF=1。求分别执行8086 CPU指令
①ADD AX,BX
②ADC AX,BX
③SBB AX,BX
④NEG AX
⑤AND AX,BX
⑥OR AX,BX
⑦XOR AX,BX
⑧IMUL BL后,AX寄存器中的内容,并指出标志寄存器SF、ZF、AF、PF、CF及OF的状态。
解
①AX=2B5CH,SZAPCO=001110B
②AX=2B5DH,SZAPCO=001010B
③AX=2C3DH,SZAPCO=001001B
④AX=5433H,SZAPCO=001110B
⑤AX=2B8DH,SZAPCO=00×100B
⑥AX=FFCFH,SZAPCO=10×100B
⑦AX=D442H,SZAPCO=10×100B
⑧AX=1683H,SZAPCO=××××11B
讨论
计算机中的算术与逻辑运算若不特殊说明,都是按照二进制进行的。源操作数和目的操作数运算后,结果在目的操作数中,源操作数不变。所以执行后,寄存器BX中的内容都不变。ADC、SBB指令运算时还要考虑上次进位CF的情况。算术与逻辑运算指令对状态标志位都有影响,加减指令对6个状态标志位都有影响,而逻辑指令只影响SF、ZF、PF这3个标志位,不影响AF,CF与OF总是0。要注意,PF仅与低8位运算结果有关,而与高8位运算结果无关,AF仅与低4位运算结果有关。
8086指令系统中有许多指令执行后影响标志位,其中主要的有算术运算指令(加、减、乘、增量、减量、十进制调整)、逻辑运算指令(与、或、异或、测试、算术逻辑移位、循环移位);此外还有字符串比较与搜索指令(CMPS、SCAS)、具有恢复状态标志功能的指令(POPF、IRET、SAHF)、设置进位标志指令(STC、CLC、CMC)。其他类型的指令(传送类、程序控制类)对标志位不影响。算术逻辑运算中的除法与逻辑非(DIV、IDIV、NOT)也不影响标志位。
例3.3 若AX=FFF8H,BX=FFFAH,求执行指令IMUL、BX后,DX与AX中的内容,并指出标志位OF与CF的状态。
解
AX=0030H,DX=0000,OF=CF=0。
讨论
本题是带符号数乘法,答案很简单。乘法指令不论是8位×8位,还是16位×16位,都规定一个操作数默认在累加器AL或AX中,而另一个操作数可以在寄存器或存储器中,乘积在AX(8位×8位)或DX与AX(16位×16位)中。本题中的两个操作数若看作无符号数,则数值都很大,但若看作符号数,则数值都不大,AX=FFF8H,AX的值为-8,BX=FFFAH,BX的值为-6,所以(-8)×(-6)为48(=30H)。于是,乘积的高16位为DX=0000H,乘积的低16位为DX=0030H。对于乘法指令只有两个标志位OF与CF受影响,OF与CF在这里并不表示溢出与进位。若OF=CF=0,只表示乘积的高一半是乘积低一半符号位的扩展(无符号数乘法表示积的高一半为0);若OF=CF=1,表示AH或DX的内容是积的有效数字。
除法指令与乘法指令有些类似,被除数默认在累加器AX(16位除以8位)或DX与AX(32位除以16位)中,除数在寄存器或存储器中,除法指令的标志位不确定。
例3.4 若AL=78H,BL=87H:
①求执行指令
之后AL=?标志位AF=?CF=?并说明BCD码调整情况。
②执行指令
后情况又如何?
解
①AL=65H,AF=1,CF=1。
执行“ADD AL,BL”后,AL=FFH,显然,FFH是二进制数,不是BCD码,要把FFH变成BCD码,就要对FFH进行调整。DAA指令正是对二进制加法结果进行BCD调整的专用指令。因为FFH的高位F与低位F都是大于9的数,所以执行DAA指令时,FFH要加上66进行调整,最后结果为AL=65H,AF=1,CF=1。
②AL=91H,AF=0,CF=1。
执行指令“SUB AL,BL”后,AL=F1H,显然,F1H是二进制数,不是BCD码,要把F1H变成BCD码,就要对F1H进行调整。DAS指令正是对二进制减法结果进行BCD调整的专用指令。因为F1H的高位大于9,所以要减6调整,而低位1是小于9的数且AF=0,所以不要调整。执行DAS指令时,F1H要减去60进行调整,最后结果为AL=91H,AF=0,CF=1。
讨论
计算机在进行加减运算时,全部是按照二进制数进行运算的,而人们习惯于十进制数,所以要把二进制数变成十进制数(BCD码表示的数),就需要进行转换。计算机一般都设有对二进制加减后的十进制调整指令,即DAA与DAS。计算机的算术逻辑单元中专门有一个十进制调整部件。标志寄存器中的AF标志位也是专门为十进制加减调整指令DAA与DAS而设置的。
BCD码加法调整原则是:
①如果标志位AF=1,或AL寄存器的低4位大于9,则AL加06H,并置AF=1;
②如果标志位CF=1,或AL寄存器的高4位大于9,则AL加60H,并置CF=1;
③如果满足上述两条,则AL加66H,并置AF=1,CF=1。
BCD码减法调整原则与上述加法调整原则类似,只不过是把加06H、60H、66H换成减去06H、60H、66H罢了。
DAA与DAS是对组合的BCD码进行加减调整的指令,而AAA与AAS是对未组合的BCD码进行加减调整的指令。
例3.5 若一个4字节数放在寄存器BX间址的内存中(低地址对应低字节),要求这个4字节数整个左移一位如何实现?右移一位又如何实现?(www.daowen.com)
解
①4字节数整个左移一位:
或者
或者
讨论
一个多字节数整个左移或者右移一位,要把这个数作为一个整体考虑。4字节数左移一位时要先从低16位向左移,低16位的最高位移到CF中;接着要用大循环RCL左移高16位,这样就把CF中的值移到了高16位的最低位。右移一位时正好相反,要先从高16位向右移,接着用RCR向右移低16位。
如果是8字节的数存放在内存中的话,要把这8字节的数左移或者右移一位将如何实现?读者可以在机器上试一试。
例3.6 若SS=1652H,SP=2100H,AX=1234H,BX=5678H,FR=2115H,试说明执行指令
之后,SP=?SS=?CX=?DX=?并画出表指出栈中各单元的内容。
解
SS=1652H,SP=20FEH,CX=2115H,DX=5678H。
栈中的各个单元内容如表3.1所示。
表3.1 栈中各个单元内容
讨论
堆栈操作不管是压入还是弹出,每次都是16位数据,栈指针SP每次加2或者减2,如果压入n次再弹出n次,则SP保持不变。压入时,先调整栈指针,即SP-1,再压入高8位;再调整栈指针SP-1,压入低8位。弹出时正好相反,先弹出数据,再调整栈指针。SP始终指向栈顶的位置。
例3.7 把2 KB的数据块从偏移地址以2000H开始的单元传送到偏移地址以2100H开始的缓冲区(注意地址有重叠)。试用串操作指令和一般传送指令两种方法各编一程序实现。
解
①利用串操作指令编程如下:
②利用一般传送指令编程如下:
讨论
要传送、填充、检索一个数据块,用串操作指令更方便,执行速度会更快。在用串操作指令之前,要把准备工作做好,即把源操作数地址传送给SI,目的操作数地址传送给DI,操作的次数传送给CX,地址增量或减量用指令CLD或STD设置,这样就可以用重复串操作指令执行了。本题因为有重复地址,所以从最后一个单元开始传送,保证数据不会丢失。
例3.8 分别编一程序使:
①AX寄存器高3位清零;
②BX寄存器高3位置1;
③CX寄存器高4位变反;
④DX寄存器高3位不变,其余位清零。
解
讨论
逻辑运算指令可以使某些位置1,某些位清零,某些位变反。本题的答案不是唯一的,可以用多种办法完成上述要求。
用逻辑运算指令AND、OR、XOR、TEST还可以改变某些标志位,然后用条件转移指令JCC可以根据标志位把程序转移到所需要的地方。
例3.9 下列8086指令中哪些是错误的,错在何处?
①MOV DL,[DX]
②MOV ES,2000H
③SUB[BX],[SI]
④ADD AX,[BX+CX]
⑤XCHG DS,[2400H]
⑥DEC ES
⑦IN AL,DX
⑧OUT 1C0H,AX
解
①错,DX不能作为间接寻址的寄存器。
②错,立即数不能直接送给段寄存器。
③错,两个存储单元间内容不能直接相减。
④错,CX寄存器不能作为变址寄存器。
⑤错,不允许段寄存器与存储单元内容进行交换。
⑥错,减1指令不能对段寄存器直接进行操作。
⑦对。
⑧错,输出指令的口地址是16位的,必须用DX间址。
例3.10 在指令“CMP AH,BH”后面紧跟一条JCC NEXT条件转移指令,其中条件CC可以是B、NB、BE、NBE、L、NL、LE、NLE中的任一个,如果AH和BH的内容如下:
对每一组AH与BH数据,使用哪几种CC的转移指令将引起程序转移到NEXT?
解
①若把95H和55H看成无符号数,则前者高于后者,所以CC可取NB、NBE;若把它们看成符号数,则前者小于后者,前者为负数,后者为正数,所以CC可取L和LE。同理,对于后面的几组数据都要用两种情况(即作为无符号数和符号数)来判断。
②CC可取B、BE、L、LE。
③CC可取NB、NBE、NL、NLE。
④CC可取B、BE、NL、NLE。
⑤CC可取NB、BE、NL、LE。
例3.11 若起始地址偏移量为2000H的内存单元存放着100个ASCII码字符,现给这些字符添加奇偶校验位(bit7),使每个字符中“1”的个数为偶数,再顺序输出到地址为100H的端口。
解
例3.12 连续执行以下指令,填写执行指令的结果(MEM为存储器物理地址)。
解
答案在题目中。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。