循環(huán)指令,子程序指令 一、循環(huán)是一種特殊的轉(zhuǎn)移流程,當(dāng)滿足(或不滿足)某條件時,反復(fù)執(zhí)行一系列操作,直到不滿足(或滿足)條件為止。循環(huán)流成的條件一般都是循環(huán)計數(shù),在程序中用循環(huán)計數(shù)來控制循環(huán)次數(shù)。 LOOP LABEL ;CX←CX-1;若CX≠0,循環(huán):IP←IP+位移量;否則,順序執(zhí)行 LOOPZ/LOOPE LABEL ;CX←CX-1;若CX≠0且ZF=1,循環(huán):IP←IP+位移量;否則,順序執(zhí)行 LOOPNZ/LOOPNE LABEL ;CX←CX-1;若CX≠0且ZF=0,循環(huán):IP←IP+位移量;否則,順序執(zhí)行 LOOP指令首先將計數(shù)值CX減1,然后判斷計數(shù)值CX是否為零。CX不為0,則繼續(xù)執(zhí)行循環(huán)體內(nèi)的指令;CX等于0,表示循環(huán)結(jié)束,于是程序退出循環(huán),順序執(zhí)行后面的指令。LOOPZ和LOOPNZ指令中油要求同時ZF為1或0才能循環(huán),用于判斷結(jié)果是否為零或相等,以便提前結(jié)束循環(huán)。循環(huán)指令中的操作數(shù)LABEL采用相對尋址方式,表示循環(huán)的目標(biāo)地址,是一個8位位移量。循環(huán)指令不影響標(biāo)志。 例17-1:在字節(jié)數(shù)組中找出第一個非零元素,并顯示輸出第一個非零元素的下標(biāo)。 NAME LI17-1.ASM DATA SEGMENT ARRAY DB 0,0,0,7,0,0,4,34,25,30 COUNT EQU $-OFFSET ARRAY DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BEGIN: MOV AX,DATA MOV DS,AX MOV CX,COUNT MOV DI,0FFFFH NEXT: INC DI CMP ARRAY[DI],0 LOOPZ NEXT JNE OKENTRY MOV DL,'0' JMP DISPLAY OKENTRY:MOV DX,DI OR DL,30H DISPLAY:MOV AH,02H INT 21H MOV AH,4CH INT 21H CODE ENDS END BEGIN 例17-2:求兩個一維字?jǐn)?shù)組的和,數(shù)組元素個數(shù)為N,當(dāng)計算到兩個數(shù)組對應(yīng)元素之和為零時就停止求和(假設(shè)數(shù)組元素為無符號二進制數(shù))。 NAME LI17-2.ASM DATA SEGMENT ARRAY1 DW 23,34,4,5,66,76,0,345,567,23,12,67 ARRAY2 DW 34,24,3,2,44,79,0,345,56,43,21,567 N EQU $-OFFSET ARRAY2 SUM DW 15 DUP(?) DATA ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE BEGIN: MOV AX,DATA MOV DS,AX MOV AX,0 MOV SI,0FFFEH MOV CX,N SHR CX,1 NOZERO: INC SI INC SI MOV AX,ARRAY1[SI] ADD AX,ARRAY2[SI] MOV SUM[SI],AX LOOPNZ NOZERO JNZ L MOV DL,'Y' JMP Q L: MOV DL,'N' Q: MOV AH,02H INT 21H MOV AH,4CH INT 21H CODE ENDS END BEGIN 二、子程序指令 程序中有些部分可能要實現(xiàn)相同的功能,而且這些功能需要用到,用子程序?qū)崿F(xiàn)這個功能是很適合的。子程序通常是與主程序分開的、完成特定功能的一段程序。當(dāng)主程序(調(diào)用程序)需要執(zhí)行這個功能時,就可以調(diào)用該子程序(被調(diào)用程序);于是,程序轉(zhuǎn)移到這個子程序的起始處執(zhí)行。當(dāng)運行完子程序后,再返回調(diào)用它的主程序。子程序由主程序執(zhí)行子程序調(diào)用指令CALL來調(diào)用;而子程序執(zhí)行完后用子程序返回指令RET,返回主程序繼續(xù)執(zhí)行。CALL和RET指令均不影響標(biāo)志位。 1、子程序調(diào)用指令CALL CALL指令用在主程序中,實現(xiàn)子程序的調(diào)用。子程序和主程序可以在同一個代碼段內(nèi),也可以在不同段內(nèi)。類似無條件轉(zhuǎn)移JMP指令,子程序調(diào)用CALL指令也可以分成段內(nèi)調(diào)用(近調(diào)用)和段間調(diào)用(遠調(diào)用);同時,CALL目標(biāo)地址也可以采用直接尋址或間接尋址方式。但是,子程序執(zhí)行結(jié)束時要返回的,所以,CALL指令不僅要同JMP指令一樣改變CS:IP以實現(xiàn)轉(zhuǎn)移,而且還要保留下一條要執(zhí)行指令的地址,以便返回時重新獲取它。保護CS:IP值的方法是壓入堆棧,獲取CS:IP值的方法就是彈出堆棧。 CALL指令的4種格式: CALL LABEL ;段內(nèi)調(diào)用,直接尋址:SP←SP-2,SS:[SP]←IP,IP←IP+16位位移量 CALL R16/M16 ;段內(nèi)調(diào)用,間接尋址:SP←SP-2,SS:[SP]←IP,IP←R16/M16 CALL FAR PTR LABEL ;段間調(diào)用,直接尋址:SP←SP-2,SS:[SP]←CS,SP←SP-2,SS:[SP]←IP ;IP←LABEL偏移地址,CS←LABEL段地址 CALL FAR PTR MEM ;段間調(diào)用,間接尋址:SP←SP-2,SS:[SP]←CS,SP←SP-2,SS:[SP]←IP ;IP←[MEM],CS←[MEM+2] 根據(jù)過程偽指令,匯編程序可以自動確定是段內(nèi)還是段間調(diào)用,同時可以采用NEAR或FAR偽指令強制成為近調(diào)用或遠調(diào)用。 2、子程序返回指令RET 子程序執(zhí)行完后,應(yīng)返回主程序中繼續(xù)執(zhí)行,這一功能由RET指令完成。要回到主程序,只要能獲得離開主程序時,由CALL指令保存于堆棧的指令地址即可。根據(jù)子程序與主程序是否同處于一個段內(nèi),返回指令分為段內(nèi)返回和段間返回。 RET指令的4種格式如下: RET ;無參數(shù)段內(nèi)返回:IP←SS:[SP],SP←SP+2 RET I16 ;有參數(shù)段內(nèi)返回:IP←SS:[SP],SP←SP+2,SP←SP+I16 RET ;無參數(shù)段間返回:IP←SS:[SP],SP←SP+2,CS←SS:[SP],SP←SP+2 RET I16 ;有參數(shù)段間返回:IP←SS:[SP],SP←SP+2,CS←SS:[SP],SP←SP+2,SP←SP+I16 盡管段內(nèi)返回和段間返回具有相同的匯編助記符,但匯編程序會自動產(chǎn)生不同的指令代碼;也可以分別采用RETN和RETF表示段內(nèi)和段間返回。返回指令還可以帶有一個立即數(shù)I16,則堆棧指針SP將增加,即SP←SP+I16。這個特點使得程序可以方便的廢除若干執(zhí)行CALL指令以前入棧的參數(shù)。
|