




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章编程中的高级处理技术
7.1移位指令与应用
7.2串操作
7.3宏
*7.4重复汇编
本章要点
习题七返回章目录第7章编程中的高级处理技术返回章目录7.1移位指令与应用7.1.1逻辑左移【指令格式】SHL
d1,d2【功能】把操作数d1的各个二进制位依次向左移动d2位,移动造成右边的空位填0,结果放回操作d1中。【说明】(1)操作数d1必须是通用寄存器或内存型寻址方式,必须有确定的类型,可以是字节型,也可以是字型,并且对内存型寻址方式可以使用段跨越。7.1移位指令与应用(2)操作数d2表示移动的位数,只能是立即数1或者寄存器CL,当移动位数超过1位时,必须把移动位数放在CL中,以CL作为d2操作数。(3)操作数d1各位移动的情况如图7.1所示,从最高位起,将有d2位移到操作数d1之外,除了最后移出的一位放到标志位CF中之外,其余各位均被丢弃,移动造成右边的空位用0填充。……位号:15/714/6 100CF 操作数d1
(2)操作数d2表示移动的位数,只能是立即数1或者(4)移动后d1中的数据是在其原值的后面加了d2个0,即把原数值扩大了倍,当扩大后的值超过表示范围时,超过d1类型(字节或字)规定位数的高位部分会自动丢失。(5)该指令对其余标志位的影响情况是:移动后的结果为0则ZF置1,否则ZF清0;移动后d1最高位的值会复制到SF上;如果移动前后d1的最高位不同则OF置1,否则OF清0。移位指令涉及数值计算问题,但并不复杂。比如AX的值是8D56H,CL的值是3,则下面几条指令是SHL指令的正确用法,后面也给出了移位后的结果:SHL AL,1 移位后,AL=0ACH,CF=0,AH不变SHL AX,1 移位后,AX=1AACH,CF=1SHL AH,CL移位后,AH=68H,CF=0,AL不变SHL AX,CL移位后,AX=6AD0H,CF=0(4)移动后d1中的数据是在其原值的后面加了d2个7.1.2算术左移【指令格式】SALd1,d2【说明】这是一条与SHL完全相同的指令,该指令与SHL指令是同一条机器指令的两种不同写法。
7.1.2算术左移
7.1.3逻辑右移【指令格式】SHRd1,d2【功能】把操作数d1的各个二进制位依次向右移动d2位,移动造成左边的空位填0,结果放回操作数d1中。【说明】(1)对两个操作数的语法限制以及对标志位的设置情况都与SHL指令相同,见SHL指令说明的(1)、(2)和(5)。(2)SHR指令在位的移动方向上与SHL指令刚好相反,其它方面则很类似,向右移出的最后一位放到CF中,右移造成左边的空位以0填充,如图7.2所示。7.1.3逻辑右移(3)移动后的值是把d1中的原值作为无符号数,除以的商。位号:15/714/6 1 0操作数d1 CF图7.2逻辑右移指令SHR的功能……(3)移动后的值是把d1中的原值作为无符号数,除以的商。7.1.4算术右移【指令格式】SARd1,d2【功能】把操作数d1的各个二进制位依次向右移动d2位,移动造成左边的空位填d1原值的最高位,结果放回操作d1中。【说明】SAR指令的功能基本上与SHR的一样,仅仅是移动造成的空位填充方式不同,如果操作数d1移动前最高位是1,则移动造成的空位以1填充,否则以0填充,如图7.3所示。SAR指令执行的结果是把d1中的原值作为带符号数,除以并把除法的商放回d1中。7.1.4算术右移位号:15/714/6 1 0……
……操作数d1 CF图7.3算术右移指令SAR的功能位号:15/714/6 1 0…………
7.1.5循环左移【指令格式】ROL
d1,d2【功能】把操作数d1的各个二进制位向左移动d2位,从d1左端移出的每一位再依次移到右端空出的位上,最后移出的一位还要送到CF中。可以把d1的各位看作是首尾相接的一个环状,如图7.4所示,把各位的值按逆时针方向旋转d2格,再从环原先的连接部断开,可以得到ROL指令执行后的结果。7.1.5循环左移14/615/7CF01图7.4循环左移指令ROL的功能……14/615/7CF01图7.4循环左移指令ROL的功能
7.1.6循环右移【指令格式】ROR
d1,d2【功能】把操作数d1的各个二进制位向右移动d2位,从右端移出的各位再依次移到d1右端空出的位上,最后移出的一位还要送到CF中。ROR是循环右移指令,与ROL指令相比,只是移位的方向不同,把图7.4中的移动方向改为顺时针方向,从第0位上最后一次移出的位送到CF中,就是ROR指令的功能。7.1.6循环右移
7.1.7带进位的循环左移【指令格式】RCL
d1,d2【功能】把操作数d1的各位与CF联合在一起,构成9个或者17个二进制位,向左移动d2位,从左端移出的各位再依次移到右端空出的位上。从功能上说,可以把d1的各位与CF一起,看作首尾相接的一个环状,如图7.5所示,把各位按逆时针方向旋转d2格,再从环原先的连接部断开,可以得到ROL指令执行后的结果,包括CF的设置情况。7.1.7带进位的循环左移14/615/7CF01图7.5带有CF的循环左移指令RCL的功能……14/615/7CF01图7.5带有CF的循环左移指令7.1.8带进位的循环右移【指令格式】RCR
d1,d2【功能】把操作数d1的各位与CF联合在一起,构成9个或者17个二进制位,向右移动d2位,从右端移出的各位再依次移到左端空出的位上。带进位CF的循环右移指令的功能可以参照图7.5,把移动方向改为顺时针即可。逻辑移位与算术移位指令除了功能本身描述的二进制位的移动之外,还用于把一个字节型或字型数据乘以/除以2n。乘除法指令是所有8088指令中最耗时的,所花费的时间是加减法的20~30倍,是移位指令的35~50倍,因此如果能用移位指令和加减法指令代替乘除法指令,将大大提高程序的执行速度。7.1.8带进位的循环右移【例7.1】编写程序段,把AX中的无符号数乘以8,如果有溢出,忽略超过16位的部分。【解】乘以8的操作可以通过在二进制数的后面加3个0完成,即左移3位,移出部分自动丢失。只需要在CL中放移动位数(3位),再用SHL指令移位即可:MOVCL,3SHLAX,CL对于双字型数据,或者位数更多的复杂数据,也可以用移位指令与逻辑运算指令配合,简化乘除法的运算。【例7.1】编写程序段,把AX中的无符号数乘以8,如果【例7.2】编写程序段分别完成下列计算。(1)把(DX,AX)构成的无符号双字除以4,商放在(DX,AX)中,余数放BX中。(2)把(DX,BX)构成的无符号数乘以17,结果仍放在(DX,BX)中,忽略溢出。【解】(1)二进制无符号数除以4,就是把它向右移动两位,高位补0,原二进制数的最低两位就是余数。MOVBX,AXANDBX,3 ;取被除数的最低两位,作为余数SHRDX,1 ;右移一位,移出位放到CF中RCRAX,1 ;右移一位,最高位以CF的值,即DX
的移出位填充SHRDX,1RCRAX,1【例7.2】编写程序段分别完成下列计算。(2)17可以看作(16+1),因此可以把BX先左移4位,结果记在(DX,BX)中,再与原数据相加。 MOVSI,BX ;保存BX的原值 MOVAX,BX ;保存BX的原值 MOVDI,DX ;保存DX的原值 MOVCL,4 SHLBX,CL ;低字BX左移4位 SHLDX,CL ;高字DX左移4位(2)17可以看作(16+1),因此可以把BX先左MOVCL,12SHRAX,CL ;取原数据的低字的左4位,放在AX的右4位上ORDX,AX ;把AX中存放的数据加到DX中ADDBX,SIADCDX,DIMOVCL,12在例7.2的第(1)小题中,由于没有直接的指令把双字型数据移位,所以通过CF作为过渡,连续做两次字型数据的移位,先把高字DX右移1位,移出位暂时放在CF中,再用带进位CF的循环右移指令,在把低字移位的同时,把暂存在CF中的那1位移到低字的最高位上。第(2)小题中移动的位数较多,如果用循环的方式实现就违背了提高处理速度的本意。程序段中用AX取出低字部分的值,右移12位,把应该从低字移到高字的4位放在了AX的最低4位上。再把高字DX用SHL指令左移4位,移出部分自动丢失,右4位补0,最后把AX中存放的4位数据用OR指令(也可以用ADD指令)放到DX的低4位上,从而实现双字(DX,BX)乘以16的操作。在例7.2的第(1)小题中,由于没有直接的指令7.2串操作
汇编语言中的“串”是指内存中连续存放的若干个字节型或字型数据构成的一个整体,相当于一个数组。8088为这种“数组”的操作提供了专门的串操作指令,这些指令与循环或附加在串指令上的前缀配合,可以依次对串中的数据进行处理。串操作指令都要求先把数组首元素(或者最后一个元素)的地址放在指定的变址寄存器中,每处理一个数组元素,串指令本身自动把变址寄存器的内容做相应的变化,使其指向下一个待处理的元素。根据实际需要,串操作指令可以按数组存放的内存地址从小到大进行处理,也可以从大到小处理,CPU在完成串指令时,会根据标志寄存器中的DF标志位选择处理的方向。7.2串操作7.2.1DF标志位DF是8088中的一个重要的控制标志位,它决定了串指令的处理方向。当CPU执行到一条串操作指令时,如果DF的值是0,CPU会把指令相应的变址寄存器的值增加,按地址由小到大的方向处理;反之如果DF的值是1,CPU会把变址寄存器的值减小,按地址由大到小的方向处理。8088提供有两条专用指令设置DF,分别是CLD和STD指令。【指令格式】CLD【功能】把标志位DF清0。【指令格式】STD【功能】把标志位DF置1。7.2.1DF标志位
7.2.2串操作指令8088指令系统中共设计有5条串操作指令,分别用于完成从串中取出数据、往串中存入数据、串复制、串比较等操作。7.2.2.1LODS指令──从串中取出数据按照串中存放的是字节型数据还是字型数据,有两条指令分别用于从串中取出一个元素。【指令格式】LODSB或LODSW【功能】(1)LODSB进行字节型串操作,从内存中DS:SI所确定的逻辑地址处取出一个字节的数据,送到AL中。当DF=0时,令SI←SI+1,当DF=1时,令SI←SI-1。7.2.2串操作指令(2)LODSW进行字型串操作,从内存中DS:SI所确定的逻辑地址处取出一个字型数据,送到AX中。当DF=0时,令SI←SI+2,当DF=1时,令SI←SI-2。本书中把LODSB指令和LODSW指令统称作LODS指令,以下各串操作指令也做类似处理。LODS指令要求把串放在DS所指向的段中,SI则存放将要处理的元素的偏移地址。对字节型的串,每个元素占1字节,所以执行一次LODSB指令,SI中的值会根据DF的情况自动加1或减1;而字型的串中每个元素占2字节,SI需要加2或减2后才能指向下一个元素。串指令LODS实际上是把一条MOV指令和一条ADD(或SUB、INC、DEC等)指令综合在一起,可以说,没有串指令同样可以编写数组操作的程序,但串指令会使这种操作简化。(2)LODSW进行字型串操作,从内存中DS:SI【例7.3】设DS段中的变量arr中存放了一个带符号的字型数组,元素个数已放在字型变量arrlen中(>0)。编写程序段,利用串操作指令,统计出该数组中正数、0和负数各多少个,结果分别放在DS段中的字型变量countp、count0和countn中。【解】 MOVCX,[arrlen] MOV[countp],0 MOV[count0],0 MOV[countn],0 LEASI,arr ;DS已有正确值,只要把SI 指向串首地址 CLD ;清方向标志【例7.3】设DS段中的变量arr中存放了一个带符号的字lab1: LODSW CMPAX,0 JGlab2 ;大于0转 JLlab3 ;小于0转 INC[count0] JMPlab4lab2: INC[countp] JMPlab4lab3: INC[countn]lab4: LOOPlab1lab1: LODSW7.2.2.2STOS指令──往串中存入数据【指令格式】STOSB或STOSW【功能】(1)STOSB进行字节型串操作,把AL的值送往内存中由ES:DI所确定的内存中。当DF=0时,令DI←DI+1,当DF=1时,令DI←DI-1。(2)STOSW进行字型串操作,把AX的值送往内存中由ES:DI所确定的内存中。当DF=0时,令DI←DI+2,当DF=1时,令DI←DI-2。STOS指令主要用于把一段连续的存储区域以AL或AX中的值填充,特别的是,存储区的段地址必须放在附加段寄存器ES中。STOS与LODS指令配合,还可以从一个串中取出数据,有选择地存到另一个串中。7.2.2.2STOS指令──往串中存入数据【例7.4】设DS段中的变量arr1中存放了一个带符号的字型数组,元素个数已放在字型变量arr1len中(>0)。编写程序段,试利用串操作指令,把该数组中非0元素复制到DS段中的另一个字型变量arr2中,要求在arr2中连续存放,并统计出非0元素的个数填在变量arr2len中。【分析】首先把DS、SI、ES和DI指向正确的位置,然后利用循环指令,每次从arr1中取出一个数,若不是0,则存往arr2。由于是字型数据,循环结束后DI的值减去arr2的偏移地址可得到保存下来的数据占据了多少字节,除以2后即得元素个数。
【例7.4】设DS段中的变量arr1中存放了一个带符号【解】 PUSHDS POPES ;令ES←DS LEASI,[arr1] LEADI,[arr2] MOVCX,[arr1len] CLD ;准备好取出数据的串和存 入数据的串的首地址【解】lab1: LODSW TESTAX,AX JZlab2 ;AX为0转 STOSWlab2: LOOPlab1 SUBDI,OFFSETarr2 SHRDI,1 ;除以2 MOV[arr2len],DIlab1: LODSW7.2.2.3MOVS指令──串复制【指令格式】MOVSB或MOVSW【功能】(1)MOVSB进行字节型串复制,把DS:SI所指向的一个字节型数据送往ES:DI所指向的内存中。当DF=0时,令SI←SI+1,DI←DI+1;当DF=1时,令SI←SI-1,DI←DI-1。(2)MOVSW进行字型串复制,把DS:SI所指向的一个字型数据送往ES:DI所指向的内存中。当DF=0时,令SI←SI+2,DI←DI+2;当DF=1时,令SI←SI-2,DI←DI-2。7.2.2.3MOVS指令──串复制MOVS指令可以实现把内存中的一个数据,不经过寄存器的过渡由一处复制到另一处。这一点是MOV指令做不到的。MOVS指令与循环控制指令配合,可以完成数据块的复制。被复制的数据串称为源串,复制到的目的地称为目标串。如果源串与目标串所占据的内存是完全分离的,数据传递可以按由串首至串尾的次序进行,也可以按相反的方向进行。但是,当两者占据的内存区域有部分重叠时,需要注意用DF控制方向,当源串首地址小于目标串首地址时,应由尾至首进行传送,源串首址大于目标串首址时,则由首至尾传送。MOVS指令可以实现把内存中的一个数据,不经【例7.5】设字节型变量str中存放了100个字符,编写程序段完成下列操作:(1)删除串中前5个字符,并把后续字符前移。(2)把串中各字符向后移一个字节,在串首插入一个空格符。【分析】第(1)题要把串的后95个字节向前移动,是源串首址大于目标串首址的情况,需要自首至尾进行移动;第(2)题正相反,源串首址小于目标串首址,只能按由尾至首的方向移动。【例7.5】设字节型变量str中存放了100个字符,【解】(1) MOVAX,SEGstr ;取变量str所在的段地址 MOVDS,AX MOVES,AX LEASI,[str+5] ;取源串首偏移地址 LEADI,[str] ;取目标串首偏移地址 MOVCX,95 ;置复制字节数 CLD lab: MOVSB ;字节型复制 LOOPlab【解】(2) MOVAX,SEGstr MOVDS,AX MOVES,AX LEASI,[str+99] ;取源串尾的偏移地址 LEADI,[str+100] ;取目标串尾的偏移地址 MOVCX,100 ;复制100个字节 STD lab: MOVSB LOOPlab MOV[str],''(2) MOVAX,SEGstr7.2.2.4CMPS指令──串比较【指令格式】CMPSB或CMPSW【功能】(1)CMPSB进行字节型串比较,把DS:SI所指向的一个字节型数据与ES:DI所指向的一字节相减,把相减结果反映到条件标志位上。当DF=0时,令SI←SI+1,DI←DI+1;当DF=1时,令SI←SI-1,DI←DI-1。(2)CMPSW进行字型串比较,把DS:SI所指向的一个字型数据与ES:DI所指向的一个字相减,相减结果反映到条件标志位上。当DF=0时,令SI←SI+2,DI←DI+2;当DF=1时,令SI←SI-2,DI←DI-2。程序设计中经常会遇到比较问题,比较两个符号串是否完全相同,或者比较两个串按字典顺序的大小,这一类问题正是CMPS指令发挥作用的地方。7.2.2.4CMPS指令──串比较【例7.6】编写子程序,按字典排序法,比较两个已知长度的字符串的大小。【解】;入口参数:DS:SI和ES:DI分别存放第1个串和第2个串的起始逻辑地址;CX和DX分别放两个串的串长;出口参数:AL为1表示第1个串大,AL为-1表示第2个串大,AL为0表示两者相等;破坏寄存器:AH,CX,SI,DI【例7.6】编写子程序,按字典排序法,比较两个已知长度strcmpPROCNEARCLDMOVAH,0 ;记载串长1<串长2CMPCX,DXJBlab1MOVAH,1 ;记载串长相等JElab1MOVCX,DX ;按第2个串的长度进行比较MOVAH,2 ;记载串长1>串长2lab1:JCXZlab2CMPSBJAlab3 ;串1>串2转JBlab4 ;串1<串2转LOOPlab1strcmpPROCNEARlab2:CMPAH,1JBlab4 ;串1<串2转JAlab3 ;串1>串2转MOVAL,0JMPlab5lab3:MOVAL,1JMPlab5lab4:MOVAL,-1lab5:RETstrcmpENDPlab2:CMPAH,17.2.2.5SCAS指令──串扫描【指令格式】SCASB或SCASW【功能】(1)SCASB把AL与字节型串中数据比较,用AL减去ES:DI所指向的一个字节型数据,相减结果反映到条件标志位上。当DF=0时,令DI←DI+1;当DF=1时,令DI←DI-1。(2)SCASW把AX与字型串中数据比较,用AX减去ES:DI所指向的一个字,结果反映到条件标志位上。当DF=0时,令DI←DI+2;当DF=1时,令DI←DI-2。SCAS指令通常用于查找一个数组中是否存在某个指定的值。该指令不改变数组中的任何数据,也不改变AX或AL的值,可以用循环控制的方法连续查找。7.2.2.5SCAS指令──串扫描【例7.7】编写子程序,查找一个字型数组中是否存在一个给定的值。【解】;入口参数:ES:DI存放字型数组的首地址,CX中放串中元素个数;AX放指定查找的值;出口参数:CF为1表示找到,CF为0表示没找到;破坏寄存器:CX,DI【例7.7】编写子程序,查找一个字型数组中是否存在一个searchPROCNEARJCXZlab0CLDlab1:SCASWJElab2LOOPlab1lab0:CLCJMPlab3lab2:STClab3:RETsearchENDPsearchPROCNEAR
7.2.3串重复前缀串操作指令是对内存中连续存放的一批数据进行处理的一种高效、快捷的方法,它往往需要循环控制指令的配合。对于那些单纯是数据块复制、查找、比较的操作,汇编语言中还设计有3个串操作重复前缀,以进一步提高编程和数据处理的效率。串操作前缀是附加在串操作前面的指令,它是一种以CX为计数器的重复操作指示器,用以简化循环操作控制。使用串操作前缀的一般格式是:串前缀串操作指令7.2.3串重复前缀7.2.3.1REP前缀【功能】当CX的值不是0时,重复执行后面的串操作指令,每执行一次,把CX的值减1,直到CX=0为止。图7.6描述了REP串前缀的功能。REP前缀将使它后面的串操作指令重复执行,每执行一次串指令就把CX的值减1,直到CX减到0为止。图7.6描述了带有REP前缀的串指令的执行方式。可以看到,这是一种先判断后重复的循环,如果CX的值是0,则串操作指令一次都不执行,这与LOOP指令控制的循环是不同的。7.2.3.1REP前缀CX=0?CX←CX-1执行一次后面的串指令YN完成图7.6REP前缀的功能REP前缀通常加在MOVS或STOS串指令的前面,可以用一条指令把一个串复制到内存的另一个地方,或者把一段内存区域用一个特定值填充。REP前缀一般不与另外3条串指令连用。CX=0?CX←CX-1执行一次后面的串7.2.3.2REPZ和REPNZ前缀REPZ和REPNZ也是串指令前缀,与REP一样都是用于控制后面的串指令重复执行,但重复执行不仅依赖于CX的值,还依赖于标志寄存器中的ZF标志位。【功能】带有REPZ前缀的串指令按下列方式执行:(1)若CX=0,则结束指令的执行,否则转(2)。(2)CX←CX-1。(3)执行一次串指令。(4)若ZF=0,则结束指令的执行,否则转(1)。REPNZ的功能与REPZ仅在第(4)项不同,REPZ是在ZF=1时控制串操作重复执行,而REPNZ则是在ZF=0时控制串操作重复执行。REPZ和REPNZ的功能可以用图7.7描述。7.2.3.2REPZ和REPNZ前缀CX=0?CX←CX-1执行一次后面的串指令 ZF=1?YNNY完成(a)REPZ串前缀的功能 CX=0?CX←CX-1执行一次后面的串指令 CX=0?CX←CX-1执行一次后面的串指令 ZF=0?YNNY完成(b)REPNZ串前缀的功能REPZ和REPNZ前缀通常加在CMPS或SCAS串指令的前面,完成连续比较操作。这两个前缀各自又有一种功能完全相同的变形,REPZ可以写作REPE,REPNZ可以写作REPNE。CX=0?CX←CX-1执行一次后面的串指令 7.2.3.3串前缀的应用根据串前缀与串指令的功能,什么样的串指令前面配什么样的串前缀是有一定限制的。表7.1列出了串前缀与串指令之间的配合关系,其中的“√”表示对应的串指令与串前缀可以配合使用,“×”表示不能,“△”表示相应的用法没有实用价值。7.2.3.3串前缀的应用串前缀串指令REPREPZ(REPE)REPNZ(REPNE)LODS△××STOS√××MOVS√××CMPS×√√SCAS×√√表7.1串前缀与串指令之间的配合关系
串前缀REPREPZREPNZLODS△××S从表7.1中可以看到,LODS指令一般不与串前缀配合使用,因为LODS是从串中取出数据放到AL或AX中,每取一个数据就应该做适当的处理,然后再去取下一数据,否则后取出的数据将取代AL或AX中的原有数据,使得只有最后一次取出的数据被保留下来。画有“×”的部分是指根本不存在这样配合的用法。实际上,8088的指令系统中只有两个机器码与串前缀对应,并且,对于MOVS、STOS和LODS,不论串指令的前面加的是什么前缀,都按REP进行处理,汇编程序在翻译时既不报错也不警告;对CMPS和SCAS指令,如果前面加上了前缀REP,汇编程序将按REPZ进行翻译。串前缀的用途在于代替控制串操作的循环结构,下面的例7.8和例7.9就是这种简化的典型用法。从表7.1中可以看到,LODS指令一般不与串前【例7.8】把字型变量v1中存放的50个整数复制到变量v2中,先用LOOP指令编写程序段完成复制操作,再用带前缀的串指令简化。【解】用循环控制方法编写的程序段如下:MOVAX,SEGv1MOVDS,AX ;准备源串的段地址MOVSI,OFFSETv1;准备源串的起始偏移地址MOVAX,SEGv2MOVES,AX ;准备目标串的段地址LEADI,v2 ;准备目标串的起始偏移地址MOVCX,50【例7.8】把字型变量v1中存放的50个整数复制到变量lab:MOVAX,[SI]MOVES:[DI],AXLOOPlab该程序段的最后3行可以用一个带前缀的串指令简化,写作:REPMOVSWlab:MOVAX,[SI]【例7.9】编写一个子程序,判断一个数据串中是否存在一个给定的值。要求子程序对字节型和字型的串都能判断,以CF作为出口参数,如果在串中找到目标值,在CF位置1,否则令CF清0。【解】;入口参数:ES:DI=数据串的首地址;AX=查找目标值,字节型数据串则以AL存放目标值;CX=串中元素个数;CF=0表示串中元素是字型,1则表示串中元素是字节型【例7.9】编写一个子程序,判断一个数据串中是否存在一;出口参数:CF=1表示在串中找到了给定值,0表示没找到;破坏寄存器:CX,DIsearchPROCNEARJCXZs2;串长为0,串中不存在给定数据,转CLD;清方向标志,准备按增量方向查找JCs3;入口参数CF为1转字节型查找REPNZSCASW;字型查找JZs1;找到转JMPs2;未找到转;出口参数:CF=1表示在串中找到了给定值,0表示没找s3:REPNZSCASB;字节型查找JZs1 ;找到转s2:CLC ;置未找到标记JMPs4s1:STC ;置找到标记s4:RETsearchENDPs3:REPNZSCASB从图7.7的流程图可以看到,带有REPZ和REPNZ前缀的串指令可以在两种情况下结束串操作,一是已执行到CX为0时,二是当ZF不符合要求时。例7.9中,在带有REPNZ前缀的串扫描指令的后面用条件跳转指令进行判断,此时必须能够分辨出是哪一种情况导致串操作结束。可以想到的指令除了JZ、JNZ之外,还有JCXZ,究竟用哪一个为好呢?如果串指令执行完后CX的值不是0,可以肯定是由于ZF不满足重复条件而导致串操作提前结束的,对例7.9就可以知道找到了目标值。这种情况下JCXZ或JZ、JNZ指令都可使用;反之若CX的值是0,表示串操作已经处理到串的最后一个元素,并且最后一次处理的结果已设置在ZF上,但这时如果用JCXZ指令进行判断,就不能分辨最后一次串操作比较或查找的结果是相等还是不等。总之,在带有REPZ或REPNZ前缀的串指令的后面,必须用JZ、JNZ指令判断比较或查找的情况,而不能用JCXZ指令。从图7.7的流程图可以看到,带有REPZ和R7.3宏程序中使用宏分为定义和调用两个部分。宏定义用来说明哪些指令或伪指令是将在程序中重复出现的程序段;宏调用是用来告诉汇编程序,在翻译前先把宏定义中的程序段复制一遍。可见,宏定义和宏调用都是告诉汇编程序如何处理,属于伪操作。7.3宏7.3.1宏定义【格式】宏名MACRO宏体ENDM【说明】(1)“宏名”是一个标识符,一个程序中可以定义多个宏,对每一个宏必须以不同的标识符命名,且宏名不能与变量、标号、段名等标识符同名。(2)汇编语言规定,宏定义的起始标记MACRO前面必须写宏的名字,而结束标记ENDM的前面却不允许写任何内容,写在起止标记之间的部分称为宏体,宏体部分通常是一段程序中需要重复使用的指令序列。7.3.1宏定义(3)宏定义仅仅用来告诉汇编程序,将来宏调用时复制的对象是什么,宏定义中的程序段并不是程序的一部分,也就是说,如果程序中定义了一个宏而没有调用它,汇编程序将忽略宏定义。(4)宏定义可以写在程序的任何地方,但习惯上总是把宏定义写在程序的最前面。宏定义与编辑器中的文字块的定义有相似之处,也有一些差别。两者都需要以特定的方式说明开始和结束的位置。文字块是文件的一部分,而宏体中的程序段必须经过宏调用才能复制到源程序中正确的位置,没有被调用的宏体在汇编程序翻译时会被忽略。(3)宏定义仅仅用来告诉汇编程序,将来宏调用时复制7.3.2宏调用定义后的宏名又称为宏指令。经宏定义后,就可以在源程序中调用宏了。宏调用的方式是在源程序中需要复制宏体的地方写宏的名字。宏名单独占一行,当源程序被汇编时,汇编程序将对宏调用进行宏体复制,并取代宏名,这种复制操作称为宏展开。为了与源程序的其它部分相区别,后面的叙述中,对由宏调用而展开后得到的指令,都在前面标以加号“+”以示区别。7.3.2宏调用【例7.10】参照汇编程序的处理方法,对下面程序中的宏进行展开。back=4CHdosintEQU21HdispchMACROMOVAH,2MOVDL,'*'INT21HENDM【例7.10】参照汇编程序的处理方法,对下面程序中的宏codeSEGMENTASSUMECS:codemain:dispchdispchMOV AH,backINT dosintcodeENDSEND maincodeSEGMENT【解】宏展开后的结果是:+MOV AH,2+MOV DL,'*'+INT 21H+MOV AH,2+MOV DL,'*'+INT 21HMOV AH,4CHINT 21H【解】宏展开后的结果是:由于宏展开是汇编程序翻译的一个步骤,宏展后的结果并不是源程序,所以展开后不再写出完整的程序格式,只列出有效指令部分。可以看到,汇编程序对宏调用与已定义的常量及符号的引用的处理是很类似的,定义部分在汇编处理结束后就已完成它的作用。汇编程序翻译后得到的机器代码中没有宏、常量等的定义,只是调用或引用部分被代换成宏体或定义的内容。宏与常量定义及符号定义的差别在于,常量及符号定义都必须在一行写完,对常量和符号的引用只能代换指令中的操作数,或者操作数的一部分,宏调用则可以代换一段程序。不仅如此,宏还允许代换的内容有个别地方不同,这是通过带参数的宏实现的。由于宏展开是汇编程序翻译的一个步骤,宏展后的
7.3.3带参数的宏如果宏只能对完全相同的程序段进行复制,那就没有多大的应用价值了,宏的好处主要体现在每次调用而展开的宏体可以不同。这需要在宏定义时以形式参数指明宏体中的哪些部分可以被不同的实际参数代替,每次调用时在宏名字的后面附带实际参数。完整的宏定义格式是:宏名MACRO[形式参数表]宏体ENDM形式参数可以出现在宏体中的任何位置,可以在操作数中,可以在指令助记符的位置,甚至还可以是其中的一部分。下面的几个例子用来说明参数的各种不同用法。7.3.3带参数的宏【例7.11】普通用法,形式参数出现在操作数的位置。dchMACROxMOVAH,2MOVDL,xINT 21HENDM源程序中调用宏dch时,应该在宏名字的后面跟一个实际参数,从例7.11的宏体可以看出,这个实际参数应该是用于屏幕显示的一个ASCII字符。因而,源程序中用下面的写法连续两次调用上述宏,就可以实现回车换行操作。宏展开时,对每一次宏调用,将分别以相应的实际参数代换宏体中的形式参数。dch13dch10【例7.11】普通用法,形式参数出现在操作数的位置。【例7.12】形式参数可以出现在助记符的位置。ccMACROcmd,lab CMPAX,BX cmdlab ENDM上述宏在调用时可以用不同的实际参数代换形式参数cmd,使得宏体中的第2行是不同的指令。比如下面是几个调用的例子,请读者自己写出宏展开的结果。ccJG,n1ccJBE,n2ccJNZ,n3【例7.12】形式参数可以出现在助记符的位置。【例7.13】宏的形式参数可以作为一个标识符的一部分。这时,必须用符号“&”把形式参数与标识符的其余部分分开。例7.12中的宏定义还可以写成下面的形式:cc1MACROcmd,labCMPAX,BXJ&cmdlabENDM【例7.13】宏的形式参数可以作为一个标识符的一部分。宏体中第2行的J&cmd就是在一个标识符中(例7.13中表现为指令助记符)含有形式参数,符号“&”用于把形参cmd从标识符中分离出来。如果没有分隔符号“&”,汇编程序将把Jcmd作为一个整体处理,而不知道其中的cmd是形参。对例7.12后面的3个调用,调用例7.13中的宏可以达到同样的效果,相应写法是:cc1G,n1cc1BE,n2cc1NZ,n3宏体中第2行的J&cmd就是在一个标识符中【例7.14】形式参数还可以出现在变量定义伪操作的初值表中,甚至是以字符串形式出现的初值。msgMACROnum,pnamevar&numDB'HELLO,&pname'ENDM汇编语言规定,字符串中的形参必须用分隔符“&”从其它部分分离出来。对于下面两个宏调用, msg1,John msg2,Henrry宏展开的结果是: +var1DB'HELLO,John' +var2DB'HELLO,Henrry'【例7.14】形式参数还可以出现在变量定义伪操作的初值
*7.3.4宏操作中形参与实参的对应关系由于宏是伪操作,形参与实参的对应方法是由汇编程序决定的,与高级语言中形参与实参的对应方式有很大的不同。汇编语言规定:(1)形参表中的多个参数项之间必须用逗号分隔,但实参表的各个参数项可以用逗号也可以用空格分隔。(2)如果形参的数目与实参的数目相等,则按照形参表与实参表中各参数项的次序一一对应。(3)如果形参数目少于实参数目,多余的实参被忽略,汇编程序不做任何提示。*7.3.4宏操作中形参与实参的对应关系(4)如果形参数目多于实参数目,不足的实参作空串处理,汇编程序也不做提示。(5)如果实参中包含逗号、空格等分隔符作有效符号,必须用尖括号“<>”括起来,避免混淆。(4)如果形参数目多于实参数目,不足的实参作空串处【例7.15】设有宏定义如下:dataMACROp,qv&pDBqENDM以及下面的宏调用:x=1data%x,%xx=x+1data%x,%x其宏展开结果是:+v1DB1+v2DB2【例7.15】设有宏定义如下:符号“%”的作用体现在宏展开中是用常量标识符x的值(第1次宏调用时是1,第2次宏调用时是2),而不是符号x本身,去替换宏展开时的形参。需要注意的是,宏操作与源程序的其它部分一样,都要经过汇编程序的处理。汇编程序在处理带有宏调用的程序时,是先进行宏展开,再进行语法检查及翻译。宏体在定义时,由于可以带有一些形式参数,在没有进行代换之前很可能是不符合语法规则的,但宏调用并展开后是否符合语法规则,需要由汇编程序来判定。如果展开后的指令或伪指令有错,汇编程序只能指出宏调用有错,并指出宏调用所在行的号码,却无法指出究竟是展开后的哪一行不符合语法。符号“%”的作用体现在宏展开中是用常量标识符因此,对这一类错误提示,程序员只能自己按规则进行宏展开,并判断展开后的结果是如何出的错。对于MASM汇编程序比较熟悉的人,还可以借助于MASM处理源程序时产生的一个.LST文件(只要在MASM提问“Sourcelisting[NUL.LST]”时输入一个合适的文件名即可产生清单文件),判断程序中的错误,以及查看宏展开的结果。另外,宏调用的优先级高于其它伪指令和指令,所以如果用伪指令或指令助记符等内部保留字作为宏的名字,则汇编程序会把这样的标识符当作宏进行处理,而使得源程序中无法使用其原有的功能。汇编语言中还提供了一个PURGE伪指令,用于在源程序适当的位置取消某个宏。比如:因此,对这一类错误提示,程序员只能自己按规则进行宏展开,并判addMACROx,yENDMADDAX,BXPURGEaddADDAX,BX这样的源程序中,前一个ADD被当作宏调用处理(汇编语言是不分大小写的),进行宏展开;后一个ADD由于已用PURGE伪指令取消了作为宏的add宏调用,使得该标识符恢复原功能,因此是ADD指令。
addMACROx,y
7.3.5宏体中的标号宏体中出现标号分为两种情况:一是在带有跳转功能的指令中,标号作为跳转的目的地,也就是对标号的引用;另一种是宏体中某条指令的前面出现标号,即标号定义。如果宏体中引用标号,由于汇编语言允许从程序的不同地方用跳转指令跳转到同一位置,所以即使源程序中对这样的宏多次调用,展开后的结果并不违反语法规则。但是需要注意,如果标号的引用出现在条件跳转指令中,由于条件跳转的距离是有限制的,所以源程序中在不同位置调用这样的宏,那些离标号定义处较近的可以不超过范围因而没有语法错误,但那些离标号定义处远的就不保证了。7.3.5宏体中的标号【格式】LOCAL标号1,标号2,…【功能】用于告诉汇编程序,在宏展开时,对宏体中出现的“标号1”、“标号2”等标号定义,代换为特殊的各不相同的标号。汇编程序在遇到用LOCAL说明的标号时,会代以??0000、??0001、?0002、……等特殊的标识符,以保证宏体中的标号定义在每次宏展开时各不相同,避免重复定义的情况。【格式】LOCAL标号1,标号2,…【例7.16】设有如下宏定义:sumMACROa,bLOCALnextMOVCX,aLEABX,bXORAX,AXnext:ADDAX,[BX]ADDBX,2LOOPnextENDM并已知buf1和buf2是已定义的两个变量,展开下面的宏调用:sum5,buf1sum7,buf2【例7.16】设有如下宏定义:【解】宏展开结果是:+MOVCX,5+LEABX,buf1+XORAX,AX+??0000:ADDAX,[BX]+ADDBX,2+LOOP??0000+MOVCX,7+LEABX,buf2+XORAX,AX+??0001:ADDAX,[BX]+ADDBX,2+LOOP??0001【解】宏展开结果是:可以看到,两次调用宏sum,展开后的结果中标号分别是??0000和??0001,是不同的。如果宏定义中没有LOCAL伪操作,展开结果中将在两个地方定义标号next,是重复定义。汇编语言还规定,LOCAL伪操作必须出现在宏体的第1行上,在“宏名MACRO”与LOCAL伪操作之间不允许有任何内容,包括空行、注释。可以看到,两次调用宏sum,展开后的结果中标号*7.3.6宏的嵌套类似于在子程序中可以调用另一个子程序,在一个宏体中也允许再调用另一个已定义的宏。对这种宏中套宏的宏调用,汇编程序将逐次展开,直到展开后的结果不再含有宏调用为止。【例7.17】设某程序中已定义了3个字型变量v1、v2、v3,下面是源程序中的一段,试展开最后一行的宏调用。mm1 MACROx MOVAX,x MULAX ENDM*7.3.6宏的嵌套mm2MACROa,b,cmm1aMOVBX,AXmm1bADDAX,BXMOVc,AXENDM
mm2v1,v2,v3mm2MACROa,b,c【解】展开mm2后得到:+mm1v1+MOVBX,AX+mm1v2+ADDAX,BX+MOVv3,AX其中还含有宏调用,再把两个mm1展开后可得到如下结果: +MOVAX,v1 +MULAX +MOVBX,AX +MOVAX,v2 +MULAX +ADDAX,BX +MOVv3,AX【解】展开mm2后得到:7.3.7宏与子程序的比较
(1)处理的时间不同。宏调用是在源程序被汇编时由汇编程序处理的;而子程序调用是在程序执行期间由CPU直接执行的。(2)处理的方式不同。宏必须先定义后调用,宏调用是用宏体替换宏调用伪指令,实参代替形参,源程序被翻译成目标代码后宏定义随之消失;而子程序的调用没有这样的替换操作,是以CALL指令将控制权由调用者转给子程序 7.3.7宏与子程序的比较(3)目标代码的长度不同。由于每一次宏调用都要进行宏展开,把宏体中的内容复制一遍,因而用宏编写的程序在目标代码中会重复出现相同或相似的程序段,占用内存空间大;而子程序是由CALL指令调用,无论调用多少次,子程序的目标代码只在最终的执行程序中出现一次,目标代码相对较短。(4)执行速度不同。子程序调用时会比宏展开后的代码多执行CALL指令和RET指令,以及需要附加的指令进行参数传递,因而执行速度稍慢。(3)目标代码的长度不同。由于每一次宏调用都要进行(5)参数处理不同。宏调用是以实参代替形参,参数的形式不受制,可以是指令助记符、寄存器名、标号等;而子程序的参数传递必须有确切的存放地。编写程序的过程中,对于程序中的重复部分,究竟是采用宏还是子程序,程序员可以权衡内存空间、执行速度、参数传递方法等各方面的因素后取舍。在大多数情况下,宏比子程序有更大的灵活性,且执行速度快,在重复部分较短时经常采用;而一个已经验证过的子程序,可以做成目标代码存放在子程序库中,在另一个程序中应用时可不经过汇编程序的翻译,直接与需要使用它的程序连接在一起,从而避免宏展开后可能出现的语法及逻辑错误。(5)参数处理不同。宏调用是以实参代替形参,参数的*7.4重复汇编
7.4.1有规律变化的重复在变量定义中经常会出现把某个变量的初值设定为一串连续变化的整数,比如:DB1,2,3,4,5,6,7,8,9,10对这种有规律变化的情况,往往用重复汇编与“=”定义的常量配合处理。重复汇编的基本格式是:【格式】REPTnENDM*7.4重复汇编【说明】把一组源代码重复n次。格式中的REPT和ENDM是汇编语言保留字,是重复汇编的起止标志。REPT后面的n必须是一个常量或常量标识符,表示重复次数,省略号部分是被重复的源程序代码。【例7.18】前面提到的把1到10的整数作为字节型变量的初值,可以用下面的方式编写:【说明】把一组源代码重复n次。格式中的REPT和x=1REPT10DBxx=x+1ENDM汇编后产生的结果如下:+DB1+DB2
+DB9+DB10x=1
7.4.2无规律变化的重复如果在一组连续的指令中,是用同一条指令或伪指令处理不同的操作数,而操作数本身没有内在规律时,可以用无规律重复汇编简化编程。这种重复汇编的用法是:
【格式】IRP形参,<实参表>ENDM【功能】IRP和ENDM是重复汇编的起止标志,省略号表示被重复的一组指令或伪指令,形式参数是这一组指令中可变化的部分。如果实参表中有n个参数项,汇编程序将把这一组指令或伪指令重复n次,每一次用实参表中的一个参数项代替形参。7.4.2无规律变化的重复【例7.19】把除SP以外的各通用寄存器入栈需要7条PUSH指令,如果用重复汇编可以写成:IRPregs,<AX,BX,CX,DX,SI,DI,BP>PUSHregsENDM汇编后展开的结果是:+PUSHAX+PUSHBX+PUSHCX+PUSHDX+PUSHSI+PUSHDI+PUSHBP【例7.19】把除SP以外的各通用寄存器入栈需要7本
章
要
点与前面的章节相比,本章说明的是汇编语言提供的更复杂的数据处理方法和更简洁的编程形式。移位操作主要用于对二进制位串的处理,可以加速乘以或除以2n的计算;串操作指令主要针对类似于高级语言中的数组的操作,带有前缀的串指令不仅可以简化程序的编制,而且可以缩短程序执行的时间。宏和重复汇编都是汇编语言提供的伪操作。把源程序中不同位置上重复出现的相同或相似的一组指令定义成宏,然后在源程序中以宏名字进行宏调用,可以使重复出现的程序段只编写一次,不仅减少了出错的可能性,而且便于程序的修改;对于连续重复出现的一组指令或伪指令,还可以用重复汇编简化编程。本章要点习
题
七7.1已知(DX,AX)中存放了一个无符号双字,编写程序段,利用移位指令把这个双字乘以7,不计溢出。7.2编写一个子程序,以AX为入口参数,把AX中的各个二进制位颠倒次序后还放回AX中。比如,入口参数AX=1011000111101001B,则处理后AX应为1001011110001101B。[提示:用一条非循环移位指令与一条带CF的循环移位指令配合,选取的两条指令在移位方向上必须相反]7.3编写子程序,入口参数是一个字型数据,统计该字的16个二进制位中含有多少个1和多少个0。习题七7.4编写完整程序,调用第6章的read子程序,从键盘读入一个带符号整数,以二进制输出其补码。[提示:read子程序得到的结果本就是补码,只需要用二进制依次输出它的16个二进制位即可]7.5不允许使用串指令,分别编写程序段,实现DF为0时以下各串操作指令的功能。(1)REPMOVSB(2)REPSTOSW(3)REPZCMPSB(4)REPNZSCASW7.4编写完整程序,调用第6章的read7.6已知var是一个字型数组变量,存放了n个带符号整数,编写程序段,把这n个整数按正负分类,分别存入两个字型变量varp和varn中,并跳过原数组中的0。要求尽可能地利用串操作指令。7.7利用串指令编写一个口令检验程序,从键盘读入一个符号串,与源程序中预先定义的一个符号串(口令)相比较,如果不同,允许再次输入,最多输入3次,3次输入都不对则程序结束。输出口令检验的结果,显示是否输入了正确的口令,以及是第几次输对的。如果忽略字母的大小写又该如何处理呢?7.6已知var是一个字型数组变量,存放7.8给定宏定义如下:difMACROx,yMOVAX,xSUBAX,yENDMdifaMACROa,b,cLOCALcontPUSHAXdifa,bCMPAX,0JGEcontNEGAXcont:MOVc,AXPOPAXENDM7.8给定宏定义如下:描述宏difa的功能,并对下面的宏调用进行展开,判定展开后的结果是否有效(是否符合汇编语言语法规定)。(1)difap1,p2,distance;实参都是字型变量(2)difa[BX],[SI],m[DI],CX;m是字型变量(3)difa[BX][SI],m[BP],240H;m是字型变量(4)difaAX,AX,AX描述宏difa的功能,并对下面的宏调用进行展开,判定展开后的7.9编写宏定义,把一个字节型数组各元素清0,并以变量名varb和数组元素个数100为实参,调用该宏,写出宏展开后的结果。7.10编写一个宏定义IO,要求能够用于实现DOS的9号和10号子功能,即完成字符串输入或输出操作,并将下面的程序段用宏调用简化。LEADX,buf1MOVAH,9INT21HLEADX,buf2MOVAH,10INT21H7.9编写宏定义,把一个字节型数组各元素7.11编写一个宏定义swap,把一个字节型数据的高4位与低4位交换,并对下面的宏调用进行展开,判断展开后的结果是否有效,以及是否有逻辑错误,如果有,如何改进?(1)swapAL(2)swapCL(3)swap[BX](4)swap[var];var是已定义的字节型变量(5)swap[var+BX];var是已定义的字节型变量7.11编写一个宏定义swap,把一个字节第7章编程中的高级处理技术
7.1移位指令与应用
7.2串操作
7.3宏
*7.4重复汇编
本章要点
习题七返回章目录第7章编程中的高级处理技术返回章目录7.1移位指令与应用7.1.1逻辑左移【指令格式】SHL
d1,d2【功能】把操作数d1的各个二进制位依次向左移动d2位,移动造成右边的空位填0,结果放回操作d1中。【说明】(1)操作数d1必须是通用寄存器或内存型寻址方式,必须有确定的类型,可以是字节型,也可以是字型,并且对内存型寻址方式可以使用段跨越。7.1移位指令与应用(2)操作数d2表示移动的位数,只能是立即数1或者寄存器CL,当移动位数超过1位时,必须把移动位数放在CL中,以CL作为d2操作数。(3)操作数d1各位移动的情况如图7.1所示,从最高位起,将有d2位移到操作数d1之外,除了最后移出的一位放到标志位CF中之外,其余各位均被丢弃,移动造成右边的空位用0填充。……位号:15/714/6 100CF 操作数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 人教版高中语文第三册项脊轩志 同步练习基础知识
- bot工程合同范例
- 写劳务合同范例软件
- 农业土地合同范例
- 农资店转租合同范例
- 企业移动光钎合同范例
- 代理公司合作合同范例
- 临电合同范例
- 仓储车辆合同范例
- 2022年全国道路交通安全法律法规知识考试题(附含答案)
- 2023年四川绵阳中考满分作文《被幸福照亮》
- 二年级数学100以内加减法竖式计算题单元考核习题
- 红星前进品牌手册2024
- 2024-2030年中国粒子加速器行业发展现状调研及市场趋势洞察报告
- 2023-2024(上) 全品学练考 高中物理 选择性必修第一册第2章 机械振动简谐运动导学案含答案
- 2021年江苏旅游职业学院单招综合素质试题
- JBT 14543-2024 无刷稳速直流电动机技术规范(正式版)
- 医院实验室生物安全风险评估表
- 中国食物成分表2018年(标准版)第6版
- 小精灵的秋天
- 四年级下册英语-Unit-4-Free-time-粤人版
评论
0/150
提交评论