




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
会计学1汇编语言程序设计第3章3.1寻址方式3.1.1寻址方式和有效地址概念操作数地址的表示有3种情况:
(1)直接放在指令中。指令的操作数部分就是操作数本身。这种操作数叫做立即数,对应的指令寻址方式称为立即数寻址。
(2)放在CPU的某个内部寄存器中。指令的操作数部分是CPU的一个寄存器。这种指令寻址方式称为寄存器寻址。
(3)放在某个存储单元中,指令的操作数部分包含着该操作数所在的内存地址。这种指令寻址方式称为存储器寻址。第1页/共246页
每个存储单元在存储器中所具有的地址称为存储单元的物理地址,段基地址(简称段地址)是指每一段的起始地址,单元与段基地址的距离称为段内偏移地址,也叫偏移量。物理地址是由存储单元所在段的基地址和段内偏移地址这两个部分组成。以MOV指令为例,若有:
MOVDS∶BUFFER,AL这里,DS∶BUFFER表示内存的某一单元地址,称为逻辑地址。DS对于实地址方式就是段基址,对于保护方式则可通过段管理部件形成段基址。BUFFER为段内偏移地址,段内偏移地址有16位和32位两种。段基址和段内偏移地址相加,形成线性地址,对实地址方式而言,该线性地址就是物理地址。对保护方式而言,线性地址经管理部件再变换成32位物理地址。第2页/共246页
段内偏移地址可以由基址寄存器内容、变址寄存器内容、比例因子和位移量这4个基本部分组合而成。由4个基本部分组合而成的偏移地址称为有效地址EA(EffectiveAddress),比例因子可取1、2、4、8中的任一个,基址寄存器内容、变址寄存器内容和位移量可为正数也可为负数。有效地址EA的组合及计算方法是:有效地址EA=基址+(变址×比例因子)+位移量第3页/共246页
可用作基址、变址的寄存器和比例因子、位移量的取值规定是:●工作于实地址方式下的16位寻址:基址寄存器可以是BX或BP寄存器,变址寄存器可以是SI或DI寄存器,比例因子或者没有或者为1。位移量可以是0、8位或16位。●工作于保护方式下的32位寻址:基址寄存器可以是任何32位通用寄存器中的一个,变址寄存器可以是除ESP外的任何32位通用寄存器中的一个,比例因子可以是1、2或4或8,位移量可以是0、8位或32位。第4页/共246页3.1.2数据寻址方式
1.立即数寻址直接出现在指令中的操作数称为立即数,它紧跟在操作码的后面,其本身就是代码的一部分,这种寻址方式叫做立即数寻址。立即数可以是8位、16位或32位。例3-1MOVAL,20MOVBX,2568HMOVECX,25685678H这3条指令中的立即数依次是8位、16位和32位,对应的寄存器也分别是8位的AL、16位的BX和32位的ECX。执行指令MOVBX,2568H的结果是(BX)=2568H,执行过程见图3-1。第5页/共246页
说明:①立即数只能作源操作数,不能作为目的操作数,一般用于给寄存器赋初值;②立即数既可以是二进制数、十进制数,也可以是十六进制数;③低位字节数存放在存储单元的低地址字节,高位字节数存放在存储单元的高地址字节,如:MOVAX,im中的立即数im,其低8位字节iml存储在低地址字节单元中,高8位字节imh存储在高地址字节单元中,指令的存储与执行过程如图3-2所示。第6页/共246页图3-1例3-1立即数寻址示意图第7页/共246页
图3-2立即数寻址及数据存储示意图第8页/共246页2.寄存器寻址寄存器寻址又称寄存器直接寻址。操作数直接存放在寄存器中,由指令指定的寄存器进行寻址,即操作数包含在指令规定的8位、16位或32位寄存器中。如:
INCDLMOVDS,AXMOVEBX,ECX三条指令表明操作数分别存于8位DL、16位的AX和32位的ECX中。第9页/共246页
例3-2
设(CX)=1234H,(AX)=5678H,执行指令MOVCX,AX
其结果是:(CX)=5678H,(AX)不变,仍为5678H,执行过程见图3-3。说明:虽然操作数可使用CPU内部通用寄存器中的任意一个,且它们都能参与算术/逻辑运算和存放运算结果。由于AX和EAX是累加器,若结果是存放在AX或EAX中,通常指令执行的时间要短一些。第10页/共246页图3-3例3-2寄存器寻址执行情况第11页/共246页
3.直接寻址指令中的操作数部分直接给出的是操作数的有效地址EA的寻址方式称为存储器直接寻址,简称直接寻址。有效地址EA是和操作码一起放在存储器代码段中,它可以是16位或32位整数。但操作数一般在数据段DS中。设要访问的数据存放在DS所指向的数据段中,实地址模式下物理地址的计算方法是:物理地址=10H(DS)+有效地址第12页/共246页图3-4例3-3直接寻址执行情况第13页/共246页
例3-3设操作数存放在DS所指向的数据段中,(DS)=2000H,(21000H)=34H,(21001H)=12H,(BX)=5678H,执行指令MOVBX,[1000H]后的结果为:(BX)=1234H,指令中的16位地址偏移量是低位字节在低地址存储单元中,高位字节在高地址存储单元中。执行过程如图3-4所示。例3-4执行指令MOVAX,BEGIN的结果是:将内存中从BEGIN开始的连续两个单元内容送入AX中。第14页/共246页
说明:①直接寻址方式,是以数据段的地址为基础,可在多达64KB的范围内寻找操作数。②缺省情况下,认为操作数有效地址的作用域是DS所指向的数据段,但允许使用段超越前缀指定为其他段,即对于寻找操作数来说,还允许操作数在以代码段、堆栈段或附加段为基准的区域中,即只要在指令中指明是段超越的,则16位地址偏移量可以与CS、SS、ES、FS或GS相加,作为操作数的地址,如MOVAX,ES∶[2000H]。第15页/共246页③指令中操作数的有效地址既可以是一个数字,也可以是一个符号地址,如例3-4中的BEGIN就是一个符号地址。④直接寻址主要用于单个操作数的相对寻址场合,如简单的标量操作数寻址和静态分配的数组的起始地址寻址等。第16页/共246页
4.寄存器间接寻址操作数在存储器中,但操作数地址的偏移量包含在寄存器中,这种寻址方式称为寄存器间接寻址。寄存器间接寻址可以是16位寻址,也可以是32位寻址。若使用BX、SI、DI、BP4个寄存器中的一个,则为16位寻址;若使用的是EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP中的一个,则为32位寻址。以BX、SI、DI、EAX、EBX、ECX、EDX、ESI、EDI间接寻址时,则默认操作数在DS段中;以BP、EBP、ESP间接寻址时,则默认操作数在SS段中。寄存器的使用规定对16位寻址和32位寻址是不一样的。第17页/共246页图3-5寄存器间接寻址示意图第18页/共246页(1)16位寻址时,偏移地址放在SI、DI、BP或BX中,段默认有两种情况:①若以SI、DI、BX间接寻址,通常操作数在现行数据段区域中,即数据段寄存器DS左移4位后加上SI、DI、BX中的16位偏移量作为操作数的地址。例如,MOVAX,[SI],操作数在数据段寄存器DS中,16位偏移量在SI中。设(DS)=2000H,(SI)=1000H,21000H单元的内容为34H,21001H单元的内容为12H,执行MOVAX,[SI]后,AX的内容为1234H。指令的执行过程如图3-5所示。第19页/共246页②若是以寄存器BP间接寻址,则操作数在堆栈段区域中,即堆栈段寄存器SS左移4位后与BP相加作为操作数的地址。例如,MOVAX,[BP],操作数在数据段寄存器SS中,16位偏移量在BP中。设(SS)=3000H,(BP)=2000H,32000H单元的内容为34H,32001H单元的内容为12H,执行MOVAX,[BP]后,AX的内容为1234H。指令的执行过程如图3-6所示。第20页/共246页图3-6BP寄存器间接寻址示意图第21页/共246页(2)32位寻址时,偏移地址放在以EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP寄存器中,段默认有两种情况:①通用寄存器EAX、EBX、ECX、EDX、ESI、EDI默认段寄存器为DS。②通用寄存器ESP、EBP默认段寄存器为SS。第22页/共246页例3-5MOVEBX,[EAX];默认DS为段基址,传送双字给EBXMOVDX,[EBX];默认DS为段基址,传送字给DXMOVCH,[EAX];默认DS为段基址,传送字节给CH第23页/共246页说明:①如果操作数在默认段之外,指令中必须加段超越前缀。如
MOVAX,ES∶[SI];操作数在数据段寄存器ES中,不在默认段DS中
MOVAX,DS∶[BP];操作数在数据段寄存器DS中,不在默认段SS中所以,“ES∶”和“DS∶”分别是两指令的段超越前缀。②若在指令中规定是段超越的,则BP也可以与其它的段寄存器相加,形成操作数地址,如MOVAX,DS∶[BP],BP不是与SS段寄存器形成操作数地址,而是与DS段寄存器形成操作数地址。③寄存器间接寻址的应用场合与直接寻址的应用场合相似。④源操作数与目的操作数的位数要匹配。第24页/共246页
例3-6设(DS)=2000H,(SI)=1200H,(21200H)=56H,执行指令MOVAH,[SI]的结果是:(AH)=56H,执行过程见图3-7。
图3-7例3-6寄存器间接寻址执行情况第25页/共246页
例3-7设(DS)=2000H,(DI)=2100H,(22100H)=68H,(22101H)=41H,执行指令MOVBX,[DI]的结果是:(BX)=4168H。第26页/共246页
5.基址寻址由指定的基址寄存器内容,加上指令中给定的偏移量(要由一个段寄存器作为地址基准)作为操作数的地址的寻址方式称为基址寻址。在基址寻址方式下,EA=[基址寄存器]+位移量,位移量是常数且紧跟在操作码之后,与操作码一起存放在代码段中。基址寄存器的使用规定对16位寻址和32位寻址是不一样的。第27页/共246页(1)16位寻址情况下,SX和BP作为基址寄存器。在缺省段超越前缀时,BX以DS作为默认段寄存器,BP以SS作为默认段寄存器。位移量可为8位或16位。
(2)32位寻址情况下,8个32位通用寄存器均可作基址寄存器,其中ESP、EBP以SS为默认段寄存器,其余6个通用寄存器均以DS为默认段寄存器。位移量为8位或32位。基址寻址适于对一维数组的数组元素进行检索操作。位移量表示数组起始地址偏移量,基址表示的是可以变化的数组元素下标。
EA的书写形式可以是“[基址寄存器]+位移量”,也可以是“位移量[基址寄存器]”。基址寻址的执行过程示例如图3-8所示(以例3-8中的MOVDX,[EAX+1500]为例,默认段基址是DS)。第28页/共246页图3-8基址寻址的执行过程示意图第29页/共246页
例3-8MOVEAX,[BX+24] ;或MOVEAX,24[BX]MOVECX,[EBP+50] ;或MOVECX,50[EBP]MOVDX,[EAX+1500] ;或MOVDX,1500[EAX]第30页/共246页
例3-9设(DS)=2000H,(SI)=1200H,(21206H)=56H,执行指令MOVAH,[SI+6]的结果是:(AH)=56H,执行过程见图3-9。图3-9例3-9寄存器相对寻址执行情况第31页/共246页
6.变址寻址由指定的变址寄存器内容,加上指令中给定的偏移量(要由一个段寄存器作为地址基准)作为操作数的地址的寻址方式称为变址寻址。在变址寻址方式下,EA=[变址寄存器]+位移量,位移量跟在操作码之后,与操作码一起存放在代码段中。变址寄存器的使用规定对16位寻址和32位寻址是不一样的。
(1)16位寻址时,仅SI、DI可作变址寄存器,默认DS作为段基址寄存器。如:
MOVAX,COUNT[SI]第32页/共246页(2)32位寻址时,除ESP外的任何通用寄存器均可作变址寄存器,EBP默认SS作段基址寄存器,其余的以DS作段基址寄存器。如:
MOVEAX,5[EBP]MOVECX,DATA[EAX]EA的书写形式可以是“[变址寄存器]+位移量”,也可以是“位移量[变址寄存器]”,即位移量可以写在[]里,也可以写在[]外面;也可以是一个数字,或一个符号地址。以MOVAX,COUNT[SI]为例,默认段基址是DS,变址寻址的执行过程如图3-10所示。第33页/共246页图3-10变址寻址示意图第34页/共246页
变址寻址适用于对一维数组的数组元素进行检索操作。位移量表示数组起始地址偏移量,变址表示的是可以变化的数组元素下标。例3-10
执行指令MOVCX,LIST[DI]的结果是将内存中从DS∶[DI+LIST]处开始的连续两个单元内容送入CX中,其中LIST是用符号表示的位移量,变址寄存器使用的是DI,所以默认段为DS。第35页/共246页
7.基址加变址寻址由指令中的基址寄存器内容和变址寄存器内容相加得到操作数的有效地址EA的寻址方式称为基址加变址寻址,即EA=[基址寄存器]+[变址寄存器]如:
MOVAX,[BX+SI] ;或MOVAX,[BX][SI]MOVEAX,[EDX][EBP] ;或MOVEAX,[EDX+EBP]第36页/共246页
基址加变址寻址有16位和32位寻址两种情况,每种情况下基址、变址寄存器的使用规定和段寄存器的默认规定与基址寻址、变址寻址相同。但当一种寻址方式中既有基址寄存器又有变址寄存器,而两个寄存器默认的段寄存器又不相同时,一般规定由基址寄存器来决定默认哪一个段寄存器作段基址指针。缺省时操作数所在段由指令中的基址寄存器决定,若使用BP、ESP或EBP,则默认操作数在SS段中;若使用其他基址或变址寄存器,则默认操作数在DS段中。如:MOVAX,[BX][SI];基址寄存器是BX,默认DS为段基址寄存器MOVEAX,[EBP][ECX];基址寄存器是EBP,默认SS为段基址寄存器基址加变址寻址可用于二维数组操作(如检索数组元素)和二重循环等。第37页/共246页
例3-11
设(DS)=2000H,(SI)=200H,(BX)=1000H,(21200H)=21H,执行指令MOVAL,[SI+BX]的结果是:(AL)=21H,执行过程如图3-11所示。图3-11例3-11基址加变址寻址示意图第38页/共246页
例3-12
执行MOVBX,[EDI+EAX]的结果是将内存中DS∶[EDI+EAX]处开始的连续两个单元内容送BX中。第39页/共246页
8.比例变址寻址变址寄存器的内容乘以比例因子再加上位移量得到操作数有效地址EA的寻址方式称为比例变址寻址,即EA=[变址寄存器]×比例因子+位移量比例变址寻址只有32位寻址一种情况。如:
MOVEAX,TABLE[ESI*4];TABLE是位移量,4是比例因子其中,乘比例因子的操作是在CPU内部由硬件完成的。第40页/共246页
例3-13
指令MOVEAX,50[ESI*4]的位移量是50,比例因子是4,执行该指令时,默认DS为段基址,执行过程如图3-12所示。图3-12比例变址寻址过程示意图第41页/共246页
例3-14执行指令MOVAX,LIST[2*ESI]的结果是将内存中从DS:[2*ESI+IST]处开始的连续两个单元内容送AX中;执行指令MOVCL,[ESI+4*EAX]的结果是将内存中DS:[ESI+4*EAX]处的单元内容送CL中;执行指令MOVDX,[EBP+4*ECX+9]的结果是将内存中从DS:[EBP+4*ECX+9]处开始的连续两个单元内容送入DX中。第42页/共246页
9.基址加比例变址寻址由变址寄存器的内容乘以比例因子再加上基址寄存器的内容而得到操作数有效地址EA的寻址方式称为基址加比例变址寻址方式,即EA=[变址寄存器]×比例因子+[基址寄存器]基址加比例变址寻址只有32位寻址一种情况。如:
MOVECX,[EDX*8][EAX];或MOVECX,[EDX*8+EAX]MOVAX,[EBX*4][ESI];或MOVAX,[EBX*4+ESI]基址加比例变址寻址方式主要用于数组元素大小为2、4、8字节时的二维数组检索操作等场合。第43页/共246页
例3-15
设(DS)=2000H,(DI)=200H,(AX)=1000H,(21204H)=32H,执行指令MOVAL,[DI+AX+4]的结果是:(AL)=32H,执行过程见图3-13。图3-13例3-15基址加比例变址寻址执行过程示意图第44页/共246页
例3-16
执行指令MOVBX,LIST[ESI+EAX]的结果是将内存中从DS:[ESI+EAX+LIST]处开始的连续两个单元内容送入BX中。第45页/共246页10.带位移的基址加变址寻址由变址寄存器、基址寄存器内容和位移量一同相加而得到操作数有效地址的寻址方式称为带位移的基址加变址寻址,即EA=[变址寄存器]+[基址寄存器]+位移量带位移的基址加变址寻址分为16位寻址和32位寻址两种情况。变址、基址寄存器的使用约定和对段寄存器的默认约定与前面所述相同。如:MOVAX,[BX+DI+MASK];或MOVAX,MASK[BX][DI]ADDEDX,[ESI][EBP+0FFFF000H];或ADDEDX,0FFFF000H[ESI][EBP]以执行指令MOVAX,MASK[BX][DI]为例,默认DS为段基址,图3-14是带位移的基址加变址寻址过程示意图。第46页/共246页图3-14带位移的基址加变址寻址过程示意图第47页/共246页
11.带位移的基址加比例变址寻址由变址寄存器内容乘以比例因子、基址寄存器内容和位移量一同相加而得到操作数有效地址的寻址方式称为带位移的基址加比例变址寻址,即EA=[变址寄存器]×比例因子+[基址寄存器]+位移量带位移的基址加比例变址寻址只有32位寻址一种情况,这与比例变址寻址、基址加比例变址寻址方式一样,各种约定和默认情况同前所述。寻址过程中,变址寄存器内容乘比例因子的操作是在CPU内部由硬件完成的,其他操作与图3-14所示相同。第48页/共246页
例3-17INC[EDI*8][ECX+40];或INC[EDI*8+ECX+40]当二维数组的数组元素大小为2、4、8字节,且数组起始地址不为0时,适于用带位移的基址加比例变址寻址方式进行数组检索操作。第49页/共246页3.1.3程序存储器寻址方式
1.段内相对寻址在此寻址方式下,转移后的指令与转移指令本身在同一代码段中,指令中的地址是一个相对于当前IP内容的位移量,它是一个带符号数,而转移后指令的有效地址为有效地址=(IP)+位移量其中位移量是一个字节称为短转移,转移的范围是-128~+127,可用SHORT表示;位移量是两个字节称为近转移,转移范围是32KB,可用NEAR表示。第50页/共246页
例3-18
指令JMPSHORTAIM1是短转移,SHORT表示为短转移,AIM1为目的地址;指令JMPNEARPTRAIM2是近转移,NEAR表示为近转移,AIM2为目的地址。转移后的目的地址,汇编语言在汇编时,能自动计算目的地址相对于当前IP的内容的位移量,然后替换目的地址。此寻址方式不影响代码段寄存器CS的值,只影响指令指针IP的值。第51页/共246页
2.段间直接寻址在段间直接寻址方式下,转移后的指令与转移指令本身不在同一代码段中,汇编语言在汇编时,自动将指令中的目的地址的段基址和偏移量替换掉CS和IP原先的内容。段间直接寻址方式也称为远转移,可用FAR表示。
例3-19
指令JMPFARPTRAIM是远转移,FAR表示为远转移,AIM为目的地址。第52页/共246页
3.存储器间接寻址在存储器间接寻址下,目的地址不直接出现在指令中,而是存储在一个寄存器或者一个内存单元中,因此,要先使用除立即数寻址以外的任意一种数据寻址方式获取目的地址,然后判断转移到该目的地址是段内转移还是段间转移,根据判断结果按照段内相对寻址和段间直接寻址两种寻址方式的规则替换CS、IP的内容。例3-20
指令JMPBX中的BX为目的地址,它将替代IP的内容,为段内转移;指令JMPWORDPTRLIST[SI+DI]是用DS:[SI+DI+LIST]处开始的连续两个单元内容作目的地址,并用它替代IP的内容,为段内转移;指令JMPEAX中的EAX为目的地址,高16位送CS,低16位送IP,为段间转移。第53页/共246页3.2指令系统80x86的指令系统可以分为以下13个功能组。(1)数据传送指令;(2)算术运算指令;(3)逻辑运算与移位指令;(4)串操作指令;(5)位操作指令;(6)控制转移指令;(7)标志操作指令;(8)按条件设置字节指令;(9)操作系统型指令;(10)处理器控制指令;(11)高级语言指令;(12)Cache管理指令;(13)数字处理指令。第54页/共246页
标志操作指令、栈操作的相关指令已在第2章作过介绍。本节要介绍的指令包括:数据传送指令、算术运算指令、逻辑运算与移位指令、位操作指令、按条件设置字节指令SET、操作系统型指令、处理器控制指令、高级语言指令、Cache管理指令和数字处理指令,串操作指令、控制转移指令和高级语言指令将在第5章中介绍,CALL/RET指令将在第6章中介绍,输入/输出指令将在第10章中介绍。需要说明的是,汇编语言对于指令的大小写是不敏感的。第55页/共246页3.2.1数据传送指令数据传送指令可分为通用传送指令、地址传送指令、输入/输出指令、查表转换指令XLAT和扩展传送指令MOVSX和MOVZX
1.通用传送指令这类指令可分为一般传送指令MOV、入出栈指令和交换指令XCHG。入出栈指令包括:压栈/弹栈指令PUSH/POP、全部通用寄存器内容压栈和弹栈指令PUSHA/PUSHAD及POPA/POPAD。第56页/共246页1)传送指令MOV
格式:MOVOPRD1,OPRD2
功能:将OPRD2的内容传送到OPRD1中,并替换OPRD1中原来的内容。说明:MOV是操作码,OPRD1和OPRD2分别是目的操作数和源操作数。源操作数可以是累加器、寄存器、存储器以及立即操作数,而目的操作数可以是累加器、寄存器和存储器。数据传送方向的示意图如图3-15所示。第57页/共246页图3-15MOV指令数据传送方向的示意图第58页/共246页(1)除了代码段寄存器CS和指令指针IP以外,可在CPU内部寄存器之间任意传送数据。例3-21MOV AL,BLMOV DL,CHMOV AX,DXMOV CX,BXMOV DS,BXMOV DX,ESMOV BX,DIMOV SI,BP第59页/共246页(2)立即数传送至CPU内部的通用寄存器组,给这些寄存器赋初值。例3-22MOV CL,4MOV AX,03FFHMOV SI,057BH第60页/共246页(3)除了CS和IP以外,可实现CPU内部寄存器与存储器(所有寻址方式)之间的数据传送,传送的数据可以是一个字节、一个字或者一个双字。例3-23MOVAL,BUFFERMOVAX,[SI]MOVEAX,[EBX]MOV[DI],CXMOVSI,BLOCK[BP]MOVDS,DATA[SI+BX]MOVDEST[BP+DI],ES第61页/共246页
但是,MOV指令不能实现存储单元之间的数据传送。若需要把地址即段内的地址偏移量为AREA1的存储单元的内容,传送至同一段内的地址为AREA2的存储单元中去,MOV指令不能直接完成这样的传送。若要实现两个存储单元之间的数据传送,必须借助CPU的内部寄存器来实现。例3-24给出了传送方法。第62页/共246页
例3-24MOV AL,AREA1MOV AREA2,AL(以累加器AL为例)
例3-25
若传送的数据不是—个字节,而是一个数据块,如100个数据,给出所描述的程序段。
分析解决的方法有两个:方法1:采用与例3-24类似的200条指令来完成100个数据的传送,这些指令的操作是重复的,每条指令的地址又是变化的。第63页/共246页
方法2:为简化程序的编制,利用循环程序,方法是:每次循环都要修改源地址和目的地址,这就需要把源、目的地址分别放在两个寄存器中,用寄存器间接寻址来寻找操作数,修改了寄存器的内容,就可以实现对地址的修改。再把循环次数的控制部分考虑进去,就可得如下程序:第64页/共246页 MOVSI,OFFSETAREA1 ;目的地址存于SI寄存器中
MOVDI,OFFSETAREA2 ;源地址存于DI寄存器中
MOVCX,100 ;计数器存于CX中AGAIN:MOVAL,[DI]MOV[SI],ALINCSI ;修改目的地址
INCDI ;修改源地址
DECCX ;修改计数器的值
JNZAGAIN第65页/共246页
说明:①程序段中的AREA1和AREA2是立即数还是存储单元地址,汇编程序是根据对符号的定义来加以区别的;②指令INC和DEC分别是增量、减量指令,JNZ为转移指令,将在第5章中作介绍。③OFFSETAREA1是指地址单元AREA1在段内的地址偏移量。如前所述,在80x86中要寻找内存操作数时,必须以段地址(在某个段寄存器中)加上此单元的段内地址偏移量,才能确定某一内存单元的物理地址。上述关于MOV指令的使用说明,是判断MOV指令使用正确与否的依据。例3-26均为正确使用MOV指令的例子,而例3-27均为使用MOV指令不正确的例子。第66页/共246页
例3-26
下列的指令均为正确的指令。
MOVAX,BXMOVDS,DXMOVAH,[CX]MOVBX,WORDPTR[DX]MOVAL,21HMOV[1000H],BXMOV[2000H],54H第67页/共246页
例3-27
下列的指令均为错误的指令。
MOV47H,AX;目的地址不可为立即数
MOVCS,BX;为CS赋值的方法不对
MOVIP,DX;为IP赋值的方法不对
MOV[CX],[1000H];两个存储单元的数据不可直接传送
MOVDS,SS第68页/共246页2)地址传送指令地址传送指令主要用于传送操作数的地址,包括:装入有效地址指令LEA、装入DS、ES、FS、GS、SS指令LDS、LES、LFS、LGS、LSS。
(1)装入有效地址指令LEA。格式:LEAreg,mem
功能:将有效地址(偏移地址)mem而不是mem的内容装入到一指定寄存器reg中。第69页/共246页
说明:①源操作数必须是一个内存操作数,目的操作数必须是一个16位的通用寄存器。②该指令通常用来建立串操作指令所必须的寄存器指针。第70页/共246页
例3-28LEABX,LIST
将变量LIST的地址偏移量部分送到BX。例3-29若BX寄存器的内容是0400H,SI寄存器的内容是003CH,执行指令LEABX,[BX+SI+0F62H]后,BX的内容是什么?执行这条指令是将BX、SI的内容与0F62H相加的结果送BX,即将0400H+003CH+0F62H=139EH送BX,所以,执行完该条指令后(BX)=139EH。它与MOVBX,[BX+SI+0F62H]的区别是执行这条MOV指令,是将139EH表示的单元的内容送BX。第71页/共246页
例3-30
设EDX=30H,ESI=32H,DOLLAR=7580H,执行LEAECX,[EDX][4*ESI]DOLLAR的结果是将有效地址7678H(=30H+4×32H+7580H)传送给ECX。需指出的是,在很多场合下,LEA指令可以用相应的源操作数为立即数的MOV指令代替。例如,指令MOVBX,OFFSETVARWORD与指令LEABX,VARWORD的执行效果是完全一样的。区别在于前者是用伪指令运算符OFFSET(将在第4章中作介绍)取得源操作数,在程序执行前,由汇编程序汇编时赋值;而后者是在执行指令时赋值;LEA的源操作数可以用各种寻址方式,OFFSET运算符的操作数只能是一个直接的存储器符号。例如,指令LEADX,TABLE[SI]等效于下列两条指令:
MOVDX,OFFSETTABLEADDDX,SI第72页/共246页(2)加载DS/ES/FS/GS/SS指令LDS/LES/LFS/LGS/LSS。格式:OPRD1,OPRD2LDSreg, memLESreg, memLFSreg, memLGSreg, memLSSreg, mem
这里的mem是32位或48位远指针,reg是16位或32位任意通用寄存器。第73页/共246页
功能:这5条指令的作用是将一个32位或48位的全地址指针(包括一个16位段选择符和一个16位或32位偏移值)装入一个段寄存器和一个通用寄存器。段寄存器由指令操作码LDS、LES、LFS、LGS、LSS分别指定为DS、ES、FS、GS、SS,通用寄存器由目的操作数OPRD1指定。第74页/共246页
说明:①对实地址方式和虚拟8086方式,这类指令取的是双16位全地址指针。例3-31EXDWORDDD12345678HLDSSI,EXDWORD执行LDS指令后,将高16位1234H送DS,低16位5678H送SI。②对16位和32位保护方式,是将选择符送操作码指定的段寄存器,有效地址送指令指定的通用寄存器。第75页/共246页
例3-32EXDWORD DD12345678H ;定义偏移值
DW0010H ;定义选择符
LDSESI,EXDWORD执行LDS指令后,将低32位偏移值12345678H送令中指定的通用寄存器ESI,将高16位选择符0010H送DS。③LFS/LGS/LSS只能在80386以上的CPU中使用,主要用于处理不在当前数据段中的数据。
例3-33
执行LSSSP,LIST[DI]的结果是把DS:[DI+LIST]所指向单元内容前两个字节送到SP中,接下来的两个字节送SS中,此时即可访问栈单元。第76页/共246页3)交换指令XCHG与字节交换指令BSWAP(1)交换指令XCHG。格式:XCHGOPRD1,OPRD2
功能:将源操作数OPRD2与目的操作数OPRD1相交换。说明:①交换可在通用寄存器与累加器之间,通用寄存器之间,通用寄存器与存储器之间进行,但段寄存器不能作为一个操作数。两个操作数可以是两个寄存器操作数,或一个寄存器与一个存储器操作数,相当于三条指令:XCHGreg,reg、XCHGmem,reg和XCHGreg,mem。这里,reg是寄存器操作数,mem是存储器操作数。②OPRD1和OPRD2可以是字节、字或者双字,但长度应相等。第77页/共246页例3-34XCHG AL,CLXCHG AX,DIXCHG BX,SIXCHG AX,BUFFER ;设BUFFER为字单元
XCHG BX,DATA[SI]XCHG AX,WORDPTR[SI]XCHG BL,[1000H]第78页/共246页(2)字节交换指令BSWAP。格式:BSWAPreg32
功能:将32位通用寄存器中的双字以字节为单位进行高、低字节交换。即对指定寄存器的32位操作数,将位31~24与位7~0、位23~16与位15~8进行交换,也就是将第一个字节与第四个字节交换,第二个字节与第三个字节交换。说明:①这是一条80486扩展的指令。第79页/共246页②可用于在两种不同结构的微处理器之间进行数据的交换。多字节结构的数据有两种存储方式:一种是Intel系列CPU采用的低位结尾的内存字节排序方法,在这种方法中,多字节结构数据的高位字节存放在内存的高地址单元中;另一种是Motorola系列CPU采用高位结尾的内存字节排序方法,数据存放顺序正好与第一种相反。例3-35
设(EAX)=12345678H,执行指令BSWAPEAX的结果是:(EAX)=78563412H。第80页/共246页4)查表转换指令XLAT
格式:XLAT
功能:完成一个字节的查表转换。在DS∶EBX处建立了一个256字节的表,用寄存器EBX作为基址,寄存器AL作为表的无符号下标(即表指针),将AL指向的那个字节的内容送回AL,即((EBX)+(AL))→AL。第81页/共246页
说明:①在使用该指令之前,存储器内需有一个代码转换表,表首地址要送到EBX中,相对于表首的位移量送到AL中,则转换后数据的有效地址为有效地址=表首地址+位移量即以EBX寄存器内容作为表首、AL寄存器内容作为位移量所对应的表中数据送入寄存器AL中,并替换掉AL原先的内容。第82页/共246页②该指令无显式操作数,操作数是隐含的。指令默认段是数据段DS,而偏移量总是从寄存器EBX中得到。③指令执行前AL是下标,执行后AL是查表的结果。若要在其他段中查表,可加段前缀。④XLAT指令用于一些无规律的代码转换。第83页/共246页图3-16例3-36查表转换指令执行过程第84页/共246页
例3-36
通过查表转换指令,求0~9中任意一个数的平方。程序段描述如下:
TABDB1,4,9,16,25,36,49,64,81MOVAX,SEGTABMOVDS,AXMOVBX,OFFSETTABMOVAL,5XLAT执行该程序段后,(AL)=25,执行过程见图3-16。第85页/共246页5)扩展传送指令MOVSX和MOVZX
格式:MOVSXOPRD1,OPRD2MOVZXOPRD1,OPRD2
功能:MOVSX为带符号扩展传送指令,将寄存器或存储器中的8位符号数带符号扩展成16位或32位,16位符号数带符号扩展成32位,然后传送给16位或32位寄存器。
MOVZX为零扩展传送指令,将寄存器或存储器中的8位无符号数通过在高位加0扩展成16位或32位,16位无符号数通过加0扩展成32位,然后传送给16位或32位寄存器。第86页/共246页
说明:①对带符号数补码,经MOVSX扩展后的结果与扩展前真值是相等的,只是补码位数不同而已;经MOVZX扩展后,无符号数的真值不变。这两条指令常被用于作除法时对被除数位数的扩展。例如,MOVSXECX,AL是将AL内容带符号扩展为32位送入ECX;MOVZXEAX,CX是将CX中16位数高位加0扩展为32位送EAX。②扩展规则:对MOVSX而言,若OPRD2内容是正数,则扩展后的高8位或16位全填0;若OPRD2内容是负数,则扩展后的高8位或16位全填1;对MOVZX而言,扩展后的高8位或16位全填0。第87页/共246页③在MOVSXOPRD1,OPRD2和MOVZXOPRD1,OPRD2中,OPRD1可以是16位或32位的寄存器,而OPRD2可以是16位的寄存器或是8位的存储单元,OPRD1的长度必须是OPRD2的长度的一倍。④该指令仅限于80386以上的CPU。例3-37设(AL)=42H,(CX)=9687H,(DS)=2000H,(22000H)=0A8H,分别执行:MOVSXBX,AL、MOVSXEDX,CX、MOVSXDX,[2000H]、MOVZXBX,AL和MOVZXDX,[2000H]5条指令,5条指令的执行结果如表3-1所示(带下划线的数据是指令执行后按指令的要求应填补的内容)。第88页/共246页表3-1例3-37执行结果示意指令名称执行结果MOVSXBX,AL(BX)=0042H=0000000001000010BMOVSXEDX,CX(EDX)=0FFFF9687H=11111111111111111001011010000111BMOVSXDX,[2000H](DX)=0FFA8H=1111111110101000BMOVZXBX,AL(BX)=0042H=0000000001000010BMOVZXDX,[2000H](DX)=00A8H=0000000010101000B第89页/共246页3.2.2算术运算指令这类指令的源操作数与目的操作数均为二进制数,可以是8位、16位或32位的带符号数或无符号数(如果是带符号数,则最高位为符号位),也可以是无符号的组合、未组合BCD码数。算术运算指令还支持十进制调整和数据宽度变换指令等。这类指令如加、减、比较等是双操作数指令、加1或减1指令等是单操作数指令、有符号整数乘法指令IMUL等是三操作数指令,而十进制调整和数据宽度交换等指令则为无操作数指令。第90页/共246页
除数据宽度变换指令外,算术运算指令的操作结果一般会影响EFLAGS寄存器中的状态标志位,主要是影响进位标志CF、辅助进位标志AF、符号标志SF、零标志ZF、奇偶标志PF、溢出标志OF。
80X86提供了各种校正操作,故可进行十进制算术运算。参与加、减运算的操作数如图3-17所示。从图3-17可看出,加法和减法指令的目的操作数可以是累加器、任一通用寄存器或存储单元,但不能为立即数。第91页/共246页图3-17加减运算操作示意图第92页/共246页1.加法/减法指令ADD/SUB格式:ADDOPRD1,OPRD2SUBOPRD1,OPRD2
功能:
(1)ADD是将OPRD2的内容与OPRD1的内容相加,并将相加结果送到OPRD1中,替换掉OPRD1原来的内容,即OPRD1←OPRD1+OPRD2。
(2)SUB是用OPRD1的内容减去OPRD2的内容,并将相减结果送到OPRD1中,替换掉OPRD1原来的内容,即OPRD1←OPRD1-OPRD2。第93页/共246页
说明:①实现累加器与立即数,累加器与任一通用寄存器,累加器与存储单元内容相加/减,和/差放在累加器中。例3-38ADD AL, 30ADD AX, 3000HADD AX, SIADD AL, DATA[BX]SUB AX, BXSUB EAX, EDX第94页/共246页②实现任一通用寄存器与立即数相加/减,与累加器或另一个通用寄存器相加/减,与存储单元的内容相加/减,和/差放在寄存器中。例3-39ADD BX, 3FFHADD SI, AXADD DI, CXADD DX, DATA[BX+SI]SUB DX, 3FFHSUB DI, AXSUB BX, CXSUB BX, BUF[BX+SI]第95页/共246页③实现存储器操作数与立即数相加/减,与累加器或别的寄存器相加/减,和/差放至此存储单元中。
例3-40ADD BETA[SI],100ADD BETA[SI],AXADD BETA[SI],DXSUB BUF[SI],200SUB BUF[SI],AXSUB BUF[SI],DX第96页/共246页④段寄存器CS和指令指针IP不能作为OPRD1。OPRD1和OPRD2可以是字节、字或者双字,但是长度应当相等。⑤加减指令对标志位CF、OF、PF、SF、ZF和AF的影响如下:X---XX-X-X-XOFDFIFTFSFZF
AF
PF
CF第97页/共246页
2.带进位的加法指令ADC/带借位的减法指令SBB格式:ADCOPRD1,OPRD2SBBOPRD1,OPRD2
功能:这两条指令与ADD和SUB指令类似,只是在两个操作数相加/减时,要加/减进位标志CF的现行值,结果送至目的操作数:
(1)ADC是将OPRD2的内容、OPRD1的内容和进位标志CF内容相加,并将相加结果送到OPRD1,即OPRD1←OPRD1+OPRD2+CF。
(2)SBB是用OPRD1的内容减去OPRD2的内容再减去进位标志CF内容,并将相减结果送到OPRD1,即OPRD1←OPRD1-OPRD2-CF。第98页/共246页
例3-41
指令ADCECX,EAX实现的功能是将ECX内容、EAX的内容与CF内容相加,相加结果送到EAX中;指令SBB[DI],100实现的功能是用DS∶[DI]所指单元的内容减去100再减去CF内容,结果送到DS∶[DI]指向的字节单元中。说明:ADC/SBB指令主要用于多字节运算中。在80x86中可以进行8位运算、16位运算,也可以进行32位运算,但是32位二进制数的表达范围仍然是很有限的。为了扩大数的范围,仍然需要多字节运算。第99页/共246页
例3-42
在8086中可以进行8位运算和16位运算,若要进行32位的运算,直接使用加减法指令就不行了。现有两个四字节的数相加,加法要分两次进行,先进行低两字节相加,然后再做高两字节相加。在高两字节相加时要把低两字节相加以后的进位考虑进去,就要用到带进位的加法指令ADC。设这两个四字节的数已分别放在自FIRST和SECOND开始的存储区中,每个数占四个存储单元,存放时低字节存放在低地址处,实现这两个四字节的数相加的程序段描述如下:第100页/共246页MOV AX,0MOV BX,OFFSETFIRSTADD AX,[BX]MOV DX,OFFSETSECONDADD AX,[DX]MOV THIRD,AXMOV AX,[BX+2]ADC AX,[DX+2]MOV THIRD+2,AX第101页/共246页
例3-43
在80486中,若要完成64位加、减法运算,可用下述程序段:ADDEAX,ECX;EBX∶EAX←(EBX∶EAX)+(EDX∶ECX)ADCEBX,EDXSUBEAX,ECX;EBX∶EAX←(EBX∶EAX)-(EDX∶ECX)SBBEBX,EDX
由此可看出,在80486中,64位加、减法运算的实现,通常要综合使用ADD/SUB和ADC/SBB指令。第102页/共246页②ADC和SBB指令对标志位的影响如下:X---XX-X-X-XOFDFIFTFSFZFAFPFCF第103页/共246页
3.加1/减1指令INC/DEC
格式:INCOPRDDECOPRD
功能:完成对指定的操作数OPRD加/减1,然后返回此操作数:
INC是将OPRD的内容加1,并将结果送回到OPRD中,即OPRD←OPRD+1;
DEC是将OPRD的内容减1,并将结果送回到OPRD中,即OPRD←OPRD-1。第104页/共246页
说明:①这是单操作数的指令,常用于在循环程序中修改地址指针和循环次数等。例3-44在例3-25中,实现100个数据的传送时,使用了指令:INCSI和INCDI,其功能是每传送完一个字节的数据后,源、目的地址均要增1,而DECCX是每传送完一个字节的数据后,计数器的值减1。第105页/共246页②INC指令和DEC指令对标志位的影响如下:
由此可看出,INC/DEC指令影响标志位AF、SF、ZF、PF、OF,但不影响CF。所以用INC/DEC进行循环计数时,试图以判断CF=1来结束循环是不行的,而且还会导致程序运行进入死循环。这点要特别注意。③INC/DEC指令的操作数可以是通用寄存器,也可以是存储单元。X---XX-X-X--OFDFIFTFSFZFAFPFCF第106页/共246页
4.互换相加指令XADD
格式:XADDOPRD1,OPRD2
功能:将OPRD1(8位、16位或32位寄存器或存储单元)与OPRD2(8位、16位或32位寄存器)的值相加,结果存于OPRD1中,同时将相加前OPRD1的内容送到OPRD2中。说明:①XADD实现的交换是在通用寄存器与累加器之间、通用寄存器之间、通用寄存器与存储器之间进行,但段寄存器不能作为一个操作数。第107页/共246页例3-45XADD AL,CLXADD AX,DIXADD BX,SIXADD EAX,ECXXADD NUMBLE,EBX第108页/共246页②XADD是80486新增的指令,它对标志位的影响与ADD/SUB指令的相同,即影响的标志位有:CF、AF、SF、ZF、PF、OF。③该指令可带LOCK前缀,前缀的概念将在5.5节中介绍。
例3-46
设(CL)=13H,(AH)=34H,执行指令
XADDCL,AH的结果是:(CL)=13H+34H=47H,(AH)=13H。第109页/共246页
5.求补指令NEG
格式:NEGOPRD
功能:对OPRD取补,即相当于执行“OPRD←0-OPRD”操作。说明:①NEG指令实质上执行的是减法操作。它改变的是操作数的符号,即将正数变成负数或将负数变成正数,但绝对值不变。第110页/共246页
例3-47若(AH)=13H,执行NEGAH指令后,(AH)=0EDH;若(BX)=03H,执行NEGBX指令后,(BX)=0FFFFDH。②OPRD可以是字节或字操作数。③NEG指令对标志位的影响与SUB指令相同,即影响的标志位有:CF、AF、SF、ZF、PF、OF。第111页/共246页
6.比较指令CMP
格式:CMPOPRD1,OPRD2
功能:用OPRD1的内容减去OPRD2的内容,结果反映在标志位上但相减结果并不送到OPRD1。说明:①累加器与立即数、任一通用寄存器或任一内存操作数相比较。例3-48CMP AL,100CMP AX,SICMP AX,DATA[BX]第112页/共246页②任一寄存器与立即数、另一个寄存器或任一内存操作数相比较。例3-49CMP BX,04FEHCMP DX,DICMP CX,COUNT[BP]第113页/共246页③内存操作数与立即数、任一寄存器相比较。例3-50CMP DATA,100CMP COUNT[SI],AXCMP POINTER[DI],BX第114页/共246页④比较指令的用途:用于比较两个数之间的关系,即两者是否相等,或两个中哪一个大。在比较指令之后,根据ZF标志即可判断两者是否相等。若两者相等,相减以后结果为零,ZF标志为1,否则为0。若两者不相等,则可在比较指令之后利用其它标志位的状态来确定两者的大小。如果是两个无符号数进行比较,则在比较指令之后,可以根据CF标志的状态判断两数大小。方法如下:方法1如果是两个无符号数进行大小的比较,在比较指令执行完后,可根据CF标志的状态判断这两个数的大小。第115页/共246页
例3-51CMP AX,BX
根据CMP指令的功能,应做AX-BX的操作。若结果没有产生借位(CF=0),则AX≥BX;若产生了借位(CF=1),则AX<BX。方法2带符号数的比较。此时无法根据某一标志或SF标志或CF标志来判断两数的大小。例如,在例3-51中,令AX=-2,BX=127,执行CMPAX,BX,即进行-2与127的比较,这里-2<127。比较指令使两数相减:11111110(-2)-01111111(127)01111111第116页/共246页
结果的符号为0。若用SF标志判别两数大小,则认为两数相减后结果为正,从而得出-2>127的错误结果。这就是说,在带符号数的比较中,根据单一标志(或SF标志或CF标志)来判断两数的大小是不行的。实际上,对两个带符号数作减运算时,有可能产生溢出,使SF标志或CF标志不能正确地反映运算的真实结果。那么,应如何判断两个带符号数的大小呢?可作如下分析:在CMPAX,BX中,若AX与BX中的数同符号,即AX>0、BX>0或AX<0、BX<0,则AX-BX不会产生溢出,此时可用SF标志判断两数大小,即SF=0,则AX>BX;SF=1则AX<BX。若AX与BX中的数不同符号,即AX>0、BX<0或AX<0、BX>0,那么AX-BX则可能会产生溢出。若AX-BX没有产生溢出,则仍然可用SF标志判断两数大小,符合上述规律;但是若AX-BX产生了溢出,则是当SF=1时,AX>BX;SF=0时AX<BX。第117页/共246页
综上所述,可得如下结论(设待比较的两个数分别是A、B):当没有溢出(OF=0)时,若SF=0,则A>B
若SF=1,则A<B
当产生溢出(OF=1)时,若SF=0,则A<B
若SF=1,则A>B
进而:若OF“异或”SF=0,则A>B
若OF“异或”SF=1,则A<B
正是考虑了上述的情况,在80x86转移指令中,设置了两组转移指令,分别用于无符号数比较和有符号数的比较。转移指令将在第5章中讲述。第118页/共246页
例3-52
编制一求最大值的汇编程序段。分析:若自BLOCK开始的内存缓冲区中,有100个带符号数,若要找出其中的最大值,把它存放到MAX单元中。可先把数据块的第一个数取至AX中,然后从第二个存储单元开始,依次与AX中的内容相比较,若AX中的值大,接着进行下一次比较;若AX中的值小,则把内存单元的内容送至AX中。这样,经过99次比较,在AX中的必然是数据块中的最大值,再把它存至MAX单元中。因为要进行99次比较,应使用循环程序。在每一循环中要用比较指令,然后用转移指令来判断大小,循环开始前要置初值。第119页/共246页求最大值的程序段描述如下:MOV BX,OFFSETBLOCK;将数据区中的第一个数的地址送BXMOV AX,[BX];将要比较的第一个数送AXINC BX;地址增1INC BX;地址再增1MOV CX,99;比较的循环次数送CXAGAIN: CMP AX,[BX];比较两数,另一比较的数在BX指示的单元中JG NEXT;AX中的数大MOV AX,[BX];[BX]中的数大,当前最大数送AXNEXT: INC BX;地址增1INC BX;地址再增1DEC CX;循环次数减1JNE AGAIN;比较未结束,进行比较MOV MAX,AX;为0,AX中的数最大,送MAX单元HLT第120页/共246页
7.比较交换指令CMPXCHG
格式:CMPXCHGOPRD1,OPRD2
功能:先将目的操作数O
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商家合作协议合同
- 农业技术服务合同协议
- 人力资源招聘合同
- 房改房二手房买卖合同
- 服务器维护服务类合同
- 集体土地买卖合同
- 砂石材料供货合同
- 智慧园区开发建设合同
- 设备买卖居间合同
- 山西金融职业学院《数据可视化理论与实践》2023-2024学年第二学期期末试卷
- 姜晓龙-麦田除草剂爱秀的开发-先正达
- 部编人教版三年级下册语文:荷花课件
- 多联机空调系统设计课件
- 螺纹牙强度校核计算
- 技术规范书柴油发电机组
- 青岛科技大学成人大专《工商企业管理实训报告》
- 低钾血症最新版本最新课件
- 2023年陕西延长石油矿业有限责任公司招聘笔试题库及答案解析
- YY/T 1792-2021荧光免疫层析分析仪
- GB/T 39235-2020猪营养需要量
- GB/T 30799-2014食品用洗涤剂试验方法重金属的测定
评论
0/150
提交评论