Klicken Sie,um das Titelformat zu bearbeiten,Klicken Sie,um die Formate des Vorlagentextes zu bearbeiten,Zweite Ebene,Dritte Ebene,Vierte Ebene,Fnfte Ebene,*,计算机科学系,汇编,课件,10.3,条件汇编伪指令,条件汇编伪指令的一般格式:,IF condition,statements,ELSE,statements,ENDIF,当,condition,为真时,允许汇编,statements,中的语句。,条件汇编伪指令,伪指令,说明,IF,表达式,如果表达式为真则允许汇编。,IFB,如果参数为空则允许汇编,参数名必须用,括起来,IFNB,如果参数不为空则允许汇编,参数名必须用,括起来,IFIDN,如果两个参数相同则允许汇编,参数区分大小写,IFIDNI,如果两个参数相同则允许汇编,参数不区分大小写,IFDIF,如果两个参数不同则允许汇编,参数区分大小写,IFDIFI,如果两个参数不同则允许汇编,参数比区分大小写,IFDEF,名字,如果名字已经定义则允许汇编,IFNDEF,名字,如果名字未定义则允许汇编,ENDIF,结束一个条件汇编伪指令开始的语句块,ELSE,如果前面的条件均为假,则汇编该伪指令至,ENDIF,之间的语句,EXITM,立即退出宏,阻止其后任何语句的展开,检查缺少的参数,mWriteStr,MACRO string,IFB,ECHO-,ECHO*,Error:parameter,missing in,mWriteStr,ECHO*(no code generated),ECHO-,EXITM,ENDIF,push,edx,mov,edx,OFFSET string,call,WriteString,pop,edx,ENDM,默认的参数初始化值,定义宏时可以有默认的参数初始化值,,如果调用宏时未给出参数,则编译器使用默认参数值,。,格式为:,paramname,:=,例如:为,mWriteLn,宏提供一个空格作为默认的参数:,mWriteLn,MACRO text:=,mWrite,text,call,Crlf,ENDM,如果调用时不带参数,那么仍然会打印一个空格并在后面跟一个,换行符。,布尔表达式,编译器允许在常量布尔表达式中使用以下关系运算符:,LT,小于,GT,大于,EQ,等于,NE,不等于,LE,小于等于,GE,大于等于,IF,,,ELSE,和,ENDIF,伪指令,格式为:,IF expression,statement-list,ENDIF,或:,IF expression,statement-list,ELSE,statement-list,ENDIF,IF,伪指令后面必须跟一个常量布尔表达式。表达式可以包含常量、,符号常量或宏参数常量,但不能是寄存器或变量名。,例子:,mGotoxyConst,宏,mGotoxyConst,宏使用,LT,和,GT,操作符对传递给宏的参数进行,范围检查,参数,X,和,Y,必须是常量。另一个常量,ERRS,用于统计发,现的错误数。,IFIDN,和,IFIDNI,伪指令,IFIDN,伪指令以区分大小写的方式比较两个符号,(,包括宏参数,),是否相等,如果相等则返回,TRUE,。,IFIDNI,伪指令则不区分大小写。格式为:,IFIDN,statements,ENDIF,mReadBuf,MACRO,bufferPtr,maxchars,IFIDNI,ECHO,Warning:second,argument to,mreadbuf,cannot be,edx,ECHO*,EXITM,ENDIF,push,ecx,push,edx,mov,edx,bufferPtr,mov,ecx,maxchars,call,ReadString,pop,edx,pop,ecx,ENDM,下面的语句将导致宏产生一条错误信息:,mReadBuf,OFFSET buffer,edx,例如:下面的,mReadBuf,宏中,第二个参数不能是,EDX,,因为,buffer,的偏移被送到,EDX,时,参数会被覆盖。,例子:对矩阵行求和,定义宏,mCalc_row_sum,mCalc_row_sum,MACRO index,arrayOffset,rowSize,eltType,LOCAL L1,mov,eax,index,mov,ebx,arrayOffset,mov,ecx,rowSize,mul,ecx,add,ebx,eax,shr,ecx,(TYPE eltType/2),mov,eax,0,mov,esi,0,L1:,IFIDNI,mov,edx,eltType,ptrebx+esi,*(TYPE,eltType,),ELSE,movzx,edx,eltType,ptrebx+esi,*(TYPE,eltType,),ENDIF,loop L1,ENDM,特殊操作符,&,替换操作符,文本操作符,!,特殊字符操作符,%,展开操作符,替换操作符,&,将宏的内部对宏参数的引用替换为调用,时的实际值。,ShowRegister,MACRO,regName,LOCAL,tempStr,.data,tempStr,BYTE “,&,regName,=”,0,.code,push,eax,push,edx,mov,edx,offset,tempStr,call,WriteString,mov,eax,regName,call,WriteHex,pop,edx,pop,eax,ENDM,当程序中出现宏调用语句:,ShowRegister,ECX,则宏调用的输出为:,ECX=,00000101,展开操作符,%,展开文本宏并把常量表达式转换成文本。,在与用,TEXTEQU,联合使用时,,%,操作符对常量表达,式求值并将结果转化成整数。,例,1,:,count=10,sumVal,TEXTEQU%(5+count);=“15”,例,2,:,mGotoxyConst,%(5*10),%(3+4),调用宏时,两个表达式分别被求值并作为参数传递,行首的,%,当,%,作为源代码行的第一个字符时,预处理器将展开在该行发现的所有文本宏和宏函数。,例子:,.data,array DWORD 1,2,3,4,5,6,7,8,TempStr,TEXTEQU%(SIZEOF array),.code,%,ECHO,The array contains,TempStr,bytes,产生的输出为:,The array contains 32 bytes,文本操作符,将多个字符或符号作为一个字符串进行传递。,例如,本章前面的宏只接收一个唯一的字符串参数,如果传递,以下字符串,预处理器将解释为三个参数:,mWrite,“Line three”,0dh,0ah,如果用文本操作符将字符串括起来,预处理器会将文本操作符里面的所有字符都作为单个宏参数进行传递,:,mWrite,特殊字符操作符,!,强制预处理器将预定义的操作符作为原始字符进行传递。,例如:,BadYValue,TEXTEQU,24,操作符的结合使用,BadYValue,TEXTEQU,24,ShowWarning,MACRO message,mWrite,“,&,message”,ENDM,则以下的宏调用:,.code,ShowWarning,%,BadYValue,将产生如下结果:,Warning:Y,-coordinate is 24,先替换后展开,宏函数,与宏过程类似,宏函数也是一个命名的汇编语句块,唯一的不同在于,,宏函数总是用,EXITM,伪指令返回一个常量值,(,整数或字符串,),。,例如:,IsDefined,MACRO symbol,IFDEF symbol,EXITM ;True,ELSE,EXITM ;False,ENDIF,ENDM,调用宏函数:调用宏函数时参数列表必须用圆括号括起来。,例如:调用,IsDefined,宏,并向它传递一个已经或尚未定义的,参数,RealMode,:,IF,IsDefined,(RealMode,),mov,ax,data,mov,ds,ax,ENDIF,如果编译器在编译该语句之前已经遇到了,RealMode,的定义,,则编译后面两条语句。,10.4,定义重复块,WHILE,伪指令,REPEAT,伪指令,FOR,伪指令,FORC,伪指令,链表,MASM,中的重复块伪指令只能用于编译期间,而且只能使用常量值作为循环条件和计数器。,WHILE,伪指令根据一个布尔表达式来重复语句块,REPEAT,伪指令根据一个计数器来重复语句块,FOR,伪指令通过遍历一个符号列表中的每个符号来重复语句块,FORC,伪指令通过遍历一个字符串中的每个字符来重复语句块,WHILE,伪指令,格式如下:,WHILE,constExpression,statements,ENDM,只要常量表达式,constExpression,的值为真,,WHILE,伪指令就重复语句块。,例如:以下代码显示了如何生成,1,到,F0000000h,之间,的斐波那契数作为一系列编译时期的常量。,.data,val1=1,val2=1,DWORD val1,DWORD val2,val3=val1+val2,WHILE val3 LT 0F0000000h,DWORD val3,val1=val2,val2=val3,val3=val1+val2,ENDM,REPEAT,伪指令,REPEAT,伪指令以固定次数重复指令块。格式为:,REPEAT,constExpression,statements,ENDM,constExpression,是一个无符号整数常量表达式,它决定,了重复次数。,例如:以下的,REPEAT,循环创建了包含,100,个双字的数组并用数列,10,20,30,40,1000,对其进行初始化:,ival,=10,REPEAT 100,DWORD,ival,ival,=ival+10,ENDM,FOR,伪指令,FOR,伪指令通过遍历一个以逗号分隔的符号列表重复语句块,符号列表中的每个符号都引发一次循环。格式如下:,FOR parameter,statements,ENDM,第,i,次循环时,参数,parameter,被赋值为,argi,FORC,伪指令,FORC,伪指令通过遍历一个字符串中的每个字符来重复语句块,字符串中的每个字符都引发一次循环。格式如下:,FORC parameter,statements,ENDM,第,i,次循环中,参数,parameter,等于字符串,string,中的,第,i,个字符。,例如,:,Delimiters LABEL BYTE,FOR code,BYTE“&code”,ENDM,将生成以下数据:,00000000 40 1 BYTE “”,00000001 23 1 BYTE “#”,00000002 24 1 BYTE “$”,00000003 25 1 BYTE “%”,00000004 5E 1 BYTE “”,00000005 26 1 BYTE “&”,00000006 2A 1 BYTE “*”,00000007 3C 1 BYTE “”,链表,每个节点的数据区内可以使用一个或多个变量存放节点的数据。,在链接区中,用一个指针包含和链表相邻的下一节点的地址。,最后一个节点的链接区通常包含一个空指针。,data,lind,data,lind,data,lind,NULL,例子:首先创建一个链表节点类型,该类型包含一个整数,(,数据区,),和一个指向下一个相邻节点的指针(链接区):,ListNode,STRUCT,NodeData,DWORD?,NextPtr,DWORD?,ListNode,ENDS,接着使用,REPEAT,伪指令创建,ListNode,对象的多个