![關(guān)于匯編語言宏相關(guān)的所有總結(jié)_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/26/cb15319b-1733-4c67-8daa-b7fc84a0e67c/cb15319b-1733-4c67-8daa-b7fc84a0e67c1.gif)
![關(guān)于匯編語言宏相關(guān)的所有總結(jié)_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/26/cb15319b-1733-4c67-8daa-b7fc84a0e67c/cb15319b-1733-4c67-8daa-b7fc84a0e67c2.gif)
![關(guān)于匯編語言宏相關(guān)的所有總結(jié)_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/26/cb15319b-1733-4c67-8daa-b7fc84a0e67c/cb15319b-1733-4c67-8daa-b7fc84a0e67c3.gif)
![關(guān)于匯編語言宏相關(guān)的所有總結(jié)_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/26/cb15319b-1733-4c67-8daa-b7fc84a0e67c/cb15319b-1733-4c67-8daa-b7fc84a0e67c4.gif)
![關(guān)于匯編語言宏相關(guān)的所有總結(jié)_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-10/26/cb15319b-1733-4c67-8daa-b7fc84a0e67c/cb15319b-1733-4c67-8daa-b7fc84a0e67c5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、原書筆記80X86匯編語言程序設(shè)計教程宏:1. 前言:l 宏是宏匯編語言的主要特征之一!l 若某程序片段需要多次使用,為了避免重復(fù),可以將其定義為一條宏指令,利用宏指令代表該程序片段,匯編過程中,匯編器自動將宏指令替換為原程序片段。l (2015-9-16 20:43:44更新)關(guān)于宏的問題的探討,遠(yuǎn)不止于這些內(nèi)容,對于很多的細(xì)節(jié)問題,待到以后仔細(xì)查閱,此時,就不花太多時間在這些細(xì)節(jié)上了。2. 宏指令的定義和使用a. 宏指令在使用之前一定要先定義!b. 宏指令定義的一般格式如下:1. 宏指令名MACRO形式參數(shù)表2. 3. 程序片段4. 5. ENDM6. ;以下為示例:7. GETCHARM
2、ACRO;該宏指令無參數(shù)8. movah, 19. int21H10. ENDMl MACRO和ENDM是一對偽指令,成對出現(xiàn),表示宏定義的開始和結(jié)束。l 宏定義體:MACRO與ENDM之間的部分是宏定義體,可以是由指令、偽指令、宏指令構(gòu)成的程序片段l 宏指令名由用戶指定,適用一般標(biāo)號命名規(guī)則l 形式參數(shù)是可選的,并可以有一個或多個,多個形參之間用逗號間隔c. 宏調(diào)用:定義宏指令后,就可使用宏指令來表示對應(yīng)的程序片段,這稱為宏調(diào)用。一般格式如下1. 宏指令名實參列表2. ;以下為示例:3. GETCHAR4. movah, al5. ;通過調(diào)用宏指令后,將獲得的字符,傳送至ah中d. 宏展開(
3、宏擴(kuò)展):在對源程序進(jìn)行匯編時,匯編程序把源程序中的宏指令替換成對應(yīng)的宏定義體,這稱為宏展開或宏擴(kuò)展。3. 宏指令的用途a. 縮短源代碼l 將源程序中多次用到的某個程序片段(可以實現(xiàn)一定的功能,如換行、獲得一個輸入、打印一個輸出等)定義成一條宏指令,在源程序中需要的地方,直接使用宏指令即可,有效的縮短了代碼的長度,使得源代碼可讀性增強(qiáng)。b. 擴(kuò)充指令集l CPU的指令集是確定的。l 利用宏能夠在匯編語言的形式上對指令集進(jìn)行擴(kuò)充,擴(kuò)充后的指令集是 機(jī)器指令集 與 宏指令集 的并集。l 方便了源程序的編寫,也增強(qiáng)了源程序的可讀性。c. 改變某些指令助記符的意義l 宏指令名可以與指令助記符或偽操作名
4、相同,同名的情況下,宏指令的優(yōu)先級最高,而同名的指令或偽操作就失效了。l 利用以上原理,就可以實現(xiàn)改變指令助記符的意義了。4. 宏指令中參數(shù)的使用a. 宏指令可以不帶參數(shù),但是,帶參數(shù)的宏指令往往更加靈活。b. 宏指令的參數(shù)很靈活1) 宏指令的參數(shù)可以是常數(shù)、寄存器和存儲單元,還可以是表達(dá)式2) 宏指令的參數(shù)可以是操作碼c. 宏調(diào)用參數(shù)個數(shù)可以與定義時不一致l 紅調(diào)用時使用的實參個數(shù)應(yīng)該與宏定義時的形參個數(shù)一致,但是匯編程序并不要求嚴(yán)格相等。l 處理辦法:1) 若實參個數(shù)多于形參個數(shù),那么多余的實參將被忽略2) 若實參個數(shù)少于形參個數(shù),那么多余的形參將用空代替,即什么也沒有3) 另外,必須保護(hù)
5、最能展開后的程序片段是正確的,有效的。5. 特殊的宏運(yùn)算符a. 特殊的宏運(yùn)算符運(yùn)算符使用格式定義 用處&參數(shù)強(qiáng)迫替換運(yùn)算符 宏定義字符串原樣傳遞運(yùn)算符 宏調(diào)用、重復(fù)塊、重復(fù)匯編、條件匯編!字符文字字符運(yùn)算符 宏調(diào)用%表達(dá)式表達(dá)式運(yùn)算符 宏調(diào)用;注釋宏注釋 宏定義l 以上宏運(yùn)算符可用于宏定義、宏調(diào)用、重復(fù)塊b. 強(qiáng)迫替換運(yùn)算符&l (用于)宏定義中,如果形參出現(xiàn)在其他字符的緊前或緊后,或者出現(xiàn)在帶引號的字符串中,為了使匯編器識別這是一個形參符號,就必須使用該運(yùn)算符,以區(qū)分參數(shù)。以上標(biāo)注黑粗體的兩句話說明了使用強(qiáng)迫替換運(yùn)算符的兩種用法!l 注意:1) 當(dāng)在宏定義中,形參前或者形參后緊鄰形參的一個(
6、注意!只有一個不會)&符號都不會被識別為其他字符(包括在字符串中的情形),而僅用作區(qū)分形參的作用。(重要)不同的是,在字符串中,多余的&會被認(rèn)為是一個普通字符,而在字符串之外,&會被認(rèn)為是多余的字符而出錯2) 強(qiáng)迫替換運(yùn)算符不能用于變量或標(biāo)號名!注意!c. 字符串原樣傳遞運(yùn)算符l 在(用于)宏調(diào)用、重復(fù)塊和條件匯編中,將它括起來的內(nèi)容作為一個字符串,也就是作為一個整體;1) 宏調(diào)用中,若實參包含逗號或空格等間隔符,則必須使用該運(yùn)算符,以保證,實參的完整性;2) 若實參是某個有特殊意義的字符,為了使它只表示字符本身,也可使用該運(yùn)算符,把它括起來。3) 注意!使用字符串作為實參可以有兩種情況1.
7、如果字符串之間沒有逗號或者空格等分隔符,可以將沒有雙引號擴(kuò)著的字符串直接作為實參,但是,由于在宏展開過程中,是文本替換,所以,要保證,替換處的兩邊有兩個雙引號或者單引號!2. 如果字符串之間有逗號或者空格等分隔符,則必須使用字符串原樣傳遞運(yùn)算符。3. 總結(jié):實參可以有三種形式:1. 沒有雙引號或者單引號擴(kuò)著的,并且其間沒有逗號或者空格等分隔符的!2. 利用字符串原樣傳遞運(yùn)算符括起來的,沒有雙引號或者單引號擴(kuò)著的!3. 利用字符串原樣傳遞運(yùn)算符括起來的,并且有雙引號或者單引號擴(kuò)著的!雙引號或者單引號包含在尖括號之間。4. 雙引號或者單引號括起來的獨立字符串對于每一種形式,對應(yīng)的宏的編寫是不一樣的
8、,1. 宏中形參兩邊必須用雙引號括起來,并且,形參前必須添加強(qiáng)迫替換運(yùn)算符!2. 同13. 宏中形參兩邊不必用雙引號括起來!4. 同3上面的論述看起來太過復(fù)雜,我們不妨約定:當(dāng)傳遞字符串實參時,用尖括號括起來,其中不添加引號。在宏定義中,需要在對應(yīng)的字符串替換形參兩邊添加雙引號或者單引號,并且,需要在形參前添加強(qiáng)迫轉(zhuǎn)換運(yùn)算符&。 或者: 當(dāng)傳遞字符串實參時,用雙引號或者單引號括起來,不添加尖括號。在宏定義中,沒有特殊需要!d. 文字字符運(yùn)算符l 用于宏調(diào)用中的實參中!l 該運(yùn)算符用于一般字符串中,使其后的一個字符只作為一般字符。e. 表達(dá)式運(yùn)算符%l (用于)宏調(diào)用時,使用該運(yùn)算符能把其后表達(dá)
9、式的結(jié)果作為實參進(jìn)行替換,而不是表達(dá)式本身。f. 宏注釋;l 用于宏定義時!l 如果只用一個分號表示注釋的話,那么每次宏調(diào)用,注釋都會被復(fù)制一遍,為了使得宏定義中的注釋不被復(fù)制,用兩個分號對宏定義中的注釋部分進(jìn)行標(biāo)記。6. 宏與子程序的區(qū)別(主要表現(xiàn)在宏調(diào)用時的差異)a. 宏調(diào)用是通過宏指令名進(jìn)行的,多少次調(diào)用就復(fù)制多少次宏定義體;子程序在源程序中只有一份;b. 宏調(diào)用時的參數(shù)傳遞方式是通過文本替換的方式進(jìn)行的;子程序調(diào)用傳遞參數(shù)的方式只能通過寄存器、堆?;蚣s定的內(nèi)存單元進(jìn)行傳遞c. 宏調(diào)用在匯編時完成,不需要額外的時間開銷,但是耗費較多的空間;子程序在程序執(zhí)行時,通過調(diào)用返回指令,耗費一定的
10、時間,但是不耗費多余的存儲空間。7. 與宏有關(guān)的偽指令a. 局部變量說明偽指令LOCALl LOCAL標(biāo)號表l 標(biāo)號表由標(biāo)號構(gòu)成,標(biāo)號間用逗號間隔。l 使用于(宏定義體中含有標(biāo)號的宏)。l 使用于宏定義體中,必須是宏定義偽指令MACRO后的第一條語句!,MACRO與LOCAL之間不允許有注釋和分號標(biāo)志b. 清除宏定義的偽指令PURGEl PURGE宏名表l 宏名表由宏名構(gòu)成,宏名之間用逗號間隔。l 該指令告訴匯編程序取消宏名表中的宏,不再展開它們。該命令之后的對于該宏的調(diào)用,也就被匯編器無視掉了。l 該偽指令用于源程序中的任何地方!包括宏定義中和任何段之外,該偽指令不涉及機(jī)器指令,只用于匯編器
11、。c. 中止宏擴(kuò)展的偽指令EXITMl EXITMl 用在宏定義體中,常與條件偽指令一起使用,以便在規(guī)定的條件下跳過宏內(nèi)的最后的語句。l 該指令通知匯編程序結(jié)束當(dāng)前宏調(diào)用的擴(kuò)展,退出當(dāng)前宏,回到源程序或回到外層宏。d. 以上三條與宏有關(guān)的偽指令中,LOCAL與EXITM用于宏定義體中;PURGE用于其他位置或宏定義體中。8. 宏定義的嵌套(兩種類型的嵌套)a. 宏定義體中調(diào)用宏l 宏匯編語言允許在宏定義體中進(jìn)行宏調(diào)用;l 前提:在調(diào)用之前,被調(diào)用宏已經(jīng)在之前定義過了b. 宏定義體中定義宏語句l 宏定義體中允許進(jìn)行宏的定義;l 調(diào)用內(nèi)部宏的前提:只有調(diào)用了外部宏之后,才可以調(diào)用內(nèi)部宏;因為:只有
12、調(diào)用外部宏之后,內(nèi)部宏才真正被定義l 當(dāng)外部宏被調(diào)用后,外部宏中的代碼部分被寫入宏調(diào)用處,外部宏中的內(nèi)部宏定義部分并不會被寫入,可以認(rèn)為,此時,內(nèi)部宏定義由于外部宏的展開,才生效,所以,內(nèi)部宏調(diào)用的前提是外部宏已經(jīng)被調(diào)用過了。l 這里有一個小問題涉及到匯編程序的匯編過程,以后詳解。(2015-9-16 20:41:19)8.3 重復(fù)匯編1. 前言l 程序中有時會需要連續(xù)的重復(fù)完全相同或者幾乎完全相同的一組語句,這種情況下,可以考慮使用重復(fù)偽指令定義重復(fù)塊,來簡化程序。l 重復(fù)塊是允許建立重復(fù)語句塊的宏的一種特殊形式,是一種特殊的宏。l 沒有被命名的宏,因而不能被調(diào)用??;可以有參數(shù);參數(shù)在匯編過
13、程中可被實參替換;宏運(yùn)算符、用偽指令LOCAL說明的符號 等可用于重復(fù)塊;由ENDM結(jié)束2. 偽指令REPTl 一般格式如下:1. REPT表達(dá)式2. 需要重復(fù)的語句組3. ENDM4. ;實例5. CHAR=A6. dataSEGMENT7. TABLELABELBYTE;在數(shù)據(jù)段借助rept定義數(shù)據(jù)時,前面的變量名必須以這種形式(變量名+LABEL+BYTE)定義,不可以只寫一個變量名,企圖8. REPT26;直接可以連接到下行的定義部分9. DBCHAR10. CHAR = CHAR + 111. ENDM;這是一種經(jīng)典的使用方法,需要記牢,以后會有更多的更加靈活的方法等著我們?nèi)グl(fā)現(xiàn)12
14、. dataENDSl 匯編程序?qū)选靶枰貜?fù)的語句組”連續(xù)地重復(fù)匯編由表達(dá)式值所決定的次數(shù);l 表達(dá)式必須可以求出數(shù)值常數(shù)(16位無符號數(shù))l 任何有效的匯編語句均可以安排在“需要重復(fù)的匯編語句組”中l(wèi) rept語句可以出現(xiàn)在源代碼的任何部分,前提是:被重復(fù)的語句在被重復(fù)的位置處是有效的;比如說:將指令語句重復(fù)在數(shù)據(jù)段中是無效的。3. 偽指令I(lǐng)RPl 一般格式如下:1. IRP形式參數(shù),2. 需要重復(fù)的語句3. ENDM4. ;以下為一實例5. dataSEGMENT6. quartLABELBYTE;類似與上面的用法,這是一個經(jīng)典的用法7. IRPX,8. DBX*X9. ENDM;定義了
15、一個名為quart的數(shù)組,數(shù)組中依次存放著09的數(shù)的平方值10. dataENDSl 參數(shù)的個數(shù)決定了重復(fù)的次數(shù),匯編程序?qū)选靶枰獜?fù)制的語句”連續(xù)地重復(fù)匯編規(guī)定的次數(shù),并在每次匯編過程中,用相應(yīng)的實參替換“需要重復(fù)的語句”中的形參。l 實參放置在一對尖括號中,與形參之間用逗號間隔,各個實參之間也用逗號進(jìn)行間隔。4. 偽指令I(lǐng)RPCl 一般格式如下:1. IRPC形式參數(shù),字符串2. 需重復(fù)的語句組3. ENDM4. ;以下為一個示例:5. dataSEGMENT6. TABLELABELBYTE7. IRPCX, 01234567898. DW(X+1)*29. ENDM10. dataEN
16、DSl IRPC與IRP相似,除了前者的實參數(shù)列表是一個字符串以外完全一樣l 字符串的長度規(guī)定了重復(fù)的次數(shù),匯編程序?qū)选靶枰貜?fù)的語句組”連續(xù)地重復(fù)匯編指定的次數(shù),并在每次匯編時依次使用“字符串”中的一個字符作為實參代替“需要重復(fù)的語句組”中的形式參數(shù),l 如果字符串中含有空格,逗號等分隔符,那么字符串需用一對尖括號括起來!且一定不能使用雙引號或者單引號,否則雙引號或者單引號也會被當(dāng)做字符串的一部分,也就是當(dāng)做實參替換形參。l 如果沒有尖括號。1)空格之后的部分將會被忽略2)逗號之后的部分,連同逗號都會作為實參的一部分l 所以只要字符串之間沒有空格字符,所有的部分都會被當(dāng)做實參進(jìn)行傳遞,如果
17、這個實參有意義的話(一般逗號沒有意義)l 如果想要將空格作為參數(shù)的話,那就按照最初的做法,將所有參數(shù)用尖括號括起來。問題描述:在一次測試過程中,我將帶參數(shù)的重復(fù)匯編偽指令irp和irpc寫入到一個宏中,以期,通過它們在該宏中實現(xiàn)將四個寄存器壓入棧中的功能,如下所示:1. PUSHAMACRO2. irpR,3. pushR&x4. ENDM5. ENDM結(jié)果卻不如人意,編譯器提示了錯誤,而錯誤如下:1. Symbol not defined: RX *4這說明:pusha得到了展開,并且重復(fù)匯編指令也得到了展開,后者的實參并沒有對形參進(jìn)行替換!l 如果我們在代碼中直接使用irp指令,則實參會正
18、常替換形參。l 對于具有參數(shù)的irpc也具有這樣的情形。l 但是有一種例外情況,如下所示:1. DFSQUAREMACRO2. tableLABELBYTE3. irpX,4. DBX*X5. ENDM6. ENDMl 以上發(fā)生在irp語句中包含的是定義語句時!l 此問題待定,具體原因并不知道是因為什么。以后盡量避免這樣的嵌套行為。8.4 條件匯編1. 前言:a. 條件匯編提供根據(jù)某種條件決定是否匯編某段源代碼的功能。b. 在源程序中使用條件匯編語句的主要目的是:1) 通過在匯編前或匯編時改變某種條件,從而方便地產(chǎn)生功能不同的程序;2) 增強(qiáng)宏定義能力,使得宏的適用范圍更廣;3) 改善匯編效率
19、c. 條件匯編語句在形式上與高級語言中的條件語句相似,但本質(zhì)上卻是完全不同的:1) 條件匯編語句是說明性語句,由偽指令構(gòu)成,功能上由匯編程序?qū)崿F(xiàn);2) 一般情況下,高級語言的條件語句是執(zhí)行語句,由目標(biāo)程序?qū)崿F(xiàn)其功能。2. 條件匯編偽指令a. 大概:1) 一般格式如下:1. IFxxxx條件表達(dá)式2. 語句組13. ELSE4. 語句組2;條件匯編語句的可選部分5. ENDIF2) 說明:l IFxxxx 是條件偽指令助記符的一般形式,xxxx表示構(gòu)成條件偽指令助記符的其他字符;l 完整的條件偽指令助記符有:IFIFEIFDEFIFNDEFIF1IF2IFBIFNBIFIDNIFDIFl 每一個
20、條件偽指令助記符都要對應(yīng)一個條件結(jié)束偽指令助記符ENDIF,這個是統(tǒng)一的,必須的l 不同的條件指令助記符形式上可能有所不同,這里僅列出一般格式l 語句組可以包含有任意正確的語句,可以包含其他條件偽指令語句l ELSE語句組2部分是可選的l 條件匯編偽指令語句的一般意義是:如果條件偽指令要求的條件滿足,那么匯編“語句組1”,否則,在ELSE+語句組2存在的情況下,匯編語句組2,如果沒有語句組2,且條件表達(dá)式不滿足,那么不進(jìn)行匯編操作;l 匯編語言允許條件語句偽指令嵌套,且允許的嵌套次數(shù)足以滿足一般應(yīng)用需要;l 一個嵌套的ELSE偽指令,總是與最近的但又沒有ELSE相匹配的IFxxxx偽指令相匹配
21、。b. 偽指令I(lǐng)F和IFE1) 一般格式:1. IF(IFE)表達(dá)式2. 語句組13. ELSE4. 語句組25. ENDIF6. ;示例如下:7. ;示例1:8. IFMFLAG;利用一個變量作為判定對象9. movah, 0;該條件匯編偽指令選擇的是是否匯編 匯編指令語句10. int16H11. ELSE12. movah, 113. int21H14. ENDIF15. ;示例2:16. IFPORT EQ0;利用一個關(guān)系表達(dá)式作為判定對象17. PORTADDR=3F8H;該條件匯編偽指令選擇的是是否匯編 匯編偽指令語句,可以看出來,相當(dāng)靈活18. IVECTN=0BH19. IMA
22、SKV=11110111B20. ENDIF21. ;示例3(更加復(fù)雜的示例,與宏與重復(fù)塊相結(jié)合):22. SHIFTLMACROOP, N;定義了一個SHIFTL宏23. COUNT=024. REPTN;宏中包含了一個重復(fù)塊定義語句,將操作數(shù)OP每次向右算術(shù)左移一位,直到,移位的次數(shù)不小于N為止25. SHLOP, 126. COUNT=count + 127. IFCOUNT GE N;重復(fù)塊定義語句中又包含了一個條件匯編語句28. EXITM29. ENDIF;退出條件匯編語句30. ENDM;退出重復(fù)塊定義語句31. INCOP32. ENDM;退出宏定義語句2) 說明:l 偽指令I(lǐng)
23、F:如果表達(dá)式的值不等于0,則條件滿足,條件為真。非零即為真。這類似于C語言中對于條件表達(dá)式的值的判定方法。l 偽指令I(lǐng)FE:如果表達(dá)式的值等于0,則條件滿足,條件為真。相當(dāng)于IF NOT 條件表達(dá)式,與IF偽指令恰恰相反。l 上述表達(dá)式不能包含向前引用(還不能明確這個意思。),其結(jié)果應(yīng)為一常數(shù)值。一般為關(guān)系表達(dá)式或常數(shù)表達(dá)式c. 偽指令I(lǐng)FDEF和IFNDEF1) 一般格式:1. IFDEF(IFNDEF)符號2. 語句組13. ELSE4. 語句組25. ENDIF6. ;示例1:7. IFDEFMLARGE8. AXINCPROCFAR;如果MLARGE已被定義,那么將AXINC過程定義
24、為遠(yuǎn)過程。9. ELSE10. AXINCPROCNEAR;否則,將AXINC定義為近過程11. ENDIF12. incax13. ret14. AXINCENDP2) 說明:l 偽指令I(lǐng)FDEF:如果符號已定義 或已被說明為外部符號(EXTRN偽指令進(jìn)行說明),則條件滿足,即條件為真。l 偽指令I(lǐng)FNDEF:如果符號未定義或未被說明成外部符號,則條件滿足,即條件為真。又是一對兒相反的偽指令。l 符號可以在源程序中定義,也可以在匯編命令行中定義,后者參閱匯編器使用手冊。d. 偽指令I(lǐng)F1和IF21) 一般格式:1. IF1(IF2)2. 語句組13. ELSE4. 語句組25. ENDIF6
25、. ;決定匯編程序在第幾趟掃描時,匯編語句組。2) 說明:l 偽指令I(lǐng)F1:若是第一趟則為真l 偽指令I(lǐng)F2:若是第二趟則為真3. 條件匯編與宏結(jié)合a. 宏中使用條件匯編1) 條件匯編與宏結(jié)合,能大大擴(kuò)大宏的使用范圍。2) 以下為一示例:1. ADDNUMMACROREG, NUM;定義一個宏2. IF(NUM GT 2) OR (NUM LE 0);3. addREG, NUM4. ELSE5. incREG6. IFNUM EQ 27. incREG8. ENDIF9. ENDIF10. ENDM;退出宏3) 說明:l 以上示例的說明:宏ADDNUM有兩個參數(shù),在對宏調(diào)用進(jìn)行擴(kuò)展時,可以根
26、據(jù)實際參數(shù)的不同擴(kuò)展成不同的指令!l 宏,只有當(dāng)被調(diào)用時,才會在被調(diào)用的內(nèi)存空間,進(jìn)行宏的展開;既然已經(jīng)被調(diào)用,那么肯定已經(jīng)有參數(shù)向其傳遞了,所以,條件匯編指令中才能根據(jù)參數(shù)進(jìn)行一些判斷,而決定展開后的命令!l 根據(jù)以上的道理來看,匯編語言提供了有關(guān)測試宏參數(shù)的條件匯編偽指令,這更加便利了我們將宏與條件匯編語句相結(jié)合!b. 用于測試宏參數(shù)的條件匯編偽指令1) 偽指令I(lǐng)FB和IFNBl 以下為一般格式:1. IFB2. IFNB3. ;以下為一示例:4. PRINTMACROMSG;該宏的作用:當(dāng)給定實參(偏移地址)時,顯示指定的字符串,當(dāng)未給定實參時,使用默認(rèn)實參,打印默認(rèn)信息。5. IFB6
27、. movsi, DEFAULTMSG7. ELSE8. movsi, MSG9. ENDIF10. CALLSHOWIT11. ENDM12. ;事實上,以上實現(xiàn),并沒有那么簡單!以下是正確的實現(xiàn)方法!詳情見注釋13. PRINT MACRO MSG14. LOCAL begin,DEFAULTMSG;所有在宏中定義的標(biāo)號都必須使用LOCAL聲明,如果你向多次使用該宏的話15. jmp begin16. DEFAULTMSG: DB No Given Message!,0DH,0AH,$;為了使得用戶使用宏時,不用再自定義默認(rèn)消息,我們這里才宏中定義一個默認(rèn)字符串17. begin: pus
28、h ds18. push dx19. push ax;要注意保護(hù)寄存器!20.21. IFB ;IFB后面的形參必須用尖括號括起來,這里的尖括號并不是字符串原樣輸出運(yùn)算符!22. mov ax, cs;默認(rèn)字符串的段,并非程序的數(shù)據(jù)段,而是代碼段!23. mov ds, ax24. mov ah, 09H25. mov dx, OFFSET DEFAULTMSG26. ELSE27. mov ah, 09H28. mov dx, OFFSET MSG29. ENDIF30. int 21H31. pop ax32. pop dx33. pop ds34. ENDMl 這兩條偽指令一般都用于宏定
29、義體內(nèi)部。l 偽指令I(lǐng)FB:如果在宏調(diào)用時,沒有實參來代替形參,也就是沒有實參,那么條件滿足。l 偽指令I(lǐng)FNB:如果在宏調(diào)用時,有實參來代替形參,也就是有實參,那么條件滿足l 又是一對條件相反的指令。2) 偽指令I(lǐng)FIDN和IFDIFl 一般格式:1. IFIDN,2. IFIDNI,3. 4. IFDIF,5. IFDIFI,6. 7. ;以下為示例:8. ;示例1:9. RDWRMACROBUFF,RWMODE10. leadx, BUFF11. IFIDNI,;如果宏參數(shù),讀寫模式字符與READ一致,則匯編調(diào)用讀功能子程序部分12. callREADIT13. ENDIF14. IFI
30、DNI,;如果宏參數(shù),讀寫模式與WRITE一致,則匯編調(diào)用寫功能子程序部分。15. callWRITEIT16. ENDIF17. ENDM18. ;示例2:19. GETCHMACROCHAR20. movah, 121. int21H22. IFNB23. IFDIFI,24. movCHAR, AL25. ENDIF26. ENDIF27. ENDMl 這兩條指令一般都用在宏定義體內(nèi)部。l 偽指令I(lǐng)FIDN(IFIDNI):如果字符串參數(shù)1與字符串參數(shù)2相等,則條件滿足;后面添加的I是忽略大小寫的意思!l 偽指令I(lǐng)FDIF(IFDIFI):如果字符串參數(shù)1與字符串參數(shù)2不相等,則條件滿足
31、。l 參數(shù)1和參數(shù)2:有可能是宏的形參,如果是形參,則比較之前,需先用實參進(jìn)行替換后,再比較。如果不是宏的形參,則直接比較即可。l 參數(shù)一定是字符串,不需要添加引號,字符串會逐個比較大??;每一條指令都有兩種格式,普通格式時,大小寫有區(qū)別;+I格式時,大小寫沒有區(qū)別。并且該字符串一定是手動輸入到源代碼中的!Intel匯編語言程序設(shè)計1. 概述a. 宏過程(macro procedure):命名語句塊;可被調(diào)用多次;調(diào)用時,宏的副本被直接插入到程序中b. 宏過程可以必須聲明在調(diào)用宏過程之前,或者聲明在單獨的文本文件中,通過INCLUDE包含之。c. 匯編器在預(yù)處理階段處理宏的展開。d. 在80X8
32、6匯編語言程序設(shè)計教程一書中同樣有關(guān)于宏的內(nèi)容2. 宏的定義a. 方法:使用MACRO和ENDM偽指令在源程序的任意位置定義宏。b. 定義格式:1. macronameMACROparameter-1, parameter-22. statement-list3. ENDM4. ;建議對宏的名字(macroname)和ENDM之間的語句進(jìn)行縮進(jìn)5. ;statement-list即語句列表在宏被調(diào)用的時候才會被匯編;6. ;宏的定義中可以有任意多的參數(shù),參數(shù)之間用逗號間隔c. 宏的參數(shù)1) 宏的參數(shù)實際上是有名字的容器,以存放調(diào)用者傳遞給宏的文本參數(shù)。2) 說明:l 宏參數(shù)可以是整數(shù)、變量名、
33、寄存器名等等l 預(yù)處理器把各種參數(shù)統(tǒng)一視為文本進(jìn)行處理l 宏的參數(shù)沒有類型,因此預(yù)處理器并不檢查實參的類型是否與形參的類型匹配,如果不匹配,則會在匯編時由匯編器檢查。3) 示例:1. mPutcharMACROchar2. pusheax3. moval, char4. callWriteChar5. popeax6. ENDM3. 宏的調(diào)用a. 宏的調(diào)用:將宏的名字插入到需要調(diào)用宏的源碼中,并連接必要的參數(shù),即完成宏的調(diào)用。b. 格式:1. 宏名稱參數(shù)1,參數(shù)22. ;其中宏名稱必須是宏被調(diào)用前已經(jīng)在源代碼中定義號的宏的名字3. ;宏調(diào)用時每個實際參數(shù)都是一個文本值。4. ;實際參數(shù)的順序必
34、須按照宏定義時的參數(shù)順序5. ;實際參數(shù)的數(shù)目不一定與形參的數(shù)目一致:6. ;當(dāng)傳遞的參數(shù)多于定義中的形參個數(shù)時,匯編器產(chǎn)生一個警告;7. ;當(dāng)傳遞的參數(shù)少于定義中的形參個數(shù)時,那么未傳遞的參數(shù)用空參數(shù)表示。c. 說明:1) 宏代碼的執(zhí)行速度塊于過程代碼執(zhí)行,使用宏代碼可以減少程序在時間上的開銷。2) 重復(fù)使用大量的宏,會導(dǎo)致程序源代碼和程序體積增大4. 宏的其他特性a. 必須參數(shù)1) REQ修飾符可以指定宏的某個或某幾個參數(shù)是必須的,如果在宏展開中沒有獲得與之對應(yīng)的實參,則顯示一條錯誤信息。2) 示例:1. mPutCharMACROchar:REQ;注意這樣的修飾方法2. pusheax3
35、. moval, char4. callWriteChar5. popeax6. ENDMb. 宏的注釋1) 宏定義中如果有普通注釋,則每次展開時都會將該注釋一起展開。為了避免這樣,利用雙分號寫宏注釋,則不會展開。2) 示例:1. mPutCharMACROchar:REQ2. pusheax;注意保護(hù)寄存器3. moval, char4. callWriteChar5. popeax6. ENDMc. ECHO偽指令1) 匯編器匯編源碼的過程中,ECHO偽指令可以在控制臺顯示一條消息。2) 示例:1. mPutcharMACRO char:REQ2. ECHO“Expanding the m
36、Putchar macro!”3. pusheax4. moval, char5. callWriteChar6. popeax7. ENDM3) 注意:l 顯示消息是在匯編過程中!而不是在程序執(zhí)行過程中l(wèi) 顯式的字符串不需要添加雙引號,否則會連同雙引號一同輸出。d. LOCAL偽指令1) 問題:宏定義中如果使用了標(biāo)號,在多次調(diào)用之后,標(biāo)號在宏展開后的源代碼中便會多次出現(xiàn),導(dǎo)致符號重定義的錯誤!2) 使用LOCAL偽指令可以完美解決上述問題:3) 使用方法:1. makeStringMACROtext2. LOCALstring3. .data4. stringBYTEtext,05. END
37、M6. ;另一個例子:7. AgainMACRO8. LOCALloop09. movecx, 1010. loop0:11. inceax12. looploop013. ENDM4) LOCAL后可以跟多個標(biāo)號,標(biāo)號之間用逗號間隔e. 包含代碼和數(shù)據(jù)的宏1) 一般方法:在宏定義中,同時定義一個數(shù)據(jù)段和一個代碼段,即完成了包含數(shù)據(jù)和代碼的操作。2) 示例:1. mWriteMACROtext2. LOCALstring3. .data4. stringBYTEtext,05. .code6. pushedx7. movedx, OFFSET string8. callWriteString9
38、. popedx10. ENDMf. 宏的嵌套1) 在另外一個宏內(nèi)被調(diào)用的宏稱為嵌套宏(nested macro)2) 盡量使用模塊化的方法創(chuàng)建宏,保持每個宏的簡短,以便用于創(chuàng)造更復(fù)雜的宏,這樣做有助于減少程序中的重復(fù)代碼。3) 示例:1. mWriteLnMACROtext2. mWritetext;宏mWrite已經(jīng)在上一段代碼中定義過了3. callCrlf4. ENDM5. 使用本書附帶的宏庫a. 大概1) .inc文件是文本文件,即包含文件,我們可以將很多宏定義在一個獨立的文本文件中,然后在需要調(diào)用它們的源代碼文件中包含該文件即可!2) 本節(jié)所羅列的所有宏:宏的名字參數(shù)描述mDump
39、varName,useLabel顯示一個變量,使用變量名及變量的默認(rèn)屬性mDumpMemaddress,itemCount,componentSize顯示一塊內(nèi)存的內(nèi)容mGotoxyx,y設(shè)置控制臺緩沖區(qū)中光標(biāo)的位置mShowvarName從鍵盤讀取一個字符串mReadStringitsName,fomat以多種格式顯示一個變量或寄存器mShowRegisterregName,regValue顯示一個32位的寄存器的名字及其內(nèi)容,以十六進(jìn)制格式mWritetext在控制臺窗口中顯示一個字符串mWriteSpacecount在控制臺窗口中顯示一個或多個空格mWriteStringbuffer在控
40、制臺窗口中顯示一個字符變量的內(nèi)容b. mDumpMem1) 功能描述:在控制臺窗口顯示一塊內(nèi)存的內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù)包含要顯示的內(nèi)存偏移地址的常量、寄存器或變量l 第二個參數(shù):要顯示的項目的數(shù)量l 第三個參數(shù):單個項目的字節(jié)數(shù),該參數(shù)也指明了最后顯示結(jié)果的形式!3) 實現(xiàn)1. mDumpMemMACROaddress:REQ,itemCount:REQ,componentSize:REQ2. pushebx3. pushecx4. pushesi5. movesi, address6. movecx, itemCount7. movebx, componentSize8. cal
41、lDumpMem9. popesi10. popecx11. popebx12. ENDMc. mDump1) 功能描述:以十六進(jìn)制格式顯示變量的地址和內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):變量的名字l 第二個參數(shù):(可選的)傳遞一個字符Y或者是N表示是否顯示變量的名字3) 實現(xiàn)1. mDumpMACROvarName:REQ, useLabel2. callCrlf3. IFNBuseLabel4. mWrite “Variable name: &varName”5. ENDIF6. mDumpMemOFFSET varName,LENGTHOF varName,TYPE varName7.
42、ENDMd. mGotoxy1) 功能描述:把光標(biāo)定位在屏幕上指定的位置2) 參數(shù)解釋:l 第一個參數(shù):Xl 第二個參數(shù):Y,X和Y可以是8位的立即數(shù)或內(nèi)存操作數(shù)或寄存器3) 實現(xiàn)1. mGotoxyMACRO X:REQ,Y:REQ2. pushedx3. movdh, Y4. movdl, X5. callGotoxy6. popedx7. ENDMe. mReadString1) 功能描述:從鍵盤上讀取一個字符串并把該字符串存儲在一個緩沖區(qū)中2) 參數(shù)解釋:l 第一個參數(shù):緩沖區(qū)的名字,或者是存儲緩沖區(qū)偏移地址的寄存器3) 實現(xiàn)1. mReadStringMACROvarName:REQ
43、2. pushecx3. pushedx4. movedx, OFFSET varName5. movecx, SIZEOF varName6. callReadString7. popedx8. popecx9. ENDMf. mShow1) 功能描述: 以調(diào)用者選定的格式顯示任意寄存器或變量的名字和內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):寄存器或變量名l 第二個參數(shù):輸出參數(shù):H = 十六進(jìn)制 D = 無符號十進(jìn)制整數(shù) I = 有符號十進(jìn)制整數(shù) B = 二進(jìn)制 N = 添加一個換行符 可以組合多種輸出格式,也可以指定多個換行符默認(rèn)格式:HIN3) 實現(xiàn)該宏的實現(xiàn)過長,該宏定義在Macros.i
44、nc包含文件中g(shù). mShowRegister1) 功能描述:以十六進(jìn)制格式顯示一個32位寄存器的內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):對于該寄存器要顯示的名字,被用作字符串。l 第二個參數(shù):該寄存器的名字,被用來取值3) 實現(xiàn)1. mShowRegisterMACROregName,regValue2. LOCAL tempStr3. .data4. tempStrBYTE“®Name=”,05. .code6. pushedx7. movedx, OFFSET tempStr8. callWriteString9. popedx10. 11. moveax, regValue12. c
45、allWriteHex13. popeax14. ENDMh. mWriteString1) 功能描述:在控制臺窗口顯示一個字符串的內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):字符串名3) 實現(xiàn)1. mWriteStringMACRO buffer:REQ2. pushedx3. movedx, OFFSET buffer4. callWriteString5. popedx6. ENDMi. mWriteSpace1) 功能描述:在控制臺窗口顯示一個或多個空格2) 參數(shù)解釋:l 第一個參數(shù):一個數(shù)字,指定空格的數(shù)量,默認(rèn)個數(shù)是13) 實現(xiàn)1. mWriteSpaceMACROcount:=;默認(rèn)實參
46、的寫法2. LOCAL spaces3. .data4. spacesBYTEcount DUP( ),05. .code6. pushedx7. movecx, OFFSET spaces8. callWriteString9. popedx10. ENDM6. 例子程序:封裝10.3 條件匯編偽指令 與 宏0.前言a. 條件匯編偽指令和宏聯(lián)合使用可以使得宏更加靈活。b. 本節(jié)看似在講述關(guān)于條件匯編偽指令的相關(guān)內(nèi)容,但是無不聯(lián)系了宏的應(yīng)用!c. 一般格式1. IFcondition2. statement3. ELSE4. statement5. ENDIFd. 本章介紹的是:常量條件偽指令
47、;6.7節(jié)介紹的是:運(yùn)行時偽指令e. 條件匯編偽指令概況偽指令說明IF 表達(dá)式如果表達(dá)式為真(非0)則允許匯編。可以使用的相關(guān)操作符有LT,GT,NE,LE,GEIFB如果參數(shù)為空則允許匯編,參數(shù)名必須用尖括號()括起來IFNB如果參數(shù)不為空則允許匯編,參數(shù)名必須用尖括號括起來IFIDN,如果兩個參數(shù)相同則允許匯編,參數(shù)比較是大小寫敏感的IFIDNI,如果兩個參數(shù)相同則允許匯編,參數(shù)比較是不區(qū)分大小寫的。IFDIF,如果兩個參數(shù)不同則允許匯編,參數(shù)比較是大小寫敏感的。IFDIFI,如果兩個參數(shù)不同則允許匯編,參數(shù)比較是不區(qū)分大小寫的。IFDEF 名字如果名字已經(jīng)定義則允許匯編IFNDEF 名字
48、如果名字未定義則允許匯編ENDIF結(jié)束一個條件匯編偽指令開始的語句塊ELSE如果前面的條件匯編偽指令的條件均為假,則匯編該偽指令至ENDIF偽指令之間的語句ELSEIF 表達(dá)式如果前面的條件匯編偽指令的條件均為假,則匯編該偽指令至下一條匯編偽指令之間的語句EXITM立即退出宏,組織其后任何語句的展開1. 檢查缺少的參數(shù)(介紹使用了IFB條件匯編偽指令的用途!)a. 宏可以通過條件匯編偽指令檢查其任何一個參數(shù)是否為空。b. 背景:當(dāng)宏的用戶使用宏,某個參數(shù)為空時,有可能生成錯誤的指令,在匯編時產(chǎn)生錯誤。為了減少宏的用戶產(chǎn)生此類錯誤,需要檢查缺失參數(shù),并做防范措施。c. 示例:1. mWriteStrMACRO string2. IFB;當(dāng)用戶未提供參數(shù)時,在預(yù)處理階段就顯示出錯信息,并不展開宏3. ECHO -4. ECHO * Error: parameter missing in mWriteStr5. ECHO * (no code
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 人民版道德與法治九年級上冊第七課《生命之間》配套聽課評課記錄
- 湘教版七年級數(shù)學(xué)下冊第2章2.1.2冪的乘方與積的乘方(第1課時)聽評課記錄
- 人教版七年級數(shù)學(xué)上冊:1.2.1《有理數(shù)》聽評課記錄
- 冀教版數(shù)學(xué)九年級上冊《平行線分線段成比例》聽評課記錄1
- 《兩漢的科技和文化》聽課評課記錄1(新部編人教版七年級上冊歷史)
- 蘇教版四年級數(shù)學(xué)下冊期末復(fù)習(xí)口算練習(xí)題三
- 湘教版數(shù)學(xué)八年級上冊《小結(jié)練習(xí)》聽評課記錄
- 聽評課記錄數(shù)學(xué)二年級
- 小學(xué)生營養(yǎng)餐飯?zhí)霉ぷ魅藛T聘用合同范本
- 人員派遣租賃協(xié)議書范本
- 防洪防汛安全知識教育課件
- (正式版)FZ∕T 80014-2024 潔凈室服裝 通 用技術(shù)規(guī)范
- 新起點英語二年級下冊全冊教案
- 【幼兒園戶外體育活動材料投放的現(xiàn)狀調(diào)查報告(定量論文)8700字】
- 剪映專業(yè)版:PC端短視頻制作(全彩慕課版) 課件 第3章 短視頻剪輯快速入門
- 湖南省長沙市開福區(qū)青竹湖湘一外國語學(xué)校2023-2024學(xué)年九年級下學(xué)期一模歷史試題
- 帶狀皰疹與帶狀皰疹后遺神經(jīng)痛(HZ與PHN)
- 漢密爾頓抑郁和焦慮量表
- 風(fēng)電場事故案例分析
- 前列腺癌的診斷與治療
- 人教版八年級數(shù)學(xué)初中數(shù)學(xué)《平行四邊形》單元教材教學(xué)分析
評論
0/150
提交評論