210 likes | 369 Views
汇编语言. 数学科学学院计算机应用技术专业. 修兴强 北京师范大学数学科学学院 202.112.84.202/~ xiux/download.php E-mail: xq_xiu@yahoo.com.cn. 2007 年 10 月. 汇编语言. 1. 1. 第9章 字符串和数组. 2007 年 10 月. 2007 年 10 月. 汇编语言. 汇编语言. 2. 2. 基本字符串操作指令. Intel 指令集中有5组高度优化的简单字符串指令,处理 字节 、 字 和 双字 数组。. 2007 年 10 月. 汇编语言. 3.
E N D
汇编语言 数学科学学院计算机应用技术专业 修兴强 北京师范大学数学科学学院 202.112.84.202/~xiux/download.php E-mail: xq_xiu@yahoo.com.cn 2007年10月 汇编语言 汇编语言 1 1
第9章 字符串和数组 2007年10月 2007年10月 汇编语言 汇编语言 汇编语言 2 2
基本字符串操作指令 • Intel指令集中有5组高度优化的简单字符串指令,处理字节、字和双字数组。 2007年10月 汇编语言 汇编语言 3
上页中的每条指令都使用ESI或EDI寄存器,或同时使用二者以寻址内存。字符串操作指令只使用内存操作数。简单字符串操作指令可以自动重复执行,这使得它在处理字符串和数组时特别有用。上页中的每条指令都使用ESI或EDI寄存器,或同时使用二者以寻址内存。字符串操作指令只使用内存操作数。简单字符串操作指令可以自动重复执行,这使得它在处理字符串和数组时特别有用。 • 在保护模式程序中,ESI被作为偏移自动地在DS指定的段中寻址,EDI自动地在ES指定的段中寻址,DS和ES总是被设置为同样的值而且无法改变它们。 • 在实地址模式下,字符串操作指令使用SI和DI寄存器来寻址内存。SI是DS段中的偏移,DI是ES段中的偏移。我们通常在main过程的开始将ES和DS设置为同样的段值。 汇编语言
使用重复前缀 • 字符串操作指令本身每次只处理一个内存值,但如果增加一个重复前缀的话,该指令就会使用ECX作为计数器进行重复。换句话说,就是可以使用一条指令处理整个数组。可以使用的重复前缀如下所示: 汇编语言
方向标志 • 简单字符串指令使用方向标志来决定ESI和EDI是自动增加还是自动减少。 • 方向标志可以通过CLD和STD指令显式地改变: CLD ;清除方向标志 STD ;设置方向标志 汇编语言
使用重复前缀的例子 cld ;清除方向标志 mov esi,OFFSET string1 ;将ESI指向源字符串 mov edi,OFFSET string2 ;将EDI指向目的字符串 mov ecx,10 ;将计数器设置为10 rep movsb ;重复按字节移动10个数据 汇编语言
MOVSB,MOVSW和MOVSD指令 • MOVSB,MOVSW和MOVSD指令从ESI指向的内存位置拷贝数据到EDI指向的内存位置,同时ESI和EDI寄存器自动增加或减少(依据方向指标的值而定)。 • MOVSB,MOVSW和MOVSD指令可以和重复前缀联合使用,方向标志决定ESI和EDI的值是增加还是减少,增减的数字大小如下所示: 汇编语言
CMPSB,CMPSW和CMPSD指令 • CMPSB,CMPSW和CMPSD指令每次将ESI指向的内存操作数同EDI指向的内存操作数相比较: • CMPSB,CMPSW和CMPSD指令可以同重复前缀联合使用,方向标志决定了ESI和EDI的值是增加还是减少。 • 例子:比较两个字符串Cmpsb.asm。 • 比较结束时,ESI和EDI最终指向两个字符串不同之处后面的一个位置;如果两个字符串相同的话,ESI和EDI将指向各自字符串结尾处后面的一个位置。 • 只有在两个字符串长度相等的条件下,使用CMPSB指令才是可行的。 汇编语言
SCASB,SCASW和SCASD指令 • SCASB,SCASW和SCASD指令将AL/AX/EAX中的值同目标内存中的字节、字或双字相比较,目标内存数据是由EDI寻址的。 • 这些指令在一个字符串或数组中查找一个值的时候特别有用。如果使用REPE(或REP)前缀,当ECX>0并且AL/AX/EAX不能匹配内存中的值时,指令将继续扫描字符串或数组。REPNE前缀使得指令扫描字符串直到AL/AX/EAX匹配内存中的一个值或ECX=0为止。 .data alpha BYTE ‘ABCDEFGH’,0 .code mov edi,OFFSET alpha ;将EDI指向字符串 mov al,’F’ ;查找字符F mov ecx,LENGTHOF alpha ;将计数器设置为字符串长度 cld ;清除方向标志 repne scasb ;在字符串中重复比较直至相等 jnz quit ;如果没有找到则推出 dec edi ;将EDI值减1 • 扫描匹配字符串例子: 汇编语言
STOSB,STOSW和STOSD指令 • STOSB,STOSW和STOSD指令将AL/AX/EAX的内容存储在EDI指向的内存单元中,同时EDI的值将依据方向标志的值增加或减少。同REP前缀联合使用的时候,这组指令在将整个字符串或数组填充为某个值时非常有用。 .data Count = 100 string1 BYTE Count DUP(?) .code mov al,0FFh ;将被存储的数值 mov edi,OFFSET string1 ;将EDI指向目的字符串 mov ecx,Count ;设置计数器 cld ;清除方向标志 rep stosb ;将AL的内容存储在EDI指向的字符串中 汇编语言
LODSB,LODSW和LODSD指令 • LODSB,LODSW和LODSD指令从ESI指向的内存位置向AL/AX/EAX中装入一个值,同时ESI的值根据方向标志值增加或减少。我们很少将REP前缀同LODS指令联用,因为装入到累加器中的每个新值都会覆盖掉以前的值,相反,一般仅用LODS指令来装入一个值。例如LODSB指令可以替代下面的两条指令(假设方向标志被清除): mov al,[esi] inc esi • 数组乘法的例子Mult.asm。 汇编语言
精选的字符串过程 • Str_compare过程 • Str_length过程 • Str_copy过程 • Str_trim过程 • Str_ucase过程 汇编语言
二维数组 许多应用程序,无论是数学还是其他方面,都要涉及到二维数组的处理。Intel指令集提供了基址变址和相对基址变址这两种非常适合于数组应用程序的操作数类型。 • 基址变址(base-index)操作数将两个寄存器的值相加(称为基址和变址)来产生偏移地址,操作数中可使用任意两个32位通用寄存器。在实地址模式下也可以使用16位的寄存器作为基址变址操作数,在这种情况下,惟一允许的组合是[bx+si],[bx+di],[bp+si]和[bp+di](在通常情况下应避免使用BP寄存器,除非要访问的是堆栈操作数)。 • 基址变址操作数在访问二维表格的时候非常有用,通常使用基址寄存器存放行偏移,变址寄存器存放列偏移。表格的例子(table.asm)。 汇编语言
相对基址变址操作数将偏移、基址寄存器和变址寄存器组合起来产生一个有效地址,下面是该操作数最常见的两种格式:相对基址变址操作数将偏移、基址寄存器和变址寄存器组合起来产生一个有效地址,下面是该操作数最常见的两种格式: [base + index + displacement] displacement[base + index] • 偏移(Displacement)可以是变量的名字或常量表达式,基址和变址可以使用任意的32位寄存器。由于在实地址模式下只允许16位的寄存器作为基址/变址操作数,因此这时的限制和在实模式下使用基址变址方式寻址的限制是一样的。 • 和基址变址操作数一样,相对基址变址操作数也很适用于处理二维表格。表格的名字可以用来作为操作数的偏移部分,基地址寄存器用于存放表格的行号,变址寄存器用于存放列号。表格的例子(table2.asm)。 汇编语言
3 1 1 1 1 1 1 1 1 3 3 3 3 3 5 5 7 7 7 5 5 5 5 5 5 5 5 7 2 2 2 2 2 2 2 2 7 7 7 7 9 9 9 9 9 9 4 4 4 4 4 4 4 4 9 3 3 3 3 3 3 3 3 9 整数数组的查找和排序 冒泡排序法 • 冒泡排序(bubble sort)法从位置0和1开始比较每对数组值,如果两个值得顺序不对则进行交换。下图显示了对一系列整数进行的一次完整的比较过程: • 在第一遍处理完毕之后,数组并未被排序,因此外层循环又开始另一轮处理,在完成n-1遍处理后,就能保证数组是按顺序排列好了的。 • 冒泡排序法是一个时间复杂度为O(n^2)的算法,也就是说排序时间与数组元素的数目(n)之间是二次方的关系。 汇编语言
SubbleSort 汇编语言
二进制查找 • 二进制查找算法在大数组中查找一个项时被证明是非常高效的,但该算法有一个重要的前提条件:数组元素必须已经按升序或降序排列。下面是该算法的一个非正式描述: 在进行查找之前,首先要求用户输入一个整数,我们称之为search Val。 1.查找范围由名为first和last的下标表示,如果first>last则退出查找,表明没有匹配项 2.计算由下标first和last标识的数组的中点。 3.将search Val值同数组中点处的值进行比较: • 如果两个值相等则从过程中返回,EAX中包含中点值,这个返回值表明在数组中发现了匹配项。 • 如果search Val大于中点处的数值,将第一个数组下标重设为中点之后的下一个位置。 • 如果search Val小于中点处的数值,将最后一个数组下标重设为重点之前的一个位置。 4.重复步骤1。 汇编语言
二进制查找非常高效,因为它使用了二分法查找策略,每次循环后查找范围都会减半,通常该算法被称为是时间复杂度为O(log n)的算法,也就是说如果数组元素增加到n倍,那么平均查找时间只增加到log n倍。由于查找时间非常短,下表简单地记录了各种不同大小的数组最多需要的比较次数: 汇编语言
BinarySearch 汇编语言
第二次作业 • 阅读Irvine32.asm中的代码,选择至少3个过程,对每一行代码写注释,要求说明清楚过程的作用和方法。1周内提交。 • 期末成绩计算方法: MAX { 平时成绩 * 40% + 期末成绩 * 60%, 期末成绩 } 汇编语言