《微型计算机原理及应用》课件第4章_第1页
《微型计算机原理及应用》课件第4章_第2页
《微型计算机原理及应用》课件第4章_第3页
《微型计算机原理及应用》课件第4章_第4页
《微型计算机原理及应用》课件第4章_第5页
已阅读5页,还剩218页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章8086/8088寻址方式与指令系统4.18086/8088微型机的指令格式4.2微型机指令的寻址方式4.38086/8088指令系统本章小结本章学习目标

●了解指令及指令系统

●明确指令格式和指令的寻址方式

●掌握常用指令的格式及功能

●能将简单问题转化为指令序列表示

计算机是通过执行指令序列解决问题的。每种类型的计算机都具有一组指令集供用户使用,这组指令集称为计算机的机器指令系统,简称指令系统。本章介绍80X86的指令系统。4.18086/8088微型机的指令格式计算机的指令由操作码和操作数两部分组成。操作码指出计算机所要执行的操作,即完成何种功能。操作数则指出指令完成功能操作过程中所需要的数据。操作数可以是数值,也可以是操作数的地址或地址的一部分,还可以是指向操作数地址的指针或其它有关操作数的信息。

指令的格式一般如下:

指令的操作码在机器中的表示比较简单,只需要对每一种操作指定确定的二进制代码。指令中的操作数比较复杂。

操作数可以有一个、二个或三个,对应地称为一地址、二地址或三地址指令。如一个操作数,即单操作数指令是一地址指令。三地址指令中,给出参加运算的两个操作数,还给出运算结果的存放地址。二地址指令中,分别称两个操作数为源操作数和目的操作数,一般情况下,在操作码后的第一个操作数为目的操作数,第二个操作数为源操作数。在执行指令前这两个操作数都是输入,当执行指令后将把运算结果存放到目的操作数的地址之中。即参加运算的一个操作数被改变了,而另一个操作数——源操作数不变。

操作数存放的位置不同,指定操作数的地址不同。如果操作数存放在寄存器中,则由于寄存器的数量较少,因此所需要指定操作数的地址的位数就较少;如果操作数存放在存储器中,那么要指定存储器一个单元的地址是20位(8088/8086)或32位(80386及后继机型),所需要指定操作数地址的位数就较多。用什么方式指定操作数的地址会更方便程序的处理呢?这就涉及指令的寻址方式,它会影响计算机的运行速度和效率。因为计算机只识别二进制代码,所以指令系统都是由二进制代码组成的,这不易记忆和书写。因此人们使用符号语言编写程序,这种符号语言称为汇编语言,它用助记符(帮助记忆的符号)表示操作码,用符号或符号地址表示操作数或操作数的地址,且与机器指令一一对应。这样在介绍指令时,即可用汇编语言来表示指令,而不是用二进制代码。汇编指令的一般格式是:

[名字:]<助记符>[操作数1,操作数2,操作数3][;注释]

名字和冒号组成标号,二者缺一不可。标号是符号地址,表示该条指令所在段的偏移地址。有关名字的规定在5.1.2节中介绍。标号为可选项。

分号和注释对指令的执行不起任何作用,只是为阅读程序或指令方便而写。有注释必须有分号,分号后的注释可为任何字符和数字。该项为可选项。注意,有用的指令前不能加分号。

上述的汇编语言指令必须翻译成机器语言(又称为目标语言)指令,即用二进制码表示的操作码和操作数才能被机器接受,标号只在翻译过程中用到,分号和注释在翻译时被去掉。将汇编语言编写的程序翻译成机器语言程序的过程称为汇编,起翻译作用的程序称为汇编程序,它是一种系统程序。

指令的寻址方式分为两种:一种是与数据有关的寻址方式;一种是与转移地址有关的寻址方式。本节只介绍与数据有关的寻址方式。在80X86系列中,8088/8086的字长为16位,一般情况只处理8位和16位数据。根据操作数存放位置的不同,有以下几种寻址方式。4.2微型机指令的寻址方式4.2.1立即寻址

在立即寻址(ImmediateAddressing)方式中,操作数直接包含在指令中。它紧跟在操作码的后面,与操作码一起放在代码段区域中,如图4.1所示。

例:MOVAX,im

立即数im可以是8位的,也可以是16位的。若是16位的,则imL在低地址字节,imH在高地址字节。

图4.1立即寻址4.2.2寄存器寻址

在寄存器寻址(RegisterAddressing)方式中,操作数包含在CPU的内部寄存器中,如AX、BX、CX、DX、DS、SI等,如图4.2所示。

例:MOVAX,DX

由于结构上的原因,使用AX存放结果,通常指令执行时间要短一些。

图4.2寄存器寻址4.2.3存储器寻址

当数据存放在存储器中时,可用的寻找数据的方式很多。对于某一数据,可用下面的几种寻找方式。根据数据的结构不同,灵活运用下列方式,会方便数据的存取。

1.直接寻址(DirectAddressing)

在这种寻址方式中,操作数地址的16位段内偏移地址直接包含在指令中,它与操作码一起存放在代码段区域。操作数一般在数据段区域中,它的地址为数据段寄存器DS加上这16位的段内偏移地址,如图4.3所示。

图4.3直接寻址

例:设(DS)=3000H

MOVAX,[2000H]

指令中的16位段内偏移地址的低字节在前,高字节在后。这种寻址方法以数据段的段地址为基础,故可在多达64KB的范围内寻找操作数。

本例中,取数的物理地址就是:DS的内容×16(即左移4位),变为20位,再在其低端16位上加上偏移地址2000H。偏移地址2000H是由指令直接给出的。

也可用符号地址,如果DISP=2000H,则MOVAL,DISP与MOVAX,[2000H]是等价的。

2.寄存器间接寻址(RegisterIndirectAddressing)

在这种寻址方式中,操作数存放在存储器中,操作数的16位段内偏移地址放在SI、DI、BP、BX4个寄存器中的一个内。由于上述4个寄存器默认的段寄存器不同,这样又可以分成三种情况:

(1)若以SI、DI、BX进行间接寻址,则操作数通常存放在现行数据段中。此时数据段寄存器内容加上SI、DI、BX中的16位段内偏移地址,即得操作数的地址,如图4.4所示。

例:设(DS)=3000H,(SI)=1000H

MOVAX,[SI]

则物理地址为31000H。

图4.4寄存器间接寻址

(2)若以寄存器BP进行间接寻址,则操作数存放在堆栈段区域中。此时堆栈段寄存器内容加上BP中的16位段内偏移地址即得操作数的地址,如图4.5所示。

例:设(SS)=3000H,(BP)=1000H

MOVAX,[BP]

则物理地址为31000H。

图4.5BP寄存器间接寻址

(3)若要改变上述寻址段的默认方式,则可用段超越符。

例:MOVAX,ES:[SI]

MOVAX,CS:[BP]

例中以SI进行间接寻址的操作数暂时改在附加数据段,而以BP间接寻址的操作数暂时改在代码段。物理地址的计算分别要用到ES和CS的值。

这种寻址方式可用于表格数据的处理,执行完一条指令后,只需修改寄存器的内容就可取出表格的下一个数据。

3.寄存器相对寻址(RegisterRelativeAddressing)

在这种寻址方式中,操作数存放在存储器中。操作数的地址是由段寄存器内容加上SI、DI、BX、BP之一的内容,再加上由指令中所指出的8位或16位相对地址偏移量而得到的,如图4.6所示。

在一般情况下,用SI、DI或BX进行相对寻址时,以数据段寄存器DS作为地址基准;而用BP寻址时,则以堆栈段寄存器作为地址基准。

图4.6寄存器相对寻址

例:设(DS)=2000H,(SI)=1000H,DISP=1000H,

MOVAX,DISP[SI]或MOVAX,[SI+DISP]

则物理地址为22000H。

这种寻址方式也可用于表格数据的处理,表格首地址为位移量(DISP),利用修改基址或变址寄存器的内容就可取得表格中的数据。

4.基址变址寻址(BasedIndexedAddressing)

在这种寻址方式中,8088/8086通常把BX和BP作为基址寄存器,而把SI、DI作为变址寄存器。将这两种寄存器联合起来进行的寻址就称为基址变址寻址。这时,操作数的地址应该是通过段寄存器内容加上基址寄存器内容(BX或BP内容),再加上变址寄存器内容(SI或DI内容)而得到的,如图4.7所示。

同理,若用BX作为基地址,则操作数应放在数据段DS区域中;若用BP作为基地址,则操作数应放在堆栈段SS区域中。

图4.7基址变址寻址

例:设(DS)=3000H,(SI)=1000H,(BX)=1000H

MOVAX,[BX][SI]或MOVAX,[BX+SI]

则物理地址为32000H。

这种寻址方式用于数组或表格数据的处理。将数组或表格的首地址放在基址寄存器中,用变址寄存器访问数组中各元素。由于两个寄存器都可修改,因此它比寄存器相对寻址方式更灵活。

5.基址变址相对寻址(RelativeBasedIndexedAddressing)

在这种寻址方式中,操作数的地址是由基址变址方式得到的地址再加上由指令指明的8位或16位的相对偏移地址而得到的。这种方式实际上是存储器操作数寻址的一般形式,以上4种方式都是其特例,如图4.8所示。

图4.8基址变址相对寻址

例:设(DS)=3000H,(SI)=1000H,(BX)=2000H,DISP=200H

MOVAX,DISP[BX][SI]或MOVAX,[BX+SI+DISP]

则物理地址为33200H。

这种寻址方式用于堆栈数据的处理。一般BP寄存器指向栈顶,从栈顶到数组的首地址可用位移量表示,变址寄存器可用于访问数组中的某个元素。4.2.4隐含寻址

在有些指令的指令码中,不仅包含有操作码信息,而且还隐含了操作数地址的信息。例如乘法指令MUL的指令码中只需指明一个乘数的地址,另一个乘数和积的地址是隐含固定的。这种将操作数的地址隐含在指令操作码中的寻址方式就称为隐含寻址(HideAddressing)。

例:MULBL

一个乘数存放在BL中,另一个乘数固定存放在AL中,结果积固定存放到AX中。4.2.5I/O端口寻址

当数据存放在外部设备中,就为I/O端口寻址(PortI/OAddressing)。由于80X86的I/O端口(与外部设备连接)采用独立于内存的编址方式,因此需要有独立的指令。

1.输入指令

INAL/AX,PORT

INAL/AX,DX

指令所执行的操作是将外部设备接口地址中的字节或字数据送到累加器AL或AX。

当计算机从外部设备读取数据时,用输入指令。PORT为8b外部设备的接口地址,当外部设备的接口地址多于8b时,要将该地址送到寄存器DX中。80X86的外部设备接口地址为16b,按字节编址为64KB,按字编址为32K字。

例:INAL,60H

将外部设备接口地址60H中的字节送到累加器AL。

例:INAX,60H

将外部设备接口地址60H中的字送到累加器AX。即60H中的字节送AL,61H中的字节送AH。

2.输出指令

OUTPORT,AL/AX

OUTDX,AL/AX

指令所执行的操作是将计算机中的字节或字数据通过外累加器AL或AX送到接口地址决定的外部设备中。

当计算机向外部设备写数据时,用输出指令。关于外部设备的接口地址的规定同输入指令。

例:MOVDX,450H

OUTDX,AL

将AL的内容送到接口地址为450H的外部设备中。

例:MOVDX,450H

OUTDX,AX

将AX的内容送到接口地址为450H的外部设备中。这里AL送接口地址450H,AH送接口地址451H。

由此可见,外部设备和计算机交换数据只有两条指令,相当于存储器的传送指令。

80X86的指令按功能可分为数据传送指令、算术运算指令、逻辑运算和移位指令、控制转移指令、串处理指令及处理机控制指令。4.38086/8088指令系统4.3.1数据传送指令

数据传送指令负责将数据、地址或立即数传送到寄存器或存储单元中。它又可分为通用数据传送指令、地址传送指令和标志寄存器传送指令。

1.通用数据传送指令

MOV(Move) 传送指令

PUSH(Pushontothestack) 进栈指令

POP(Popfromthestack) 出栈指令

XCHG(Exchange) 交换指令

XLAT(Translate) 换码指令

1)传送指令(MOV)

汇编格式:MOVDST,SRC

执行的操作:(DST)←(SRC)

其中,DST表示目的操作数,SRC表示源操作数。

MOV指令传送的数据可以是字或字节,但SRC与DST的数据类型必须一致,即同为字节或同为字。MOV指令的传送方向有着严格规定,如图4.9所示,从寄存器到寄存器,立即数到寄存器,立即数到存储单元,存储单元到寄存器,寄存器到存储单元,寄存器或存储单元到除CS外的段寄存器,段寄存器到寄存器或存储单元。

图4.9MOV指令的传送方向由图4.9可知,立即数不能直接送段寄存器;MOV指令的目的操作数不允许用立即数,也不允许用CS寄存器;而且不允许用MOV指令在两个存储单元之间直接传送,也不允许在两个段寄存器之间直接传送。MOV指令不影响标志位。立即数不能直接送段寄存器,但可通过寄存器传送,例如:

MOVAX,DATASEG ;设DATASEG为 某数据段段名

MOVDS,AX ;数据段段基值送 入DS

当不能确定存储单元存放的数据类型时,可用属性操作符(PTR)指明,例如:

MOVBYTEPTR[2000H],0 ;将(2000H)←0, 是字节操作

MOVWORDPTR[2000H],0 ;将(2001H)←0, (2000H)←0,是字操作存储单元之间也不能直接传送。若ADDR为某16位数据的段内偏移地址,要把该数据复制到与它相邻的下一个字节单元,则必须通过通用寄存器分两次传送,例如:

MOVAL,ADDR ;源操作数为直接 地址

MOVADDR+1,AL ;寄存器送直接地址

或者可用下列指令完成:

MOVSI,OFFSETADDR ;段内偏移地址送入SI

MOVAL,[SI] ;寄存器间接寻址

MOV[SI+1],AL ;[SI+1]的另一种表达方 式是1[SI]其中,第一条指令把ADDR的偏移地址(而不是内容)送到SI寄存器。OFFSET为属性操作符,意为把其后符号的段内偏移地址(不是内容)作为源操作数。

若要实现两个存储单元之间的数据交换,可用下述指令实现:

MOVAX,AR1 ;AR1为一个存储单元地址,直 接地址

MOVBX,AR2 ;AR2为另一个存储单元地址, 直接地址

MOVAR1,BX

MOVAR2,AX

2)进栈指令(PUSH)

汇编格式:PUSHSRC

执行的操作:(SP)←(SP)-2,((SP)+1和(SP))←(SRC)

3)出栈指令(POP)

汇编格式:POPDST

执行的操作:(DST)←((SP)+1和(SP)),(SP)←(SP)+2

PUSH和POP是两条堆栈操作指令。堆栈是以“后进先出”方式工作的一个存储区,位于堆栈段中(必须由段寄存器SS指定)。它只有一个出入口(栈顶),由堆栈指针寄存器SP指示。SP的内容在任何时候都指向当前的栈顶。堆栈是由高地址向低地址生长的,即进栈操作应使SP内容减小,出栈操作应使SP内容增加。PUSH和POP指令都必须根据当前SP的内容来确定进栈或出栈的存储单元,而且必须及时修改指针,以保证SP指向当前的栈顶。堆栈的存取必须以字为单位(PC机不允许字节堆栈),所以PUSH和POP指令只能作字操作。它们可以使用除立即数以外的其它寻址方式。PUSH指令中的SRC和POP指令中的DST也可以指定段寄存器作为操作数,但POP指令不允许用CS寄存器。这两条堆栈指令不影响标志位。

设(SS)=4000H,(SP)=1126H,(AX)=0714H,执行PUSHAX的情况如图4.10所示。

设(SS)=4000H,(SP)=1124H,执行POPBX的情况如图4.11所示。

图4.10PUSH指令执行情况

图4.11POP指令执行情况实现两个存储单元AR1与AR2之间数据的互换又可用下述堆栈操作程序段实现:

PUSHAR1

PUSHAR2

POPAR1

POPAR2

堆栈在子程序调用和中断调用中起着重要的作用,如果子程序(或中断服务程序)要使用某些寄存器,就可以先将这些寄存器的内容保存在堆栈中,待子程序(或中断服务程序)执行完毕后再将寄存器原来的内容恢复。需要注意的是,由于堆栈“后进先出”的特点,PUSH与POP指令操作对象的先后次序必须相反。例如:

PUSHAX

PUSHCX

…;子程序要用到AX和CX寄存器

POPCX

POPAX

4)交换指令(XCHG)

汇编格式:XCHGOPR1,OPR2

执行的操作:(OPR1)(OPR2)

OPR1和OPR2表示操作数。该指令的两个操作必须有一个在寄存器中,因此,它可以在寄存器之间或者在寄存器和存储器之间交换信息,但不允许使用立即数或段寄存器。指令允许字或字节操作,且不影响标志位。

要实现两个通用寄存器内容的互换,例如AX与CX的互换,可使用指令:

XCHGAX,CX

实现两个存储单元AR1与AR2之间的数据互换,可使用下列指令序列:

XCHGAX,AR1

XCHGAX,AR2

XCHGAX,AR1

5)换码指令(XLAT)

汇编格式:XLATOPR或XLAT

执行的操作:(AL)←((BX)+(AL))

程序中经常需要把一种代码转换为另一种代码。例如把字符的扫描码转换成ASCII码,或者把数字0~9转换成七段数码管所需要的相应字形代码等,XLAT就是为这种用途所设置的指令。在使用这条指令以前,应先建立一个字节表格,将表格的首地址存入BX寄存器中,将需要转换的代码(应该是相对于表格首地址的位移量)存放在AL寄存器中,这时表格的内容则是所要换取的代码,该指令执行后就可在AL中得到转换后的代码。该指令可用以上两种格式中的任一种。使用XLATOPR时,OPR只是为提高程序的可读性而设置的(OPR为表格的首地址),在指令执行时只使用预先已存入BX中的表格首地址,而并不用汇编格式中指定的值。该指令不影响标志位。

例如,在数据区中TABLE开始的存储区顺序存放着A~Z的ASCII码,下列程序段将把字母从0开始的存放顺序号变为对应字母的ASCII码值。

TABLEDB‘ABCDE…Z’ ;单引号和数字一 定为英文字符

MOVBX,OFFSETTABLE

MOVAL,3 ;从0开始第三个 字母为“C”

XLAT

其中,DB伪指令表示其后存放的数据均为字节。XLAT执行完毕后,AL中的内容为字母C的ASCII码(43H)。

须注意,由于AL寄存器只有8位,因此表格的长度不能超过256。

2.地址传送指令

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

LDS(LoadDSwithPointer)指针送寄存器和DS指令

LES(LoadESwithPointer)指针送寄存器和ES指令

这组指令的功能是将地址送到指定寄存器中。

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

汇编格式:LEAREG,SRC

执行的操作:(REG)←SRC

该指令源操作数SRC必须是内存操作数,目的操作数必须是16位的通用寄存器。LEA指令对标志寄存器的各位均无影响。

设符号地址ABC代表数据段内偏移地址为1234H的存储单元地址,该单元存放的数据为5678H。

LEABX,ABC或MOVBX,OFFSETABC执行后,(BX)=1234H,而

MOVBX,ABC

执行后,(BX)=5678H。

指令LEABX,ABC与MOVBX,OFFSETABC的功能完全相同。在程序中常用它们将数组和表格的首地址装入某个基址寄存器,然后用基址寻址、基址变址等寻址方式访问数组或表格中的元素。例如,要将字数组ARRY的第2个元素与第5个元素对换,可用下列程序段实现:

LEABX,ARRY

XCHGAX,2[BX]

XCHGAX,8[BX]

XCHGAX,2[BX]

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

汇编格式:LDSREG,SRC

执行的操作:(REG)←(SRC),(DS)←(SRC+2)

该指令把源操作数SRC指定的4个相继字节的地址指针中的段内偏移地址(低字)送到由指令指定的寄存器REG,将段基址(高字)送到DS寄存器中。该指令中的REG常特指定为SI寄存器(配合后面介绍的串操作指令)。由于内存单元的物理地址是由16位的段基址和16位的段内偏移地址组成的,因而,一个存储单元的地址指针应包括段基址和段内偏移地址,共4个字节32位,上面指令的作用是同时将段基址和段内偏移地址装入指令中指定的段寄存器和指定的寄存器。指令中的SRC指明地址指针在内存中的存放处。其中,SRC的低16位存放段内偏移地址,SRC的高16位(SRC+2单元)存放段基址。

例如,指令LDSSI,[BX]的功能相当于下述三条指令:

MOVSI,[BX]

MOVAX,2[BX]

MOVDS,AX

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

汇编格式:LESREG,SRC

执行的操作:(REG)←(SRC),(ES)←(SRC+2)

该指令把源操作数SRC指定的4个相继字节的地址指针中的段内偏移地址(低字)送到由指令指定的寄存器REG中,将段基址(高字)送到ES寄存器中。该指令中的REG常特指定为DI寄存器(配合后面介绍的串操作指令)。

例如,指令LESDI,ABC的功能相当于下述三条指令:

MOVDI,ABC

MOVAX,ABC+2

MOVES,AX以上两条指令LDS和LES指定的寄存器不能使用段寄存器,且源操作数SRC为任何一种存储器寻址方式。指令执行不影响标志位。

这两条指令常用于处理不在当前数据段和附加段的字符串数据。由于源串隐含使用

DS:SI,目的串隐含使用ES:DI,因此只要设置好待处理的字符串所在的段基址和段内偏移地址即可(详见4.3.5节串操作指令的介绍)。

3.标志寄存器传送指令

LAHF(LoadAHfromFlag) 标志寄存器送AH寄存器 指令

SAHF(StoreAHintoFlag) AH寄存器送标志寄存器 指令

PUSHF(PushtheFlag) 标志寄存器进栈指令

POPF(PoptheFlag) 标志寄存器出栈指令

这四条指令的操作数均采用隐含表示(PSW、AH、堆栈),在指令形式上是无操作数指令。

标志寄存器PSW的定义如图4.12所示。

图4.12标志寄存器PSW

1)标志寄存器送AH寄存器指令(LAHF)

汇编格式:LAHF

执行的操作:(AH)←(PSW的低字节)

2)

AH寄存器送标志寄存器指令(SAHF)

汇编格式:SAHF

执行的操作:(PSW的低字节)←(AH)

3)标志寄存器进栈指令(PUSHF)

汇编格式:PUSHF

执行的操作:(SP)←(SP)-2,((SP)+1和(SP))←(PSW)

4)标志寄存器出栈指令(POPF)

汇编格式:POPF

执行的操作:(PSW)←((SP)+1和(SP)),(SP)←(SP)+2

PC的指令系统中设有几条专门的指令,可对PSW中的CF、DF、IF位直接进行置“1”、清“0”等操作。其他标志位则不能直接用指令进行修改。若要对其进行修改,如对ZF清“0”,则可用下列程序段:

LAHF

ANDAH,0BFH;将AH第6位清“0”,字符开头的 数据前面加“0”

SAHF ;ZF位被清“0”

这四条指令中,LAHF和PUSHF不影响标志位,SAHF和POPF则由装入的值来确定标志位的值。

传送类指令中还包括输入/输出专用指令,如输入指令IN(Input)和输出指令OUT(Output)。

在PC机里,所有I/O端口与CPU之间的通信都由IN和OUT指令实现,由IN完成从I/O端口到CPU的信息传送,由OUT完成从CPU到I/O端口的信息传送。4.3.2算术运算指令

算术运算指令主要包括加法、减法、乘法和除法四则运算,数据类型转换及十进制数调整类指令。

1.加、减法指令

ADD(Add) 加法指令

ADC(AddwithCarry) 带进位加法指令

INC(Increment) 加1指令

SUB(Subtract) 减法指令

SBB(SubtractwithBorrow) 带借位减法指令

DEC(Decrement) 减1指令

NEG(Negate) 求补指令

CMP(Compare) 比较指令

1)加法指令(ADD)

汇编格式:ADDDST,SRC

执行的操作:(DST)←(DST)+(SRC)

2)带进位加法指令(ADC)

汇编格式:ADCDST,SRC

执行的操作:(DST)←(SRC)+(DST)+CF(其中,CF为进位位的值)

3)加1指令(INC)

汇编格式:INCOPR

执行的操作:(OPR)←(OPR)+1

4)减法指令(SUB)

汇编格式:SUBDST,SRC

执行的操作:(DST)←(DST)-(SRC)

5)带借位减法指令(SBB)

汇编格式:SBBDST,SRC

执行的操作:(DST)←(DST)-(SRC)-CF(其中,CF为进位位的值)

6)减1指令(DEC)

汇编格式:DECOPR

执行的操作:(OPR)←(OPR)–1

7)求补指令(NEG)

汇编格式:NEGOPR

执行的操作:(OPR)←(0-OPR)

8)比较指令(CMP)

汇编格式:CMPOPR1,OPR2

执行的操作:(OPR1)-(OPR2)

CMP指令与SUB指令一样可执行减法操作,但它并不保存差,只是根据结果设置标志位。CMP指令后往往跟着条件转移指令,根据比较结果转向不同的程序段。

除INC和DEC指令不影响CF标志位外,上述其它指令都影响标志位。条件标志(或称条件码)中最主要的是CF、ZF、SF、OF四位。CF表示进位(或借位),ZF表示结果为零,SF表示符号位,OF表示带符号数的溢出。进行加法运算时,若两个操作数的符号相同,而结果和的符号与之相反时,则OF=1,否则OF=0。OF=1,说明加法溢出。CF位反映无符号数最高位是否有进位。有进位时CF=1,无进位时CF=0,即CF中保留的是有模运算中自动丢失的“1”。

进行减法运算时,若被减数与减数符号相反,而结果差的符号与减数相同时,则OF=1;若结果差的符号与被减数相同,则OF=0。OF=1,说明减法溢出。CF值反映无符号数相减时是否有借位。若减数大于被减数,则有借位,CF=1,否则CF=0。

NEG指令只有当操作数为0时,操作后才使CF=0,其它情况CF均为1。

在多字长数据运算时,必须考虑CF中保存的进位(或借位)值。

例4.1

若内存中有两个32位的操作数x和y,存放在地址偏移从AREA开始的连续存储单元中,求(x)+(y)→(X+64)和(x)-(y)→(X+96)的程序段。

(x)+(y)→(X+64)的程序段为:

LEA BX,AREA ;BX指向x低字

MOV AX,[BX] ;x低字送入AX

ADD AX,4[BX] ;与y低字相加

MOV 64[BX],AX ;送和低字

INC BX

INC BX ;BX指向x高字

MOV AX,[BX] ;x高字送入AX

ADC AX,6[BX] ;与y高字及低字进位相加

MOV 80[BX],AX ;送和高字

为实现双精度加法,必须用两条指令分别完成低位字和高位字的加法,在高位字相加时,应该使用ADC指令把前一条ADD指令所产生的进位值加入高位字之内。由于MOV指令和INC指令均不改变进位CF的值,因此ADD指令产生的进位CF,一直保留到ADC指令执行之时。

(x)-(y)→(X+96)的程序段为:

LEA BX,AREA ;BX指向x低字

MOV AX,[BX] ;x低字送入AX

SUB AX,4[BX] ;减去y低字

MOV 96[BX],AX ;送差低字

MOV AX,2[BX] ;x高字送入AX

SBB AX,6[BX] ;减去y高字及借位

MOV 112[BX],AX ;送差高字

例4.2

若内存中32位的操作数x的存放地址为X,求-x。

LEA BX,X ;BX指向x的低字地址, X为x的首地址

NEG WORDPTR2[BX] ;x高字按位取反,末位 加1

NEG WORDPTR[BX] ;x低字按位取反,末位 加1

SBB WORDPTR2[BX],0 ;将低字求补产生 的进位从高字求补 中减去,;若操作数≠0,则NEG指令取补后CF=1;若操作数=0,则NEG指令取补后CF=0。

上述程序段先将x的高位字按位取反,末位加1。按位取反是必须的,末位加1是否恰当呢?可分两种情况予以讨论。

若x低位字不等于0,显然x高位字只需按位取反,而不能末位加1。x低位字不等于0,指令“NEGWORDPTR[BX]”执行后,CF=1,当“SBBWORDPTR2[BX],0”执行后,恰好将高位字多加的1减去,因此,结果是正确的。

若x低位字等于0,根据求补规则x高位字应当按位取反,末位加1。x低位字等于0,指令“NEGWORDPTR[BX]”执行后,CF=0,因此“SBBWORDPTR2[BX],0”不会对高位字的求补结果产生任何影响,因此结果也是正确的。

2.乘、除法类指令

MUL(UnsignedMuleiple) 无符号数乘法指令

IMUL(SignedMultiple) 带符号数乘法指令

DIV(UnsignedDivide) 无符号数除法指令

IDIV(SignedDivide) 带符号数除法指令

另外,与除法指令相关的还有两条符号扩展指令:

CBW(ConvertBytetoWord)字节转换为字指令

CWD(ConvertWordtoDoubleWord)字转换为双字指令

1)无符号数乘法指令(MUL)

汇编格式:MULSRC

执行的操作:(AX)←(AL)×(SRC) (字节操作数)

(DX,AX)←(AX)×(SRC) (字操作数)

2)带符号数乘法指令(IMUL)

汇编格式:IMULSRC

执行的操作:与MUL相同,但必须是带符号数,而MUL是无符号数。

在乘法指令里,被乘数由累加器隐含指定,字运算为AX,字节运算为AL,乘数由SRC指定。两个8位数相乘得到的16位乘积隐含存放在AX中;两个16位数相乘得到的32位乘积隐含存放在DX、AX中,其中DX存放高位字,AX存放低位字。指令中的源操作数SRC可以使用除立即数方式以外的任一种寻址方式。必须注意MUL指令和IMUL指令的使用。例如,80H×10H,若把它看做无符号整数时,应为128×16

=2048,而把它看做带符号整数时,则为(-128)×16=-2048。因此,必须根据需要来决定选用哪一条指令。

乘法指令对除CF和OF以外的标志位无定义(无定义的意义和不影响不同,无定义是指指令执行后这些标志位的状态不定,而不影响则是指该指令的结果并不影响标志位,所以标志位保持不变),对于MUL指令,如果乘积的高半部分为0,则CF和OF均为0,否则CF和OF均为1。对于IMUL指令,如果乘积的高半部分仅仅是低半部分的符号扩展,则CF和OF均为0,否则CF和OF均为1。这样的标志位设置可以用来检查字节相乘的结果是字节还是字,或者可以检查字相乘的结果是字还是双字。

3)无符号数除法指令(DIV)

汇编格式:DIVSRC

执行的操作:

①字节操作。执行前,16位被除数隐含在AX中,由SRC指定8位除数,执行后结果的8位商在AL中,8位余数在AH中。

(AL)←(AX)/(SRC)的商

(AH)←(AX)/(SRC)的余数②字操作:执行前,32位被除数隐含在DX,AX中,其中DX为高位字;16位除数由SRC指定,执行后,16位商在AX中,16位余数在DX中。

(AX)←(DX,AX)/(SRC)的商

(DX)←(DX,AX)/(SRC)的余数

商和余数均为无符号数。

4)带符号数除法指令(IDIV)

汇编格式:IDIVSRC

执行的操作:与DIV相同,但操作数是带符号数,商和余数也均为带符号数,且余数的符号和被除数的符号相同。

与乘法指令类似,除法指令也采用隐含方式。被除数必须存放在AX(16位)或DX,

AX(32位)中,而除数可以用除立即数以外的任何一种寻址方式。

除法指令对所有标志位均无定义。

由于除法指令的字节操作要求被除数为16位,字操作要求被除数为32位,因此,当使用带符号除IDIV指令时,往往需要用符号扩展的方法取得除法指令所需要的被除数格式。

5)字节转换为字指令(CBW)

汇编格式:CBW

执行的操作:将AL的符号扩展到AH。即若(AL)的最高位为0,则(AH)=00;若(AL)的最高位为1,则(AH)=0FFH。

CBW指令在形式上为零地址指令,实际操作数由AX寄存器隐含。

6)字转换为双字指令(CWD)

汇编格式:CWD

执行的操作:将AX的符号扩展到DX。即若(AX)的最高位为0,则(DX)=0000;若(AX)的最高位为1,则(DX)=0FFFFH。

与CBW相同,CWD指令在形式上也为零地址指令,实际操作数由AX、DX寄存器隐含。

这两条指令都不影响标志位。

除法指令执行时,如果被除数的高8位绝对值大于除数的绝对值(字节操作时)或被除数的高16位绝对值大于除数的绝对值(字操作时),则商会产生溢出,由系统直接进入0号类型中断处理。

例4.3

若x、y、z、w均为16位带符号数,并已分别装入以X、Y、Z、W为符号地址的单元中,要求计算(w-(x×y+z-543))/x,并将结果——商存入符号地址为V的字单元中。

所需的程序段如下:

MOV AX, X

IMUL Y ;x乘以y

MOV CX, AX ;积存于BX,CX中

MOV BX, DX

MOV AX, Z

CWD ;将z扩展为双字

ADD CX, AX ;完成积加z

ADC BX, DX

SUB CX, 543 ;减543

SBB BX, 0

MOV AX, W

CWD ;将w扩展为双字

SUB AX, CX ;完成减

SBB DX, BX

IDIV X ;除以x

MOV V,AX ;商送入V单元

3.十进制数调整类指令

这组指令在二进制数计算的基础上对十进制数进行调整,得到十进制数的结果。计算机中常用8421码表示十进制数(8421码是BCD码的一种。BCD码是用二进制表示的十进制数)。在计算机里,表示十进制数的8421码可以用压缩的8421码和非压缩的8421码两种格式来表示:压缩的8421码用4位二进制数表示一个十进制数位;非压缩的8421码用8位表示一个十进制数位,8位中的低4位表示8421码,而高4位则没有意义。显然,数字的ASCII码是一种非压缩8421码。因为数字的ASCII码的高4位值为0011B,低4位是以8421码表示的十进制数位,这符合非压缩8421码的规定。

相应地,计算机中的十进制调整指令分为两组,下面分别加以说明。

压缩的8421码调整指令:

DAA(DecimalAdjustforAddition) 加法的十进制调整指令

DAS(DecimalAdjustforSubtraction) 减法的十进制调整指令

ADD、ADC以及SUB、SSB指令只用于二进制数加、减法,是逢二进一,借一当二,对连续的4位二进制数是逢十六进一,借一当十六。但压缩的8421码却是逢十进一,借一当十。因此使用加、减法指令对8421码运算后,必须经调整才能得到正确的结果。非压缩的8421码调整指令:

AAA(ASCIIAdjustforAddition) 加法的ASCII码调 整指令

AAS(ASCIIAdjustforSubtraction) 减法的ASCII码调 整指令

AAM(ASCIIAdjustforMultiplication) 乘法的ASCII码调 整指令

AAD(ASCIIAdjustforDivision) 除法的ASCII码调 整指令这组指令适用于对数字ASCII码的调整,也适用于一般的非压缩8421码的十进制调整。

十进制调整指令不能单独使用,必须与加、减、乘、除二进制指令配合使用才能进行十进制调整。十进制调整指令形式上均为零地址指令,其操作对象由AX寄存器隐含。

1)加法的十进制调整指令(DAA)

汇编格式:DAA

执行的操作:把AL中的和调整到8421格式,这条指令紧跟在ADD或ADC指令后,并且把两个8421码相加,并把结果存放在AL寄存器中。本指令的调整方法如下:

①如果AF标志(辅助进位位)为1,或者AL寄存器的低4位是十六进制的AH~FH(非法码),则将AL寄存器内容加06H,并将AF位置1;

②如果CF标志为1,或者AL寄存器的高4位是十六进制的AH~FH(非法码),则将AL寄存器内容加60H,并将CF位置1。

DAA指令对OF标志无定义,但影响所有其它标志位。

2)减法的十进制调整指令(DAS)

汇编格式:DAS

执行的操作:把AL中的差调整到8421格式。

这条指令紧跟在SUB或SBB指令后,把两个8421码相减并把差存放在AL寄存器中。本指令的调整方法如下:

①如果AF标志为1(低4位向高4位有借位),或者AL寄存器的低4位是十六进制的AH~FH(非法码),则将AL寄存器的内容减去06H,并将AF位置1;

②如果CF标志为1(有借位),或者AL寄存器的高4位是十六进制的AH~FH(非法码),则将寄存器的内容减去60H,并将CF位置1。

DAS指令对OF标志无定义,但影响所有其它标志位。

例4.4

设8421码数据x、y均为16位(4位8421码十进制数据),它们在内存中的存放地址分别为X、Y(字节单元符号地址),试完成(X)+(Y)→(Z),(X)-(Y)→(W),要求结果也是8421码数据,其中Z、W均为字单元符号地址。

所需程序段如下:

MOV AL, X

ADD AL, Y ;x,y的十位、个位相加

DAA ;十位、个位十进制加法调整

MOV Z, AL ;送十位、个位的8421码和

MOV AL, X+1

ADC AL, Y+1 ;x,y的千位、百位相加,并加十位向百位的进位

DAA ;千位、百位十进制加法调整

MOV Z+1, AL ;送千位、百位的8421码和

MOV AL, X

SUB AL, Y ;x,y的十位、个位相减

DAS ;十位、个位十进制减法调整

MOV W, AL ;送十位、个位的8421码差

MOV AL, X+1

SBB AL, Y+1 ;x,y的千位、百位相减,并减 去十位向百位的借位

DAS ;千位、百位十进制减法调整

MOV W+1,AL ;送千位、百位的8421码差

3)加法的ASCII调整指令(AAA)

汇编格式:AAA

执行的操作:把AL中的和调整为非压缩的8421(BCD)格式,AH的内容加上调整产生的进位值。

这条指令紧跟在ADD或ADC指令后,并且把两个非压缩的BCD码相加,然后把结果存放在AL寄存器中。本指令的调整步骤如下:

①如果AL寄存器的低4位在0~9之间,且AF位为0,则跳过第②步,执行第③步;

②如果AL寄存器的低4位在十六进制数A~F之间或AF位为1,则将AL寄存器的内容加6,AH寄存器的内容加1,并将AF位置1;

③清除AL寄存器的高4位;

④将AF位的值送CF位。

AAA指令除影响AF和CF标志外,对其余标志位均无定义。

4)减法的ASCII调整指令(AAS)

汇编格式:AAS

执行的操作:把AL中的差调整为非压缩的BCD格式,AH的内容减去调整产生的借位值。

这条指令紧跟在SUB或SBB指令后,并且把两个非压缩的BCD码相减,然后把结果存放在AL寄存器中。本指令的调整步骤如下:

①如果AL寄存器的低4位在0~9之间,且AF位为0,则跳过第②步,执行第③步;

②如果AL寄存器的低4位在十六进制数A~F之间或AF位为1,则将AL寄存器的内容减去6,AH寄存器的内容减1,并将AF位置1;

③清除AL寄存器的高4位;

④将AF位的值送CF位。

AAS指令除影响AF和CF标志外,对其余标志位均无定义。

例4.5

设非压缩的8421码数据x、y、z均为16位(两位非压缩BCD码的十进制数据),它们在内存中的存放地址分别为X、Y、Z(字节单元符号地址),试完成(X)+(Y)-(Z)→(W),要求结果也是非压缩的BCD码数据,其中W为字单元符号地址。

所需程序段如下:

MOV AH, 0

MOV AL, X

ADD AL, Y ;x、y个位相加

AAA ;个位十进制数加法调整

MOV W, AX ;送个位的非压缩BCD码

MOV AL, X+1

ADC AL, Y+1;x、y的十位相加,并加上个 位向十位的进位

AAA ;十位十进制数加法调整

MOV W+2,AX;送十位的非压缩BCD码

MOV AX, W

SUB AL, Z ;减去z的个位

AAS ;个位十进制数减法调整

MOV W, AX;送个位的非压缩BCD码

MOV AX, W+2

SBB AL, Z+1 ;减去z的十位

AAS ;十位十进制数减法调整

MOV W+2, AX ;送十位的非压缩BCD码

5)乘法的ASCII调整指令(AAM)

汇编格式:AAM

执行的操作:把AL中的和调整到非压缩的BCD格式,并送入AX寄存器。

这条指令紧跟在MUL指令后,并且把两个非压缩的BCD码相乘(此时要求其高4位为0),结果(积)放在AL寄存器中。本指令的调整方法是:把AL寄存器的内容除以0AH,并把商放在AH寄存器中,余数保存在AL寄存器中。

本指令根据AL寄存器的内容设置标志位SF、ZF和PF,但对OF、CF和AF位无定义。

6)除法的ASCII调整指令(AAD)

汇编格式:AAD

执行的操作:

(AL)←10*(AH)+(AL)

(AH)←0

加法、减法和乘法的ASCII调整指令都是先用加法、减法和乘法指令对两个非压缩的BCD码运算以后,再分别使用AAA、AAS、AAM指令来对运算结果进行十进制调整。除法的情况却不同,它是针对以下情况而设立的。被除数是存放在AX寄存器中的二位非压缩BCD码,其中AH中存放十位数,AL中存放个位数,而且要求AH和AL中的高4位均为0。除数是一位非压缩的BCD码,同样要求高4位为0。在把这两个数用DIV指令相除以前,必须先用AAD指令把AX中的被除数调整成二进制数,并存放在AL寄存器中。

本指令根据AL寄存器的结果设置SF、ZF和PF位,但对OF、CF和AF无定义。

例4.6

设非压缩的BCD码数据x为16位,y为8位,它们在内存中的存放地址分别为X、Y,试完成x×y→Z和x/y的商→Q、x/y的余数→R,要求结果也是非压缩的BCD码数据,结果积的存放单元Z为32位,商的存放单元Q为16位,余数的存放单元R为8位。

BCD码的乘、除算法手算如图4.13所示。

图4.13BCD码的乘、除法手算所需程序段如下:

MOV AL, X ;取x的个位数

MUL Y ;x的个位数乘以y

AAM ;将部分积调整为十进制数的十 位数和个位数

MOV Z, AL ;部分积暂存入Z的低16位

MOV Z+1, AH

MOV AL, X+1 ;取x的十位数

MUL Y ;x的十位数乘以y

AAM ;将部分积调整为十进制数的百 位数和十位数

ADD AL, Z+1 ;两次部分积的十位数相加

AAA ;调整为十进制数的百位数和十 位数

MOV Z+1, AL ;存入百位数和十位数

MOV Z+2, AH

MOV AH, 0

MOV AL, X+1

DIV Y ;x的十位数除以y

MOV Q+1, AL ;存放商的十位数,AH中为10 位数上的余数

MOV AL, X

AAD ;将AH中余数与被除数的个位 数调整为十进制数

DIV Y ;再除以y

MOV Q, AL ;送商

MOV R, AH ;送余数4.3.3逻辑运算和移位指令

1.逻辑运算指令

AND(And) 逻辑与指令

OR(Or) 逻辑或指令

NOT(Not) 逻辑非指令

XOR(ExclusiveOr) 异或指令

TEST(Test) 测试指令

1)逻辑与指令(AND)

汇编格式:ANDDST,SRC

执行的操作:(DST)←(DST)∧(SRC)

2)逻辑或指令(OR)

汇编格式: ANDDST,SRC

执行的操作:(DST)←(DST)∨(SRC)

3)逻辑非指令(NOT)

汇编格式: NOTOPR

执行的操作:(OPR)←()

4)异或指令(XOR)

汇编格式:XORDST,SRC

执行的操作:(DST)←(DST)∀(SRC)

5)测试指令(TEST)

汇编格式:TESTOPR1,OPR2

执行的操作:(OPR1)∧(OPR2),但不保存结果,仅置标志位。

以上五种指令中,NOT不允许使用立即数,其它4条指令的目的操作数不能使用立即数,并且最多只能有一个操作数为内存寻址。NOT指令不影响标志位,其它4种指令将使CF和OF位为0,AF位无定义,而SF、ZF和PF位则根据运算结果设置。逻辑运算指令对字或字节执行按位操作,主要用于将字或字节的指定位进行置“1”(或操作)、清“0”(与操作、自身异或操作)、取反的操作,测试字或字节指定的位(与操作),以及对字、字节数据进行拆分(与操作)与拼装操作(或操作)。

要将AL寄存器第8位清“0”,可用指令:

ANDAL,7FH

要将AL寄存器第8位置“1”,可用指令:

ORAL,80H

要将AL寄存器第8位取反,可用指令:

XORAL,80H要将AL寄存器全部清“0”,可用指令:

XORAL,AL

要将AL寄存器全部置“1”,可用指令:

ORAL,0FFH

要将AL寄存器全部按位取反,可用指令:

NOTAL

要测试AL寄存器的最低位是“1”还是“0”,可用指令:

TESTAL,1

要测试AL与AH寄存器的内容是否相等,可用指令:

XORAL,AH

当然也可用指令:

CMPAL,AH

2.移位指令

SHL(ShiftLogicalLeft) 逻辑左移指令

SAL(ShiftArithmeticLeft) 算术左移指令

SHR(ShiftLogicalRight) 逻辑右移指令

SAR(ShiftArithmeticRight)算术右移指令

ROL(RotateLeft) 循环左移指令

ROR(RotateRight) 循环右移指令

RCL(RotateLeftwithCarry)带进位循环左移指令

RCR(RotateRightwithCarry)带进位循环右移指令

1)逻辑左移指令(SHL)

汇编格式:SHLOPR,CNT

执行的操作:如下所示。

其中,OPR可以是除立即数以外的任何寻址方式。移位次数由CNT决定,CNT可以是1或CL。

CNT为1时只移一位;如需要移位的次数大于1,则可以在该移位指令前把移位次数送至CL寄存器中,并将移位指令中的CNT写为CL。有关OPR及CNT的规定也适用于以下的移位指令。

2)算术左移指令(SAL)

汇编格式:SALOPR,CNT

执行的操作:与SHL相同。

3)逻辑右移指令(SHR)

汇编格式:SHROPR,CNT

执行的操作:如下所示。

4)算术右移指令(SAR)

汇编格式:SAROPR,CNT

执行的操作:如下所示。

逐位右移,同时最高位不变,即如果原来最高位是0,则仍为0;如果原来是1,则仍为1。这是补码算术右移的规则。

5)循环左移指令(ROL)

汇编格式:ROLOPR,CNT

执行的操作:如下所示。

6)循环右移指令(ROR)

汇编格式:ROROPR,CNT

执行的操作:如下所示。

7)带进位循环左移指令(RCL)

汇编格式:RCLOPR,CNT

执行的操作:如下所示。

8)带进位循环右移指令(RCR)

汇编格式:RCROPR,CNT

执行的操作:如下所示。所有移位指令都可以对字或字节进行操作。对标志位的影响是:CF位根据各条指令的规定设置。OF位只有当CNT=1时方有效,移位后最高有效位的值发生变化时(原来为0,移位后为1;或原来为1,移位后为0)OF位置“1”,否则清“0”。循环移位指令不影响除CF和OF以外的其它标志。而其它移位指令则根据移位后的结果设置SF、ZF和PF位,但对AF位则无定义。算术移位指令用于带符号数乘以2或除以2的运算;逻辑移位指令则用于无大小意义的移位操作。循环移位用于多精度移位及字、字节数据的拆分、拼装。

例4.7

设x为32位的双字数据,它在内存中的存放地址为X,编写求2×x及x÷2的程序段。

程序段如下:

SALWORDPTRX,1 ;X的低16位乘以2,移 出的位存于CF

RCLWORDPTRX+2,1 ;X的高16位乘以2,并将 低16位移出的位移入第16位

SARWORDPTRX+2,1 ;X的高16位除以2,移 出的位存于CF

RCRWORDPTRX,1 ;X的低16位除以2,并将 高16位移出的位移入第15位

例4.8

编写程序,将AL寄存器高4位与低4位互换。

程序段如下:

MOV CL,4

ROL AL,CL;循环左移4位,高位逐位移 入低位

或:

MOV CL,4

ROR AL,CL;循环右移4位,低位逐位移 入高位

例4.9

若不发生溢出,编写1.5×(AX)→(AX)的程序段。

程序段如下:

MOV BX,AX

SAL AX,1 ;2×(AX)→AX

ADD AX,BX ;3×(AX)→AX

SAR AX,1 ;1.5×(AX)→

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论