560 likes | 722 Views
第 5 章 高级汇编语言程序设计. 在掌握基本的汇编语言程序设计方法之后,进一步学习如何提高编程效率的各种实用方法。. 宏 汇 编 重 复 汇 编 条 件 汇 编. 宏汇编 重复汇编 条件汇编 —— 统称宏结构. 宏( Macro )是汇编语言的一个特点,它是与子程序类似又独具特色的另一种简化源程序的方法. 5. 1 宏汇编. 宏( Macro )是源程序中一段有独立功能的程序代码。它只需在源程序中定义一次,就可以多次调用它,调用时只需用一个宏指令语句就可以了。.
E N D
第5章 高级汇编语言程序设计 在掌握基本的汇编语言程序设计方法之后,进一步学习如何提高编程效率的各种实用方法。 宏 汇 编 重 复 汇 编 条 件 汇 编
宏汇编 重复汇编 条件汇编 ——统称宏结构 宏(Macro)是汇编语言的一个特点,它是与子程序类似又独具特色的另一种简化源程序的方法
5. 1 宏汇编 宏(Macro)是源程序中一段有独立功能的程序代码。它只需在源程序中定义一次,就可以多次调用它,调用时只需用一个宏指令语句就可以了。 宏——具有宏名的一段汇编语句序列(宏定义时书写) 宏指令——这段汇编语句序列的缩写(宏调用时书写) 宏展开——宏指令处用这段宏代替的过程(宏汇编时实现) 宏的参数功能强大,颇具特色 配合宏,还有宏操作符和有关伪指令
宏名 macro [形参表] …宏定义体 endm 宏定义是用一组伪操作来实现的.其格式是: 其中macro和endm是一对伪操作,这对伪操作之间是宏定义体(一组有独立功能的程序代码).宏名给该宏定义的名称,调用时就使用宏名来调用该宏定义。 宏名的第一个符号必须是字母,其后可以跟字母、数字和下划线字符。
MAINBEGING MACRO;;定义名为MAINBEGIN的宏,无参数 MOV AX,@DATA ;;宏定义体 MOV DS,AX ENDM ;;宏定义结束 MAINEND MACRO RETNUM ;;带有形参RETNUM MOV AL,RETNUM ;;宏定义中使用参数 MOV AH,4CH INT 21H ENDM
MULTIPLY MACRO OPR1,OPR2,RESULT ;;定义名具有三个参数的宏 PUSH DX ;;宏定义体 PUSH AX MOV AX,OPR1 IMUL OPR2 MOV RESULT,AX POP AX POP DX ENDM ;;宏定义结束
宏名 [实参表] 宏调用经宏定义定义后的宏指令可以在源程序中调用,这种对宏指令的调用称为宏调用。其格式为: 宏调用的实质是在汇编过程中进行宏展开
例: START: MAINBEGIN ;宏调用,建立DS内容 MULTIPLY 240,BX,SAVE ;宏调用,显示字符串 MAINEND 0 ;宏调用,返回DOS END START • 宏调用的实质是在汇编过程中进行宏展开
在汇编时,用宏定义体的代码序列取代源程序中的宏指令名,而且用实际参数取代形式参数的过程。在汇编时,用宏定义体的代码序列取代源程序中的宏指令名,而且用实际参数取代形式参数的过程。 宏展开 • 宏展开的具体过程是:当汇编程序扫描源程序遇到已有定义的宏调用时,即用相应的宏定义体取代源程序的宏指令,同时用位置匹配的实参对形参进行取代,而且在取代时,实参与形参是一一对应的。
START: 1 MOV AX,@DATA ;宏指令MAINBEGIN的宏展开 1 MOV DS,AX 1 PUSH DX ;宏指令MULTIPLY的宏展开 1 PUSH AX 1 MOV AX,OPR1 1 IMUL OPR2 1 MOV RESULT,AX 1 POP AX 1 POP DX 1 MOV AL,0;宏指令MAINEND 0 的宏展开 1 MOV AH,4CH 1 INT 21H END START
宏的参数使用非常灵活 宏定义时, 可以无参数,例如:MAINBEGIN 可以带有一个参数,例如:MAINEND 也可以具有多个参数;例如:MULTIPLY 参数可以是常数、变量、存储单元、指令(操作码)或它们的一部分,也可以是表达式; 宏定义体可以是任何合法的汇编语句,既可以是硬指令序列,又可以是伪指令序列; 宏的参数:
例: ;宏定义 SHLEXT MACRO SHLOPRAND,SHLNUM PUSH CX MOV CL,SHLNUM SHL SHLOPRAND CL POP CX ENDM ;宏指令 SHLEXT AX,6 ;宏展开 1 PUSH CX 1 MOV CL,06 1 SHL AX,CL 1 POP CX
替换操作符 参数可以是操作码的一部分,但在宏定义中必须用&作为分隔符。&是一个操作符,它在宏体中可作为形参的前缀,展开时把&前后两个符号合并形成一个符号,这个符号可是操作码、操作数和一个字符串。 ;统一4条移位指令的宏指令(shl,shr,sal,sar) shift macro soprand,snum,sopcode push cx mov cl,snum s&sopcode& soprand,cl pop cx endm 例:宏调用: shift ax,4,ar 宏展开: 1push cx 1 mov cl,4 1 sarax,cl 1 pop cx
;统一移位和循环移位8条指令的宏指令 shrot macro sroprand,srnum,sropcode push cx mov cl,srnum sropcode sroprand,cl pop cx endm 例: 宏调用:shrot ax,4,rcl 宏展开: 1 push cx 1 mov cl,4 1 rclax,cl 1 pop cx
例: ;宏定义 dstring macro string db ’&string&’,0dh,0ah,’$’ endm ;宏调用 dstring < This is a example. > dstring < 0 !< Number !< 10 > ;宏展开 1 db ’This is a example.’, 0dh,0ah,’$’ 1 db ’0 < Number < 10’, 0dh,0ah, ’$’ 传递注释符 转义注释符
例: MSG MACRO COUNT,STRING ;宏定义 MSG&COUNT DB STRING ENDM ERRMSG MACRO TEXT CNTR =CNTR +1 MSG %CNTR,TEXT ENDM 宏调用: CNTR =0 ERRMSG ‘SYNTAX ERROR’ ERRMSG ‘INVALID OPPERAND’ 宏展开: CNTR=0 1 CNTR=CNTR+1 1 MSG %CNTR, ‘SYNTAX ERROR’ 2 MSG1 DB ‘SYNTAXERROR’ 1 CNTR=CNTR+1 1 MSG %CNTR,’INVALID OPPERAND’ 2 MSG2 DB ‘INVALID OPPERAND’
局部标号伪指令 格式:LOCAL 标号列表(各标号之间用逗号分隔) 宏定义体采用了标号,应使用LOCAL加以说明,它必须是宏定义MACRO语句之后的第一条语句。汇编程序对LOCAL伪指令的局部标号表中每个局部标号建立惟一的符号(用??0000-??FFFF)以代替在展开中存在的每一个局部标号。 与宏有关的伪指令
单独占一行 ;宏调用 absol word ptr [bx] absol bx ;宏展开 1 cmp word ptr [bx],0 1 jge ??0000 1 neg word ptr [bx] 1 ??0000: 1 cmp bx,0 1 jge ??0001 1 neg bx 1 ??0001: 例: ;宏定义 absol macro oprd local next cmp oprd,0 jge next neg oprd next: endm
宏定义删除伪指令 格式: PURGE 宏名表 为了删除汇编时引入到内存的无用的宏定义,可以用PURGE伪指令把它删除 • 宏定义退出伪指令 格式: EXITM 伪指令EXITM表示结束当前宏调用的展开
宏指令名可以与指令助记符或伪操作名相同,在这种情况下,宏指令的优先级最高,而同名的指令或伪操作就失效了.伪操作PURGE可以用来在适当的时候取消宏定义,以便恢复指令的原始含义.宏定义: ADD MACRO OPR1,OPR2,RESULT ... ENDM宏调用: ... ADD XX,YY,ZZ PURGE ADD ...
在宏调用后,用PURGE伪操作取消定义,以便恢复ADD指令的原始含义,在PURGE ADD后面所用的ADD指令,则服从机器指令的定义. PURGE伪操作可同时取消多个宏操作,此时各宏指令之间用逗号隔开.
宏定义中允许使用宏调用,其限制条件是:必须先定义后调用。例:宏定义:DIF MACRO X,Y MOV AX,X SUB AX,Y ENDMDIFSQR MACRO OPR1,OPR2,RESULT PUSH DX PUSH AX DIF OPR1,OPR2 IMUL AX MOV RESULT,AX POP AX POP DX ENDM宏调用:DIFSQR VAR1,VAR2,VAR3
宏定义体内不仅可以使用宏调用,也可以包含宏定义.宏定义: DEFMAC MACRO MACNAM,OPERATOR MACNAM MACRO X,Y,Z PUSH AX MOV AX,X OPERATOR AX,Y MOV Z,AX POP AX ENDM ENDM其中MACNAM是内层的宏定义名,但又是外层宏定义的形参,所以调用DEFMAC时,就形成一个宏定义.
宏调用: DEFMAC ADDITION,ADD宏展开: 1 ADDITION MACRO X,Y,Z 1 PUSH AX 1 MOV AX,X 1 ADD AX,Y 1 MOV Z,AX 1 POP AX 1 ENDM形成加法宏定义ADDITION. 同样,宏调用: DEFMAC SUBTRACT,SUB会形成减法的宏定义.
当然在形成这些宏定义后,就可以使用宏调用ADDITION VAR1,VAR2,VAR3 而展开成: 1 PUSH AX 1 MOV AX,VAR1 1 ADD AX,VAR2 1 MOV VAR3,AX 1 POP AX
宏与子程序的区别 • 处理的时间不同.宏调用是在源程序被汇编程序处理的;而子程序调用是在程序执行期间由CPU直接执行的. • 处理的方式不同.两者都必须先定义后使用,但宏调用是用宏体替换宏调用伪指令,实参代替形参,源程序被翻译成目标代码后宏定义随着消失;而子程序则没有这样的替换操作,是以CALL指令将控制权由调用者转给子程序并执行. • 参数处理不同.宏调用是以实参代替形参,参数的形式不受限制,可以是任何合法的字符;子程序的参数需要寄存器或存储单元进行传递,而且需要附加的指令实现参数传递.
执行速度不同.子程序调用时需要执行CALL指令和RET指令,还要执行实现参数传递的附加指令,因而会比宏展开后的代码多而执行速度稍慢.执行速度不同.子程序调用时需要执行CALL指令和RET指令,还要执行实现参数传递的附加指令,因而会比宏展开后的代码多而执行速度稍慢. • 占用的存储器空间大小不同.宏指令在每次调用时都要展开,把宏体中的程序段复制一遍,因而用宏指令编写的程序在目标代码中会重复出现相同或相似的程序段,占用内存空间较大;而子程序是由CALL指令调用的,无论调多少次,子程序的目标代码只在程序中出现一次,目标代码相对较短.
宏与子程序具有各自的特点,程序员应该根据具体问题选择使用那种方法宏与子程序具有各自的特点,程序员应该根据具体问题选择使用那种方法 通常,当程序段较短或要求较快执行时,应选用宏;当程序段较长或为减小目标代码时,要选用子程序 比较结论
5.2 重复汇编 有时汇编语言程序需要连续地重复完全相同的或者几乎完全相同的一组代码,这时可使用重复汇编。 1.重复伪操作 其格式为: REPT 表达式... (重复块) ENDM 其中表达式的值用来确定重复块的重复次数,表达式中如包含外部或未定义的项则汇编指示出错.
重复汇编指在汇编过程中,重复展开一段(基本)相同的语句重复汇编指在汇编过程中,重复展开一段(基本)相同的语句 • 重复汇编没有名字,不能被调用 • 重复汇编常用在宏定义体中,也可以在一般汇编语句中使用
重复伪操作并不一定要在宏定义体内。 例如: X=0 REPT 10 X=X+1 DB X ENDM 则汇编后产生 1 DB 1 1 DB 21 DB 3 ...1 DB 10
1 db char ;等效于db 'A' 1 char = char +1 1 db char ;等效于db 'B' 1 char = char +1 ... 1 db char ;等效于db 'Z' 1 char = char +1 例: 把字符A到Z的ASCII码填入数组TABLE CHAR=‘A TABLE LABEL BYTEREPT 26 DB CHARCHAR=CHAR+1 ENDM
例: 用宏定义及重复伪操作把TAB, TAB+ 1, TAB+2,...,TAB+16的内容存入堆栈. 宏定义: PUSH_TAB MACRO K PUSH TAB+K ENDM宏调用: I=0 REPT 17 PUSH_TAB % I I=I+1 ENDM
2.不定重复伪操作(1)IRP伪操作 格式是: IRP 形参,<自变量表> ... (重复块) ENDM 汇编程序把重复块的代码重复几次,每次重复把重复块中的形参用自变量表中的一项来取代,下一次取代下一项,重复次数由自变量表中的自变量个数来确定。自变量表必须用尖括号括起,它可以是常数,符号,字符串等。
例:IRP X,<1,2,3,4,5,6,7,8,9,10> DB X ENDM 汇编后得:1 DB 1 1 DB 2 ... 1 DB 10
例:IRP REG,<AX,BX,CX,DX> PUSH REG ENDM 汇编后得:1 PUSH AX 1 PUSH BX 1 PUSH CX 1 PUSH DX
(2)IRPC伪操作 格式是: IRPC 形参,字符串(或<字符串>) ... (重复块) ENDM IRPC和IRP类似,但自变量表必须是字符串.重复次数由字符串中的字符个数确定,每次重复用字符串中的下一个字符取代重复块中的形参.
例:IRPC X,0 1 2 3 4 5 6 7 DB X+1 ENDM 汇编后得:1 DB 1 1 DB 2 ... 1 DB 8
例: IRPC K,A B C D PUSH K&X ENDM 汇编后展开形成: 1 PUSH AX 1 PUSH BX 1 PUSH CX 1 PUSH DX
5. 3 条件汇编 • 汇编程序能根据条件把一段源程序包括在汇编语言程序内或者把它排除在外,这时就工用到条件伪操作。条件汇编伪指令在汇编过程中,根据条件决定汇编的语句。格式: IFxx表达式;满足,汇编分支语句体1 分支语句体1 [ ELSE ;不满足,汇编分支语句体2 分支语句体2 ] ENDIF ;条件汇编结束
自变量必须在汇编程序第一遍扫后就成为确定的数值.条件伪操作中的XX表示条件如下:自变量必须在汇编程序第一遍扫后就成为确定的数值.条件伪操作中的XX表示条件如下: IF expression:汇编程序求出表达式的值,如此值不为0则满足条件.IFE expression: 如求出表达式的值为0则满足条件.IFDEF symbol :如符号已在程序中定义,或者已用EXTRN伪操作说明该符号是在外部定义的,则满足条件.IFNDEF symbol:如符号未定义或未通过EXTRN说明为外部符号则满足条件.
IFB <argument> : 如自变量为空则满足条件IFNB<argument> : 如自变量不为空则满足条件IFIDN <argu-1>,<argu-2>:如果字符串<arg-1>和字符串<arg-2>相同,则满足条件.IFDIF <argu-1>,<argu-2>:如果字符串<arg-1>和字符串<arg-2>不相同,则满足条件. 上述IF和IFE的表达式中可以使用关系操作符EQ,NE,LT,LE,GT和GE。如:IF 表达式1 EQ 表达式2等。 条件伪操作可以用在宏定义体内,也可以用在宏定义体外,也允许嵌套任意次。
例:宏指令MAX把三个实参中的最大值放在AX中,而且使实参不同时产生不同的程序段.例:宏指令MAX把三个实参中的最大值放在AX中,而且使实参不同时产生不同的程序段. 宏定义: MAX MACRO K,A,B,C LOCAL NEXT,OUT MOV AX,A IF K-1 IF K-2 CMP C,AX JLE NEXT MOV AX,C ENDIF NEXT: CMP B,AX JLE OUT MOV AX,B ENDIF OUT: ENDM
宏调用: MAX 1,P MAX 2,P,Q MAX 3,P,Q,R宏展开: MAX 1,P 1 MOV AX,P 1 ??0001:MAX 2,P,Q 1 MOV AX,P 1 ??0002:CMP Q,AX 1 JLE ??0003 1 MOV AX,Q 1 ??0003: MAX 3,P,Q,R 1 MOV AX,P 1 CMP R,AX 1 JLE ??0004 1 MOV AX,R 1 ??0004:CMP Q,AX 1 JLE ??0005 1 MOV AX,Q 1 ??0005:
例:宏指令PDATA根据实参不同时产生不同的程序段.例:宏指令PDATA根据实参不同时产生不同的程序段. 宏定义: PDATA MACRO NUM IF NUM LT 100 ;;如果num < 100,则汇编如下语句 DB NUM DUP(?) ELSE ;;否则,汇编如下语句 DB 100 DUP(?) ENDIF ENDM 宏调用: … PDATA 12 … PDATA 102 宏展开: … DB 12 DUP(?) … DB 100 DUP(?)
例:宏指令GOTO L,X,REL,Y(其中REL可以是Z,NZ,L,NL等)可以根据不同情况产生无条件转移指令或比较和条件转移指令. 宏定义: GOTO MACRO L,X,REL,Y IFB <REL> JMP L ELSE MOV AX,X CMP AX,Y J&REL L ENDIF ENDM
宏调用: ... GOTO LOOP,SUM,NZ,15 ... GOTO EXIT ...宏展开: ... 1 MOV AX,SUM 1 CMP AX,15 1 JNZ LOOP ... 1 JMP EXIT
宏定义可允许递归调用,此时条件伪操作可用来结束宏递归。宏定义可允许递归调用,此时条件伪操作可用来结束宏递归。 例:宏指令POWER可以用来实现X和2N相乘.这只需对X左移N次可实现,可以设COUNT为递归次数的计数值,当该数与N相等时即可结束递归调用. 宏定义: POWER MACRO X,N SAL X,1 COUTN=COUT+1 IF COUNT-N POWER X,N ENDIF ENDM
宏调用:COUTN=0 POWER AX,3 宏展开:1 SAL AX,1 1 SAL AX,1 1 SAL AX,1
例: 宏指令BRANCH产生一条转向X的转移指令.当它相对于X的距离小于128字节时产生JMP SHORT X;否则产生JMP NEAR PTR X(X必须位于该转移指令之后,即低地址区)。 宏定义: BRANCH MACRO X IF ($-X) LT 128 JMP SHORT X ELSE JMP NEAR PTR X ENDIF ENDM