




已閱讀5頁(yè),還剩86頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第8章 高級(jí)匯編技術(shù),8.1 宏匯編 8.2 重復(fù)匯編和條件匯編 8.3 匯編語(yǔ)言與高級(jí)語(yǔ)言的混合編程,8.1 宏匯編,說(shuō)明: 宏名必須是惟一的,它代表著所定義的宏體的內(nèi)容,在其后面的源程序中,可通過(guò)該名字來(lái)調(diào)用宏。 形式參數(shù)表是用逗號(hào)(或空格,或制表符)分隔的一個(gè)或多個(gè)形式參數(shù)。它是可選項(xiàng)。選用了形式參數(shù)時(shí),所定義的宏稱(chēng)為帶參數(shù)的宏。當(dāng)調(diào)用宏時(shí),需用對(duì)應(yīng)的實(shí)際參數(shù)去取代,以實(shí)現(xiàn)向宏中傳遞信息。, 宏體可以是匯編語(yǔ)言所允許的任意指令和偽指令語(yǔ)句序列,它決定了宏的功能。在宏體中還可以定義或調(diào)用另一個(gè)宏,這就是宏嵌套。 宏一經(jīng)定義,就像為指令系統(tǒng)增加了新的指令一樣,在程序中就可像指令一樣通過(guò)宏名對(duì)它進(jìn)行任意次的調(diào)用,故又稱(chēng)為宏指令或宏調(diào)用。要注意的是,宏定義必須放在第一條調(diào)用它的指令之前,一般都將它放在程序的開(kāi)頭。,2宏的調(diào)用與展開(kāi) (1) 在匯編語(yǔ)言源程序中,為了使在源程序中不重復(fù)書(shū)寫(xiě)需要多次使用的程序段,可以用一條宏指令來(lái)代替,由匯編程序在匯編時(shí)產(chǎn)生所需要的代碼。 例如,為了實(shí)現(xiàn)ASCII碼與BCD碼之間的相互轉(zhuǎn)換,往往需要把AL中的內(nèi)容左移4位或右移4位,可以用80x86的指令來(lái)實(shí)現(xiàn)。若要左移4位,可用: MOV CL,4 SAL AL,CL,若要多次使用,就可以用一條宏指令來(lái)代替,宏定義是: SHIFT MACRO MOV CL,4 SAL AL,CL ENDM 這樣,以后凡要使AL中的內(nèi)容左移4位,就可以用這條宏指令SHIFT來(lái)代替。,宏定義中,SHTFT是宏指令名,MACRO是宏定義的定義符,ENDM是宏定義的結(jié)束符,這兩者必須成對(duì)出現(xiàn)。 宏匯編一般由可執(zhí)行的指令語(yǔ)句和管理語(yǔ)句(即由偽指令構(gòu)成的語(yǔ)句)所構(gòu)成。經(jīng)宏定義后,就可以引用宏指令,這稱(chēng)作宏調(diào)用。宏匯編程序遇到這樣的調(diào)用時(shí),就用對(duì)應(yīng)的宏體來(lái)代替這條宏指令,以產(chǎn)生目的代碼,這稱(chēng)作宏展開(kāi)。,(2) 宏定義不但能使源程序的書(shū)寫(xiě)簡(jiǎn)潔,而且由于宏指令具有接收參量的能力,所以功能就更靈活。 例如,上述的宏指令只能使AL中的內(nèi)容左移4位。若每次使用時(shí),要移位的次數(shù)不同,或要使不同的寄存器移位,就不方便了。但是,若在宏定義中引入?yún)⒘浚涂梢詽M(mǎn)足上述要求。,例8-1 定義滿(mǎn)足不同移位次數(shù)要求的宏。 SHIFT MACRO X MOV CL,X SAL CL,CL ENDM 其中,X是一個(gè)形式參量(此處用來(lái)代表移位次數(shù))。在調(diào)用時(shí)可把實(shí)際要求的移位次數(shù)作為實(shí)在參量代入。如 SHIFT 4 就可以用實(shí)在參量4代替在宏定義體中出現(xiàn)的形式參量X,從而實(shí)現(xiàn)左移4位的功能。,又如: SHIFT 6 就可以左移6次。這樣,就可以由調(diào)用時(shí)的實(shí)在參數(shù)來(lái)規(guī)定任意的移位次數(shù)。,例8-2 定義滿(mǎn)足使用不同寄存器實(shí)現(xiàn)移位要求的宏,可再引入一個(gè)形式參量Y。 SHIFT MACRO X,Y MOV CL,X SAL Y,CL ENDM 用形式參量Y來(lái)代替需要移位的寄存器。只要在調(diào)用時(shí),把要移位的寄存器作為實(shí)在參量代入,就可以對(duì)任一個(gè)寄存器實(shí)現(xiàn)指定的左移次數(shù)。 SHIFT 4,AL SHIFT 4,BX SHIFT 6,DI,在匯編這些宏指令時(shí),分別產(chǎn)生以下指令語(yǔ)句,宏匯編程序在每一條由宏展開(kāi)產(chǎn)生的指令前冠以加號(hào)“+”: +MOV CL,4 +SAL AL,CL +MOV CL,4 +SAL BX,CL +MOV CL,6 +SAL DI,CL 第一條宏指令使AL左移4位;第二條宏指令使16位寄存器BX左移4位;第三條宏指令使DI左移6位。,(3) 形式參量不僅可以出現(xiàn)在操作數(shù)部分,也可以出現(xiàn)在操作碼部分。 例8-3 用宏指令定義操作碼。 SHIFT MACRO X,Y,Z MOV CL,X S&Z Y,CL ENDM 其中第三個(gè)形式參量Z代替操作碼中的一部分。若在宏定義體中的形式參量沒(méi)有適當(dāng)?shù)姆指舴?,則不被看作為形式參量,調(diào)用時(shí)也不被實(shí)在參量所代替。,例如,上例中的操作碼部分S&Z中,若Z與S之間沒(méi)有分隔,則此處的Z就不被看作形式參量。要定義它為形式參量,必須在其前面加上符號(hào)&。所以S&Z中Z就被看作是形式參量。若有以下調(diào)用: SHIFT 4,AL,AL SHIFT 6,BX,AR SHIFT 8,SI,HR,在匯編這些宏指令時(shí),分別產(chǎn)生以下指令語(yǔ)句。 +MOV CL,4 +SAL AL,CL +MOV CL,6 +SAR BX,CL +MOV CL,8 +SHR SI,CL 這里的SHIFT宏指令可以對(duì)任一個(gè)寄存器進(jìn)行任意的移位操作(算術(shù)左移、算術(shù)右移、邏輯右移、可移任意指定的位數(shù))。,宏指令名是一個(gè)宏定義調(diào)用的依據(jù),也是不同宏定義相互區(qū)分的標(biāo)志,是必須要有的。對(duì)于宏指令名的規(guī)定與對(duì)標(biāo)識(shí)符的規(guī)定是一致的。宏定義中的形式參量表是任選的,可以沒(méi)有形式參量,也可以有若干形式參量。若有一個(gè)以上的形式參量時(shí),它們之間必須用逗號(hào)分隔。對(duì)形式參量的規(guī)定與對(duì)標(biāo)識(shí)符的規(guī)定是一致的。形式參量的個(gè)數(shù)沒(méi)有限制,只要一行限制在152個(gè)字符以?xún)?nèi)就行。在調(diào)用時(shí)的實(shí)在參量多于1個(gè)時(shí),也要用逗號(hào)分隔,它們與形式參量在順序上相對(duì)應(yīng)。但I(xiàn)BM宏匯編并不要求它們?cè)跀?shù)量上必須一致。若調(diào)用時(shí)的實(shí)在參量多于形式參量,則多余的部分被忽略;若實(shí)在參量少于形式參量,則多余的形式參量變?yōu)镹ULL(空)。,2) PURGE 一個(gè)宏指令名,可以用偽指令PURGE來(lái)取消,然后就可以重新定義。 格式: PURGE 宏指令名, 功能:取消多個(gè)宏定義。,例8-4 X=0 REPT 10 X=X+1 DB X ENDM 實(shí)現(xiàn)的功能是把1到10分配給10個(gè)連續(xù)的內(nèi)存單元。,例8-5 IRP X, DB X ENDM 因?yàn)閰?shù)表中的參數(shù)個(gè)數(shù)為10,故指令體部分重復(fù)執(zhí)行10次。例8-4中的指令體部分只有一條偽指令DB X,其中X為形式參量。在第一次執(zhí)行時(shí)用參數(shù)表中的第一個(gè)參數(shù)1代替形式參量,就為DB 1;第二次執(zhí)行時(shí),用參數(shù)表中的第二個(gè)參數(shù)2代替形式參量,就為DB 2; 所以例8-4也是把1到10分配給10個(gè)連續(xù)的內(nèi)存單元。,例8-6 IRPC X, DB X ENDM 實(shí)現(xiàn)的功能是:把字符A到F分配給內(nèi)存中的6個(gè)連續(xù)單元。 以上MACRO、REPT、IRP和IRPC 4個(gè)宏定義的偽指令都必須以偽指令ENDM作為它的結(jié)束符。,有兩點(diǎn)需要特別指出: 宏定義也可以像程序設(shè)計(jì)語(yǔ)言中的標(biāo)準(zhǔn)函數(shù)一樣,構(gòu)成一個(gè)標(biāo)準(zhǔn)函數(shù)庫(kù),供其他源程序使用。以文件的形式組織若干個(gè)宏定義即形成宏程序庫(kù)。程序設(shè)計(jì)中使用了宏程序庫(kù)中的宏定義時(shí),在源程序中應(yīng)使用INCLUDE偽指令。宏匯編程序在匯編源程序時(shí),當(dāng)遇到該偽指令,就把INCLUDE偽指令所包含的宏程序庫(kù)中的文件掃描一遍,如同在程序中使用自己定義的宏一樣,在后面的程序中就可以對(duì)宏庫(kù)中的宏定義直接進(jìn)行宏調(diào)用了。, 與子程序一樣,宏定義也可以嵌套。宏定義的嵌套有兩種方式:宏定義嵌套和宏定義內(nèi)嵌套宏調(diào)用。在一個(gè)宏定義中包含了另一個(gè)宏定義,則稱(chēng)為宏定義嵌套;在一個(gè)宏定義的宏體內(nèi)有宏調(diào)用,則稱(chēng)為宏定義內(nèi)嵌套宏調(diào)用。在宏定義內(nèi)嵌套宏調(diào)用中,被調(diào)用的宏指令必須是已定義的。宏定義嵌套常用于產(chǎn)生一些新的宏定義,而宏定義內(nèi)嵌套宏調(diào)用則可以使宏定義簡(jiǎn)化,功能單一,便于通過(guò)組合的方法實(shí)現(xiàn)一個(gè)功能較為復(fù)雜的宏定義。,8.1.3 LOCAL偽指令 如果宏定義中含有變量名或標(biāo)號(hào),且在同一源程序中又多次被宏調(diào)用,那么宏匯編程序在宏展開(kāi)時(shí),產(chǎn)生多個(gè)相同的變量名或標(biāo)號(hào),這就不能滿(mǎn)足變量名和標(biāo)號(hào)在同一程序中必須惟一的要求,從而產(chǎn)生匯編出錯(cuò),即產(chǎn)生“ERROR A2005:SYMBOL IS MULTIDEFINED”的錯(cuò)誤。為達(dá)到在宏定義中使用變量名和標(biāo)號(hào),又能避免這個(gè)錯(cuò)誤的目的,可在宏定義中使用局部符號(hào)偽指令LOCAL對(duì)變量名或標(biāo)號(hào)進(jìn)行說(shuō)明。,格式: LOCAL 功能:對(duì)在符號(hào)表中的每個(gè)符號(hào),在匯編時(shí)每擴(kuò)展一次便建立一個(gè)“?XXXX”惟一的符號(hào),保證匯編時(shí)生成名字的惟一性。 說(shuō)明: (1) 符號(hào)表是在宏定義中定義的變量名和標(biāo)號(hào),多個(gè)符號(hào)之間用逗號(hào)分隔。 (2) LOCAL偽指令指定的變量名和標(biāo)號(hào)自動(dòng)生成格式為“?XXXX”,符號(hào)的后四位順序使用0000FFFF的十六進(jìn)制數(shù)字。,8.1.4 宏和過(guò)程的比較 宏和過(guò)程都可用來(lái)簡(jiǎn)化源程序,并可使程序多次對(duì)它們進(jìn)行調(diào)用,從而使程序結(jié)構(gòu)簡(jiǎn)潔清晰,符合結(jié)構(gòu)化程序設(shè)計(jì)風(fēng)格。因此,對(duì)于那些需重復(fù)使用的程序模塊,既可用過(guò)程也可用宏來(lái)實(shí)現(xiàn)。,宏和過(guò)程的主要區(qū)別在于: (1) 宏操作可以直接傳遞和接收參數(shù),它不需通過(guò)棧等其他媒介來(lái)進(jìn)行,因此編程比較容易。而過(guò)程不能直接帶有參數(shù),當(dāng)過(guò)程之間需要傳遞參數(shù)時(shí),必須通過(guò)棧、寄存器或存儲(chǔ)器來(lái)進(jìn)行,所以相對(duì)于宏而言,它的編程要復(fù)雜一些。,(2) 宏調(diào)用只能簡(jiǎn)化源程序的書(shū)寫(xiě),縮短源程序長(zhǎng)度,它并沒(méi)有縮短目標(biāo)代碼的長(zhǎng)度,匯編程序處理宏指令時(shí),是把宏體插入到宏調(diào)用處,所以目標(biāo)程序占用內(nèi)存空間并不因宏操作而減少。而過(guò)程(子程序)調(diào)用卻能縮短目標(biāo)程序的長(zhǎng)度,因?yàn)檫^(guò)程在源程序的目標(biāo)代碼中只有一段,無(wú)論主程序調(diào)用多少次,除了增加CALL和RET指令的代碼外,并不增加子程序段代碼。 (3) 引入宏操作并不會(huì)在執(zhí)行目標(biāo)代碼時(shí)增加額外的時(shí)間開(kāi)銷(xiāo)。相反,過(guò)程調(diào)用由于需要保護(hù)和恢復(fù)現(xiàn)場(chǎng)及斷點(diǎn),因而有額外的時(shí)間開(kāi)銷(xiāo),會(huì)延長(zhǎng)目標(biāo)程序的執(zhí)行時(shí)間。,若在一個(gè)源程序中多次調(diào)用一段程序,則可用子程序,也可以用宏指令來(lái)簡(jiǎn)化源程序。用子程序的方法,匯編后產(chǎn)生的目標(biāo)代碼少,即目標(biāo)程序占用的內(nèi)存空間少,節(jié)約內(nèi)存空間。但是,子程序在執(zhí)行時(shí),每調(diào)用一次都要先保護(hù)斷點(diǎn),通常在程序中還要保護(hù)現(xiàn)場(chǎng)。同樣,在返回時(shí),先要恢復(fù)現(xiàn)場(chǎng),然后恢復(fù)斷點(diǎn)(返回)。這些操作都額外增加了時(shí)間,因而執(zhí)行時(shí)間長(zhǎng),速度慢。而宏指令恰好相反,它的目標(biāo)程序長(zhǎng),占用的內(nèi)存單元多,但在執(zhí)行時(shí)不需要保護(hù)斷點(diǎn)、現(xiàn)場(chǎng)以及恢復(fù)、返回等這些額外操作,因而執(zhí)行時(shí)間短,速度快。,所以,當(dāng)要代替的程序段較短,速度是主要矛盾時(shí),通常用宏指令。而當(dāng)要代替的程序段較長(zhǎng),額外操作所附加的時(shí)間不明顯,節(jié)省存儲(chǔ)空間是主要矛盾時(shí),通常用子程序。宏指令是機(jī)器的指令系統(tǒng)中沒(méi)有的,但又可以作為一條指令使用。所以,從形式上看,宏指令擴(kuò)充了機(jī)器的指令系統(tǒng)。,8.2 重復(fù)匯編和條件匯編,8.2.1 重復(fù)匯編 在匯編程序設(shè)計(jì)中,經(jīng)常要連續(xù)地重復(fù)相同的或幾乎完全相同的代碼序列,這時(shí)可以使用重復(fù)偽指令。 1重復(fù)偽指令 宏匯編語(yǔ)言提供的重復(fù)偽指令包括REPT、IRP、IRPC,其格式、功能及使用說(shuō)明在8.1.2節(jié)中已講述,這里不再贅述。,2重復(fù)偽指令應(yīng)用舉例 例8-7 使用不同重復(fù)偽指令定義10個(gè)數(shù)據(jù),使其內(nèi)容分別為0,1,9。 第一種方法,使用REPT偽指令: COUNT0 REPT 10 DB COUNT COUNTCOUNT+1 ENDM,第二種方法,使用IRP偽指令: IRP X , DB X ENDM 第三種方法,使用IRPC偽指令: IRPC X 0123456789 DB X ENDM,以上三種方法具有同樣的功能,匯編后產(chǎn)生的代碼如下: + DB 0 + DB 1 + DB 2 + DB 3 + DB 4 + DB 5 + DB 6 + DB 7 + DB 8 + DB 9,例8-8 下面兩條重復(fù)偽指令具有相同的功能。 (1) IRP指令: IRP REG, POP REG ENDM,(2) IRPC指令: IRPC R ABCD POP RX ENDM 匯編后它們產(chǎn)生的代碼如下: + POP AX + POP BX + POP CX + POP DX,8.2.2 條件匯編 條件匯編偽指令可使匯編程序根據(jù)某種條件對(duì)某部分源程序有選擇地進(jìn)行匯編,在形式上和高級(jí)語(yǔ)言中的條件語(yǔ)句類(lèi)似,但實(shí)質(zhì)不同。條件匯編語(yǔ)句是一種說(shuō)明性語(yǔ)句,其功能由匯編系統(tǒng)實(shí)現(xiàn);而一般高級(jí)語(yǔ)言的條件語(yǔ)句是執(zhí)行性語(yǔ)句,其功能由目標(biāo)程序?qū)崿F(xiàn)。 條件匯編語(yǔ)句通常在宏定義中使用,使得宏定義的適用范圍更廣。一般情況下,使用條件匯編語(yǔ)句可使一個(gè)源文件產(chǎn)生幾個(gè)不同的源程序,它們可有不同的功能。,格式:IF 條件 語(yǔ)句序列1 ELSE 語(yǔ)句序列2 ENDIF 功能:當(dāng)條件為真(滿(mǎn)足)時(shí)執(zhí)行匯編語(yǔ)句序列1,否則執(zhí)行匯編語(yǔ)句序列2。,說(shuō)明:“條件”為IF偽指令說(shuō)明符的一部分,ELSE偽指令及其后面的語(yǔ)句序列2是可選擇部分,表示條件為假(不滿(mǎn)足)時(shí)的情況。如果屬于非完全分支的判斷,就不用這部分。整個(gè)條件匯編最后必須用ENDIF偽指令來(lái)結(jié)束。語(yǔ)句序列1和語(yǔ)句序列2中的語(yǔ)句是任意的,也可為條件匯編語(yǔ)句。 以下5組條件匯編開(kāi)始語(yǔ)句均可選用ELSE語(yǔ)句,以便匯編條件為假時(shí)執(zhí)行語(yǔ)句序列2,但一個(gè)IF語(yǔ)句只能有一個(gè)ELSE與之對(duì)應(yīng)。,1) 是0否條件語(yǔ)句 語(yǔ)句有:IF和IFE。 IF語(yǔ)句。 格式:IF 表達(dá)式 功能:表達(dá)式值非0,則條件為真,執(zhí)行匯編語(yǔ)句序列1。 IFE語(yǔ)句。 格式:IFE 表達(dá)式 功能:表達(dá)式值為0,則條件為真,執(zhí)行匯編語(yǔ)句序列1。,2) 掃描1否條件語(yǔ)句 語(yǔ)句有:IF1和IF2。 IF1語(yǔ)句。 格式:IF1 功能:匯編處于第一次掃描時(shí)條件為真。 IF2語(yǔ)句。 格式:IF2 功能:匯編處于第二次掃描時(shí)條件為真。,3) 符號(hào)有定義否條件語(yǔ)句 語(yǔ)句有:IFDEF和IFNDEF。 IFDEF語(yǔ)句。 格式:IFDEF 符號(hào) 功能:符號(hào)已被定義或已由EXTRN偽指令說(shuō)明,則條件為真。 IFNDEF語(yǔ)句。 格式:IFNDEF 符號(hào) 功能:符號(hào)未被定義或未由EXTRN偽指令說(shuō)明,則條件為真。,4) 空否條件語(yǔ)句 語(yǔ)句有:IFB和IFNB。 IFB語(yǔ)句。 格式:IFB 功能:參數(shù)為空格,則條件為真。尖括號(hào)不能省略。 IFNB語(yǔ)句 格式:IFNB 功能:參數(shù)不為空格,則條件為真。尖括號(hào)不能省略。,5) 字符串比較條件語(yǔ)句 語(yǔ)句有:IFIDN和IFDEF。 IFIDN語(yǔ)句。 格式:IFIDN , 功能:字符串1與字符串2相同,則條件為真。, IFDIF語(yǔ)句 格式:IFDIF , 功能:字符串1與字符串2不相同,則條件為真。 說(shuō)明:這兩條語(yǔ)句只能在宏定義中使用,檢查傳送給兩個(gè)參數(shù)的實(shí)參是否相同。 例8-9 將輸入及輸出字符的DOS功能調(diào)用放在一個(gè)宏定義中,通過(guò)判斷參數(shù)為0還是非0值來(lái)選擇是執(zhí)行匯編輸入還是輸出的DOS功能。,所編制的程序描述如下,其中含有條件匯編的語(yǔ)句。 INOUT MACRO X IF X MOV AH,2 INT 21H ;輸出DL中的字符 ELSE MOV AH,1 INT 21H ;輸入一個(gè)字符到AL ENDIF ENDM,當(dāng)宏調(diào)用為INOUT 0時(shí),表明傳遞給參數(shù)X的值為0,此時(shí)IF X的條件為假,因此匯編程序只匯編ELSE與ENDIF之間的語(yǔ)句,這樣,對(duì)該宏調(diào)用來(lái)說(shuō),實(shí)際上是執(zhí)行下面的兩條指令: MOV AH,1 INT 21H 而當(dāng)宏調(diào)用為INOUT 1時(shí),實(shí)際上是執(zhí)行這樣兩條指令: MOV AH,2 INT 21H,8.3 匯編語(yǔ)言與高級(jí)語(yǔ)言的混合編程,8.3.1 調(diào)用協(xié)議 匯編程序和匯編語(yǔ)言常常以在線(xiàn)匯編語(yǔ)言代碼的形式,通過(guò)過(guò)程同高級(jí)語(yǔ)言,如C/C+、BACIC、PASCAL及FORTRAN一起使用。需要指出的是,這里盡管講的是使用Microsoft匯編語(yǔ)言過(guò)程,但只要提供兼容的調(diào)用協(xié)議,大多數(shù)其他語(yǔ)言也能夠使用。 在與高級(jí)語(yǔ)言接口時(shí),匯編程序使用兩種調(diào)用協(xié)議:一是用于C/C+語(yǔ)言的C語(yǔ)言調(diào)用協(xié)議,二是用于BASIC、PASCAL和FORTRAN語(yǔ)言的PASCAL語(yǔ)言調(diào)用協(xié)議。調(diào)用協(xié)議語(yǔ)言在MODEL語(yǔ)句中或與PROC語(yǔ)句相聯(lián)系的OPTION指示符中指定。除用這些語(yǔ)句以外還可以用完全段定義指定。,1C語(yǔ)言調(diào)用協(xié)議 C語(yǔ)言調(diào)用協(xié)議從右到左壓入?yún)?shù),像它們?cè)趨?shù)表里放的那樣,帶著放在棧上的參數(shù)從匯編語(yǔ)言過(guò)程返回,返回結(jié)果或者放在A(yíng)X中或者放在DXAX中。在BP、DI、SI、DS、SS和方向標(biāo)志位被改動(dòng)之前應(yīng)使用匯編語(yǔ)言過(guò)程保存起來(lái)。這些寄存器是高級(jí)語(yǔ)言能用到的。圖8-1給出了C語(yǔ)言調(diào)用協(xié)議下近調(diào)用和遠(yuǎn)調(diào)用的棧。,圖8-1 使用C語(yǔ)言調(diào)用協(xié)議時(shí)的棧內(nèi)容 (a) 近程調(diào)用;(b) 遠(yuǎn)程調(diào)用,對(duì)棧內(nèi)參數(shù)的訪(fǎng)問(wèn)由C語(yǔ)言調(diào)用協(xié)議提供,如例8-10所示。帶*號(hào)的語(yǔ)句是匯編程序加上的,以保持與C語(yǔ)言調(diào)用協(xié)議的一致。注意搞清楚BP的內(nèi)容如何被壓入棧中,以及BP是如何被裝入SP值以訪(fǎng)問(wèn)由C語(yǔ)言程序放在棧中的參數(shù)這兩個(gè)問(wèn)題。,例8-10 .LISTALL .MODEL SMALL,C SSS PROTO C,A:SWORD,A:SWORD .CODE SSS PROC C,A:SWORD,B:SWORD PUSH BP ;保存BP MOV BP,SP ;棧地址存入BP MOV AX,A ;使用參數(shù)A ADD AX,B ;使用參數(shù)B POP BP ;恢復(fù)BP RET 00000H SSS ENDP END,根據(jù)C語(yǔ)言調(diào)用協(xié)議編寫(xiě)的匯編語(yǔ)言過(guò)程通過(guò)指令I(lǐng)NVOKE而被調(diào)用。INVOKE用來(lái)替代標(biāo)準(zhǔn)的CALL指令。INVOKE遵循C語(yǔ)言調(diào)用協(xié)議,允許匯編語(yǔ)言程序訪(fǎng)問(wèn)C語(yǔ)言程序和函數(shù)。INVOKE指令被用來(lái)訪(fǎng)問(wèn)例8-10中的過(guò)程,例如,INVOKE SSS,20,30實(shí)現(xiàn)把30加上20后,結(jié)果放入AX中并返回。INVOKE與CALL的不同之處,按照調(diào)用協(xié)議的要求,INVOKE指令必須將參數(shù)從棧中全部移出。INVOKE指令的語(yǔ)法要求過(guò)程名后必須跟著全部的參數(shù),參數(shù)間用逗號(hào)隔開(kāi)。,2INVOKE指令的使用 用 PUSH把參數(shù)壓入堆棧,如果不小心把參數(shù)個(gè)數(shù)搞錯(cuò)了,就會(huì)使堆棧不平衡,從而使程序從堆棧中取出錯(cuò)誤的返回地址,引起不可預(yù)料的后果。所以有必要用一條語(yǔ)句來(lái)完成自動(dòng)檢驗(yàn)的任務(wù)。INVOKE語(yǔ)句是能自動(dòng)將所有的參數(shù)壓入棧中,并檢測(cè)參數(shù)個(gè)數(shù)、類(lèi)型是否正確,使用 CALL來(lái)調(diào)用的一個(gè)宏指令。 INVOKE在匯編程序中調(diào)用子程序時(shí),其參數(shù)的傳遞是通過(guò)堆棧來(lái)進(jìn)行的。例如,MessageBox()函數(shù)在USER32.INC文件中是這樣聲明的: MESSAGEBOX(HWND HWND,LPCTSTR LPTEXT,LPCTSTR LPCAPTION,UINT UTYPE),,在匯編程序中可這樣調(diào)用它: PUSH UTYPE PUSH LPCAPTION PUSH LPTEXT PUSH HWND CALL MessageBox PUSH為匯編語(yǔ)言中的進(jìn)棧指令。上面語(yǔ)句的原理是先將函數(shù)所需要的參數(shù),壓入到堆棧中去,然后再用CALL指令來(lái)調(diào)用該函數(shù)。,需要注意的是,在上述的參數(shù)進(jìn)棧過(guò)程中,是從左到右依次壓入的,即最右面的參數(shù)是最后一個(gè)進(jìn)堆棧,采用的是PASCAL規(guī)則。引入INVOKE語(yǔ)句后,就可自動(dòng)的將所調(diào)用子程序中的參數(shù)壓入堆棧中,而無(wú)須編程者用手工壓入。所以上面的代碼就可以變?yōu)?INVOKE MessageBox,NULL,addr szText,addr szCaption,MB_OK。 addr是用來(lái)把變量參數(shù)的地址傳遞給被調(diào)用的函數(shù)(注意,是所指變量在內(nèi)存中的地址,而不是變量中的值),它只能在INVOKE語(yǔ)句中使用。,3PASCAL語(yǔ)言調(diào)用協(xié)議 PASCAL語(yǔ)言調(diào)用協(xié)議用于BASIC、PASCAL和FORTRAN語(yǔ)言,在WINDOWS中,它也被用于訪(fǎng)問(wèn)WINDOWS庫(kù)文件(WINH.LIB)中的函數(shù)。PASCAL語(yǔ)言調(diào)用協(xié)議與C語(yǔ)言調(diào)用協(xié)議的差異在于:參數(shù)是自左至右壓入棧中。如果用在匯編語(yǔ)言過(guò)程中時(shí),PASCAL語(yǔ)言調(diào)用協(xié)議也需要保存寄存器SI、DI、DS和SS的內(nèi)容。方向標(biāo)志位在登錄時(shí)要被清零,并以清除狀態(tài)被返回。和在C語(yǔ)言調(diào)用協(xié)議中一樣,INVOKE語(yǔ)句也用于由匯編語(yǔ)言進(jìn)出高級(jí)語(yǔ)言過(guò)程。,這一點(diǎn)在匯編語(yǔ)言同WINDOWS一起使用時(shí)格外重要,以INVOKE MessageBeep,-1為例,如果WINH.LIB庫(kù)文件已被程序裝載,則該指令使揚(yáng)聲器發(fā)出“嘀”的一聲。其他參數(shù)也可與MessageBeep一起使用,從而由WINDOWS發(fā)出各種失敗提示音。在C語(yǔ)言程序中,通過(guò)在C語(yǔ)言程序的開(kāi)頭使用指令#INCLUDE ,就可以訪(fǎng)問(wèn)WINDOWS應(yīng)用程序接口(API)。,圖8-2 使用PASCAL語(yǔ)言調(diào)用協(xié)議時(shí)棧內(nèi)容,圖8-2給出了從PASCAL中調(diào)用函數(shù)時(shí)的棧,注意:所有這些語(yǔ)言調(diào)用的函數(shù)都被認(rèn)為是遠(yuǎn)程調(diào)用,BP給出了存儲(chǔ)參數(shù)的棧的地址。最右邊的參數(shù)的地址為BP+6,這一點(diǎn)與C語(yǔ)言調(diào)用協(xié)議正好相反。同C語(yǔ)言調(diào)用協(xié)議一樣,隱蔽的指令將BP壓入棧,并將SP寫(xiě)入BP。,4數(shù)據(jù)類(lèi)型,表8-1 各種數(shù)據(jù)類(lèi)型的比較,8.3.2 與C語(yǔ)言的接口 例8-11 本例給出了一個(gè)被C語(yǔ)言程序調(diào)用的過(guò)程,該過(guò)程使用MODEL語(yǔ)句指示內(nèi)存模型(本例為小模型)和相應(yīng)的調(diào)用協(xié)議語(yǔ)言(C語(yǔ)言)。PROTO語(yǔ)句把本過(guò)程作為外部函數(shù)聲明,并指定了全部與本過(guò)程相關(guān)的參數(shù)的大小和名稱(chēng)。本過(guò)程被作為一個(gè)近程調(diào)用 .MODEL SMALL,C X1 PROTO C,l:SWORD,F(xiàn):SWORD .CODE,X1 PROC C,l:SWORD,LSWORD FILDPI ;取出 FADD ST,ST(0) ;計(jì)算2pi MOV AX,1 ;取1 MOV TEMP,AX FILD TEMP ;取l FMUL ;計(jì)算2pil MOV AX,F(xiàn) ;取F MOV TEMP,AX FILD TEMP ;取F FMUL ;計(jì)算2pilf FISTP TEMP ;保存結(jié)果,MOV AX,TEMP ;取結(jié)果用以返回C RET X1 ENDP TEMP DW ? ;暫存區(qū) END,本過(guò)程使用數(shù)值協(xié)處理器計(jì)算電抗值,使用公式X1=2lF。其中,參數(shù)F和l從C語(yǔ)言程序中傳送到匯編語(yǔ)言過(guò)程中,返回值(X1)作為一個(gè)字長(zhǎng)的整型變量由AX傳回C語(yǔ)言程序。通過(guò)BP+4和BP+6給出的地址,可以從棧中取出l和F的數(shù)據(jù)。本例中的MOV AX,l指令,若轉(zhuǎn)換為代碼應(yīng)為MOV AX,BP+4,通過(guò)該指令可從棧中取出l值。,例8-12 本例給出了主模塊的C語(yǔ)言調(diào)用順序,該程序順序打印出電感系數(shù)為4H,頻率為1000 Hz的電抗值。注意:本程序中的計(jì)算結(jié)果被變換為整型。 #include extern int xl(int l,int f); void main() printf(“The inductive reactance of 4 H at 1000 Hz isdn“,xl(4,1000); ,8.3.3 與PASCAL語(yǔ)言的接口 1有關(guān)的PASCAL語(yǔ)句和調(diào)用約定 PASCAL語(yǔ)言沒(méi)有提供CALL調(diào)用語(yǔ)句。PASCAL主程序?qū)R編語(yǔ)言子程序的調(diào)用是通過(guò)外部過(guò)程和外部函數(shù)調(diào)用的形式來(lái)實(shí)現(xiàn)的。為了保證調(diào)用的正確實(shí)施,PASCAL主程序和被調(diào)用的匯編語(yǔ)言子程序都要遵從一定的調(diào)用約定。PASCAL語(yǔ)言中的過(guò)程和函數(shù)有所不同。,1) 過(guò)程方式 在PASCAL程序中,對(duì)要調(diào)用的匯編語(yǔ)言過(guò)程必須預(yù)先采用PROCEDURE說(shuō)明語(yǔ)句加以定義說(shuō)明。PROCEDURE語(yǔ)句的格式為: PROCEDURE過(guò)程名(參數(shù)表):過(guò)程屬性; 這樣,PROCEDURE語(yǔ)句將向PASCAL編譯程序提供如下信息: (1) 被調(diào)用的過(guò)程名; (2) 此過(guò)程是內(nèi)部過(guò)程還是外部過(guò)程; (3) 過(guò)程的參數(shù)名和類(lèi)型; (4) 是“數(shù)值參數(shù)”還是“引用參數(shù)”。,由于匯編語(yǔ)言子程序是單獨(dú)編寫(xiě)和匯編的,它相對(duì)PASCAL主程序而言總是外部的。所以,其“過(guò)程屬性”為EXTERN。并且,過(guò)程名必須在匯編語(yǔ)言程序中用PUBLIC偽指令加以說(shuō)明。第(3)項(xiàng)的過(guò)程參數(shù)名和類(lèi)型是符合PASCAL要求的變量標(biāo)識(shí)符和數(shù)據(jù)類(lèi)型。在進(jìn)行PASCAL過(guò)程調(diào)用時(shí),過(guò)程參數(shù)也是通過(guò)棧來(lái)進(jìn)行傳遞的。第(4)項(xiàng)的“數(shù)值參數(shù)”和“引用參數(shù)”涉及到是傳遞參數(shù)變量值,還是傳遞參數(shù)變量地址的問(wèn)題。當(dāng)一個(gè)變量是數(shù)值參數(shù)時(shí),主程序把此變量的值入棧,即傳遞給被調(diào)用過(guò)程;否則,主程序把此變量的地址入棧。作為引用參數(shù)的變量,在PROCEDURE語(yǔ)句中須用VAR或VARS來(lái)加以說(shuō)明。兩者的區(qū)別在于:對(duì)由VAR說(shuō)明的參數(shù),主程序須將其變量地址的偏移量入棧;而對(duì)由VARS說(shuō)明的參數(shù),除變量地址的偏移量外,主程序還要將此變量地址的段地址入棧。語(yǔ)句:,PROCEDURE ADDP(A,B:INTEGER;VAR C:INTEGER):EXTERN;,定義了一個(gè)有3個(gè)參數(shù)的外部過(guò)程ADDP。其中,變量A和B是整型數(shù)值參數(shù),而變量C是整型引用參數(shù);一旦匯編語(yǔ)言過(guò)程在PASCAL主程序中經(jīng)由PROCEDURE語(yǔ)句定義說(shuō)明后,PASCAL主程序就可以采用相應(yīng)的過(guò)程調(diào)用語(yǔ)句來(lái)調(diào)用此匯編語(yǔ)言過(guò)程了,過(guò)程調(diào)用語(yǔ)句的格式為 過(guò)程名(參數(shù)表) 對(duì)上面的ADDP過(guò)程,其相應(yīng)的過(guò)程調(diào)用語(yǔ)句為 ADDP(A,B,C) 其中,A,B,C是PASCAL主程序中的整型變量。,在被調(diào)用的匯編語(yǔ)言子程序中,PASCAL對(duì)過(guò)程的要求是: (1) 由于寄存器SP不能用于一般的尋址方式,通常用BP來(lái)存取傳遞的調(diào)用參數(shù)。所以,在過(guò)程程序開(kāi)始時(shí)要先把BP的原有內(nèi)容入棧保存,并在返回PASCAL主程序之前恢復(fù)內(nèi)容。另外,若要在子程序中改變DS和SS等寄存器的內(nèi)容,也須加以保存和恢復(fù)。 (2) 由于是外部過(guò)程,在返回PASCAL主程序時(shí)應(yīng)采用長(zhǎng)返回指令,即進(jìn)行段間返回。 (3) 在返回時(shí),應(yīng)取消棧參數(shù),即主程序傳遞給此過(guò)程的所有調(diào)用參數(shù)。,下面是用匯編語(yǔ)言編寫(xiě)的ADDP過(guò)程程序,在程序中,PUBLIC指令將過(guò)程名ADDP存放。 CODE SEGMENT ASSUME CSCODE ADDP PROC FAR PUBLIC ADDP PUSH BP MOV BP,SP PUSH AX,PUSH BX MOV AX,BP+10 ADD AX,BP+8 MOV BXBP+6 MOV BX,AX POP BX POP AX POP BP RET 6 ADDP ENDP,過(guò)程的FAR屬性使得后面的RET指令成為長(zhǎng)返回指令。RET指令中的整數(shù)用于消去棧參數(shù),它在返回后將自動(dòng)加入到SP寄存器中。程序的“RET 6”指令執(zhí)行前后棧內(nèi)容的變化如圖8-3所示。 當(dāng)ADDP過(guò)程的C變量為VARS引用參數(shù)時(shí),相應(yīng)的匯編語(yǔ)言程序有所不同。由于C的段地址,A和B的地址由BP+10和BP+8變?yōu)锽P+12和BP+10。同時(shí),“RET 6”變?yōu)椤癛ET 8”。除此之外,由于C變量不是當(dāng)前DS寄存器所指數(shù)據(jù)段中的變量,對(duì)它的存取方式也與前不同,如圖8-4所示。,圖8-3 棧變化,圖8-4 C變量為VARS引用參數(shù)時(shí)的堆棧結(jié)構(gòu),CODE SEGMENT ASSUME CSCODE ADDP PROC FAR PUBLIC ADDP PUSH BP MOV BP,SP PUSH AX PUSH BX PUSH ES MOV AX,BP+12,ADD AX,BP+10 LES BX, BP+6 MOV ESBX,AX POP ES POP BX POP AX POP BP RET 8 ADDP ENDP CODE ENDS END,2) 函數(shù)方式 函數(shù)方式同過(guò)程方式很相似。在PASCAL程序中,對(duì)要調(diào)用的匯編函數(shù)也必須預(yù)先加以說(shuō)明。不過(guò),此時(shí)采用的是FUNCTION說(shuō)明語(yǔ)句,而不是PROCEDURE說(shuō)明語(yǔ)句。 FUNCTION語(yǔ)句的格式為 FUNCTION 函數(shù)名(參數(shù)表):函數(shù)類(lèi)型;函數(shù)屬性; 在FUNCTION語(yǔ)句中,除增加了一個(gè)“函數(shù)類(lèi)型”外,其余同PROCEDURE語(yǔ)句一樣?!昂瘮?shù)類(lèi)型”符合PASCAL要求的數(shù)據(jù)類(lèi)型的語(yǔ)句。如: FUNCTION ADDF(A,B:INTEGER):INTEGER:EXTERN; 說(shuō)明定義了一個(gè)名為ADDF的外部整型函數(shù)。,PASCAL對(duì)匯編函數(shù)的要求,除在程序完成后必須返回函數(shù)值外,其余同過(guò)程完全一樣。一般來(lái)說(shuō),函數(shù)可通過(guò)AL、AX、ESBX或調(diào)用者提供的緩沖區(qū)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 刀剪產(chǎn)品的品牌推廣策略與執(zhí)行計(jì)劃考核試卷
- 豬的飼養(yǎng)智能化管理考核試卷
- 竹材加工過(guò)程中的質(zhì)量控制考核試卷
- 皮革制品的消費(fèi)心理與購(gòu)買(mǎi)決策考核試卷
- 盾構(gòu)機(jī)施工中的隧道工程地質(zhì)環(huán)境保護(hù)策略考核試卷
- 廈門(mén)醫(yī)學(xué)院《心理測(cè)量學(xué)》2023-2024學(xué)年第一學(xué)期期末試卷
- 無(wú)錫科技職業(yè)學(xué)院《人體工程學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 西昌民族幼兒師范高等專(zhuān)科學(xué)?!赌X癱兒童功能評(píng)估》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)化工大學(xué)《語(yǔ)文》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)職業(yè)技術(shù)學(xué)院《外國(guó)文學(xué)作品欣賞》2023-2024學(xué)年第二學(xué)期期末試卷
- 藥劑科終止妊娠藥品管理制度
- 除草劑分類(lèi)和使用方法
- 合同制消防員績(jī)效考核細(xì)則詳解
- 中遠(yuǎn)集團(tuán)養(yǎng)老保險(xiǎn)工作管理程序
- 留守兒童幫扶記錄表
- 門(mén)禁一卡通系統(tǒng)解決方案
- 變電站第二種工作票
- 煤礦機(jī)電運(yùn)輸專(zhuān)業(yè)質(zhì)量標(biāo)準(zhǔn)化管理制度
- 機(jī)電一體化專(zhuān)業(yè)畢業(yè)論文43973
- 基于PLC的變頻中央空調(diào)溫度控制系統(tǒng)的畢業(yè)設(shè)計(jì)
- 第三部分110kv模塊第34章1b1y1
評(píng)論
0/150
提交評(píng)論