




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、原書筆記80X86匯編語言程序設(shè)計教程宏:1. 前言:l 宏是宏匯編語言的主要特征之一!l 若某程序片段需要多次使用,為了避免重復(fù),可以將其定義為一條宏指令,利用宏指令代表該程序片段,匯編過程中,匯編器自動將宏指令替換為原程序片段。l (2015-9-16 20:43:44更新)關(guān)于宏的問題的探討,遠不止于這些內(nèi)容,對于很多的細節(jié)問題,待到以后仔細查閱,此時,就不花太多時間在這些細節(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、宏擴展):在對源程序進行匯編時,匯編程序把源程序中的宏指令替換成對應(yīng)的宏定義體,這稱為宏展開或宏擴展。3. 宏指令的用途a. 縮短源代碼l 將源程序中多次用到的某個程序片段(可以實現(xiàn)一定的功能,如換行、獲得一個輸入、打印一個輸出等)定義成一條宏指令,在源程序中需要的地方,直接使用宏指令即可,有效的縮短了代碼的長度,使得源代碼可讀性增強。b. 擴充指令集l CPU的指令集是確定的。l 利用宏能夠在匯編語言的形式上對指令集進行擴充,擴充后的指令集是 機器指令集 與 宏指令集 的并集。l 方便了源程序的編寫,也增強了源程序的可讀性。c. 改變某些指令助記符的意義l 宏指令名可以與指令助記符或偽操作名
4、相同,同名的情況下,宏指令的優(yōu)先級最高,而同名的指令或偽操作就失效了。l 利用以上原理,就可以實現(xiàn)改變指令助記符的意義了。4. 宏指令中參數(shù)的使用a. 宏指令可以不帶參數(shù),但是,帶參數(shù)的宏指令往往更加靈活。b. 宏指令的參數(shù)很靈活1) 宏指令的參數(shù)可以是常數(shù)、寄存器和存儲單元,還可以是表達式2) 宏指令的參數(shù)可以是操作碼c. 宏調(diào)用參數(shù)個數(shù)可以與定義時不一致l 紅調(diào)用時使用的實參個數(shù)應(yīng)該與宏定義時的形參個數(shù)一致,但是匯編程序并不要求嚴(yán)格相等。l 處理辦法:1) 若實參個數(shù)多于形參個數(shù),那么多余的實參將被忽略2) 若實參個數(shù)少于形參個數(shù),那么多余的形參將用空代替,即什么也沒有3) 另外,必須保護
5、最能展開后的程序片段是正確的,有效的。5. 特殊的宏運算符a. 特殊的宏運算符運算符使用格式定義 用處&&參數(shù)強迫替換運算符 宏定義<><字符串>字符串原樣傳遞運算符 宏調(diào)用、重復(fù)塊、重復(fù)匯編、條件匯編!字符文字字符運算符 宏調(diào)用%表達式表達式運算符 宏調(diào)用;注釋宏注釋 宏定義l 以上宏運算符可用于宏定義、宏調(diào)用、重復(fù)塊b. 強迫替換運算符&l (用于)宏定義中,如果形參出現(xiàn)在其他字符的緊前或緊后,或者出現(xiàn)在帶引號的字符串中,為了使匯編器識別這是一個形參符號,就必須使用該運算符,以區(qū)分參數(shù)。以上標(biāo)注黑粗體的兩句話說明了使用強迫替換運算符的兩種用法
6、!l 注意:1) 當(dāng)在宏定義中,形參前或者形參后緊鄰形參的一個(注意!只有一個不會)&符號都不會被識別為其他字符(包括在字符串中的情形),而僅用作區(qū)分形參的作用。(重要)不同的是,在字符串中,多余的&會被認(rèn)為是一個普通字符,而在字符串之外,&會被認(rèn)為是多余的字符而出錯2) 強迫替換運算符不能用于變量或標(biāo)號名!注意!c. 字符串原樣傳遞運算符<>l 在(用于)宏調(diào)用、重復(fù)塊和條件匯編中,將它括起來的內(nèi)容作為一個字符串,也就是作為一個整體;1) 宏調(diào)用中,若實參包含逗號或空格等間隔符,則必須使用該運算符,以保證,實參的完整性;2) 若實參是某個有特殊意義的字符,
7、為了使它只表示字符本身,也可使用該運算符,把它括起來。3) 注意!使用字符串作為實參可以有兩種情況1. 如果字符串之間沒有逗號或者空格等分隔符,可以將沒有雙引號擴著的字符串直接作為實參,但是,由于在宏展開過程中,是文本替換,所以,要保證,替換處的兩邊有兩個雙引號或者單引號!2. 如果字符串之間有逗號或者空格等分隔符,則必須使用字符串原樣傳遞運算符。3. 總結(jié):實參可以有三種形式:1. 沒有雙引號或者單引號擴著的,并且其間沒有逗號或者空格等分隔符的!2. 利用字符串原樣傳遞運算符括起來的,沒有雙引號或者單引號擴著的!3. 利用字符串原樣傳遞運算符括起來的,并且有雙引號或者單引號擴著的!雙引號或者
8、單引號包含在尖括號之間。4. 雙引號或者單引號括起來的獨立字符串對于每一種形式,對應(yīng)的宏的編寫是不一樣的,1. 宏中形參兩邊必須用雙引號括起來,并且,形參前必須添加強迫替換運算符!2. 同13. 宏中形參兩邊不必用雙引號括起來!4. 同3上面的論述看起來太過復(fù)雜,我們不妨約定:當(dāng)傳遞字符串實參時,用尖括號括起來,其中不添加引號。在宏定義中,需要在對應(yīng)的字符串替換形參兩邊添加雙引號或者單引號,并且,需要在形參前添加強迫轉(zhuǎn)換運算符&。 或者: 當(dāng)傳遞字符串實參時,用雙引號或者單引號括起來,不添加尖括號。在宏定義中,沒有特殊需要!d. 文字字符運算符l 用于宏調(diào)用中的實參中!l 該運算符用于
9、一般字符串中,使其后的一個字符只作為一般字符。e. 表達式運算符%l (用于)宏調(diào)用時,使用該運算符能把其后表達式的結(jié)果作為實參進行替換,而不是表達式本身。f. 宏注釋;l 用于宏定義時!l 如果只用一個分號表示注釋的話,那么每次宏調(diào)用,注釋都會被復(fù)制一遍,為了使得宏定義中的注釋不被復(fù)制,用兩個分號對宏定義中的注釋部分進行標(biāo)記。6. 宏與子程序的區(qū)別(主要表現(xiàn)在宏調(diào)用時的差異)a. 宏調(diào)用是通過宏指令名進行的,多少次調(diào)用就復(fù)制多少次宏定義體;子程序在源程序中只有一份;b. 宏調(diào)用時的參數(shù)傳遞方式是通過文本替換的方式進行的;子程序調(diào)用傳遞參數(shù)的方式只能通過寄存器、堆?;蚣s定的內(nèi)存單元進行傳遞c.
10、 宏調(diào)用在匯編時完成,不需要額外的時間開銷,但是耗費較多的空間;子程序在程序執(zhí)行時,通過調(diào)用返回指令,耗費一定的時間,但是不耗費多余的存儲空間。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)用,也就被匯
11、編器無視掉了。l 該偽指令用于源程序中的任何地方!包括宏定義中和任何段之外,該偽指令不涉及機器指令,只用于匯編器。c. 中止宏擴展的偽指令EXITMl EXITMl 用在宏定義體中,常與條件偽指令一起使用,以便在規(guī)定的條件下跳過宏內(nèi)的最后的語句。l 該指令通知匯編程序結(jié)束當(dāng)前宏調(diào)用的擴展,退出當(dāng)前宏,回到源程序或回到外層宏。d. 以上三條與宏有關(guān)的偽指令中,LOCAL與EXITM用于宏定義體中;PURGE用于其他位置或宏定義體中。8. 宏定義的嵌套(兩種類型的嵌套)a. 宏定義體中調(diào)用宏l 宏匯編語言允許在宏定義體中進行宏調(diào)用;l 前提:在調(diào)用之前,被調(diào)用宏已經(jīng)在之前定義過了b. 宏定義體中定
12、義宏語句l 宏定義體中允許進行宏的定義;l 調(diào)用內(nèi)部宏的前提:只有調(diào)用了外部宏之后,才可以調(diào)用內(nèi)部宏;因為:只有調(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ù)塊是允許
13、建立重復(fù)語句塊的宏的一種特殊形式,是一種特殊的宏。l 沒有被命名的宏,因而不能被調(diào)用!;可以有參數(shù);參數(shù)在匯編過程中可被實參替換;宏運算符、用偽指令LOCAL說明的符號 等可用于重復(fù)塊;由ENDM結(jié)束2. 偽指令REPTl 一般格式如下:1. REPT表達式2. 需要重復(fù)的語句組3. ENDM4. ;實例5. CHAR=A6. dataSEGMENT7. TABLELABELBYTE;在數(shù)據(jù)段借助rept定義數(shù)據(jù)時,前面的變量名必須以這種形式(變量名+LABEL+BYTE)定義,不可以只寫一個變量名,企圖8. REPT26;直接可以連接到下行的定義部分9. DBCHAR10. CHAR = C
14、HAR + 111. ENDM;這是一種經(jīng)典的使用方法,需要記牢,以后會有更多的更加靈活的方法等著我們?nèi)グl(fā)現(xiàn)12. dataENDSl 匯編程序?qū)选靶枰貜?fù)的語句組”連續(xù)地重復(fù)匯編由表達式值所決定的次數(shù);l 表達式必須可以求出數(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ù),<實參1, 實參2, 實參3,實參n>2. 需要重復(fù)的語句3. ENDM4. ;以下
15、為一實例5. dataSEGMENT6. quartLABELBYTE;類似與上面的用法,這是一個經(jīng)典的用法7. IRPX,<0, 1, 2, 3, 4, 5, 6, 7, 8, 9>8. DBX*X9. ENDM;定義了一個名為quart的數(shù)組,數(shù)組中依次存放著09的數(shù)的平方值10. dataENDSl 參數(shù)的個數(shù)決定了重復(fù)的次數(shù),匯編程序?qū)选靶枰獜?fù)制的語句”連續(xù)地重復(fù)匯編規(guī)定的次數(shù),并在每次匯編過程中,用相應(yīng)的實參替換“需要重復(fù)的語句”中的形參。l 實參放置在一對尖括號中,與形參之間用逗號間隔,各個實參之間也用逗號進行間隔。4. 偽指令I(lǐng)RPCl 一般格式如下:1. IRPC
16、形式參數(shù),字符串2. 需重復(fù)的語句組3. ENDM4. ;以下為一個示例:5. dataSEGMENT6. TABLELABELBYTE7. IRPCX, 01234567898. DW(X+1)*29. ENDM10. dataENDSl IRPC與IRP相似,除了前者的實參數(shù)列表是一個字符串以外完全一樣l 字符串的長度規(guī)定了重復(fù)的次數(shù),匯編程序?qū)选靶枰貜?fù)的語句組”連續(xù)地重復(fù)匯編指定的次數(shù),并在每次匯編時依次使用“字符串”中的一個字符作為實參代替“需要重復(fù)的語句組”中的形式參數(shù),l 如果字符串中含有空格,逗號等分隔符,那么字符串需用一對尖括號括起來!且一定不能使用雙引號或者單引號,否則雙
17、引號或者單引號也會被當(dāng)做字符串的一部分,也就是當(dāng)做實參替換形參。l 如果沒有尖括號。1)空格之后的部分將會被忽略2)逗號之后的部分,連同逗號都會作為實參的一部分l 所以只要字符串之間沒有空格字符,所有的部分都會被當(dāng)做實參進行傳遞,如果這個實參有意義的話(一般逗號沒有意義)l 如果想要將空格作為參數(shù)的話,那就按照最初的做法,將所有參數(shù)用尖括號括起來。問題描述:在一次測試過程中,我將帶參數(shù)的重復(fù)匯編偽指令irp和irpc寫入到一個宏中,以期,通過它們在該宏中實現(xiàn)將四個寄存器壓入棧中的功能,如下所示:1. PUSHAMACRO2. irpR,<a,b,c,d>3. pushR&x
18、4. ENDM5. ENDM結(jié)果卻不如人意,編譯器提示了錯誤,而錯誤如下:1. Symbol not defined: RX *4這說明:pusha得到了展開,并且重復(fù)匯編指令也得到了展開,后者的實參并沒有對形參進行替換!l 如果我們在代碼中直接使用irp指令,則實參會正常替換形參。l 對于具有參數(shù)的irpc也具有這樣的情形。l 但是有一種例外情況,如下所示:1. DFSQUAREMACRO2. tableLABELBYTE3. irpX,<0,1,2,3,4,5,6,7,8,9>4. DBX*X5. ENDM6. ENDMl 以上發(fā)生在irp語句中包含的是定義語句時!l 此問題待
19、定,具體原因并不知道是因為什么。以后盡量避免這樣的嵌套行為。8.4 條件匯編1. 前言:a. 條件匯編提供根據(jù)某種條件決定是否匯編某段源代碼的功能。b. 在源程序中使用條件匯編語句的主要目的是:1) 通過在匯編前或匯編時改變某種條件,從而方便地產(chǎn)生功能不同的程序;2) 增強宏定義能力,使得宏的適用范圍更廣;3) 改善匯編效率c. 條件匯編語句在形式上與高級語言中的條件語句相似,但本質(zhì)上卻是完全不同的:1) 條件匯編語句是說明性語句,由偽指令構(gòu)成,功能上由匯編程序?qū)崿F(xiàn);2) 一般情況下,高級語言的條件語句是執(zhí)行語句,由目標(biāo)程序?qū)崿F(xiàn)其功能。2. 條件匯編偽指令a. 大概:1) 一般格式如下:1.
20、IFxxxx條件表達式2. 語句組13. ELSE4. 語句組2;條件匯編語句的可選部分5. ENDIF2) 說明:l IFxxxx 是條件偽指令助記符的一般形式,xxxx表示構(gòu)成條件偽指令助記符的其他字符;l 完整的條件偽指令助記符有:IFIFEIFDEFIFNDEFIF1IF2IFBIFNBIFIDNIFDIFl 每一個條件偽指令助記符都要對應(yīng)一個條件結(jié)束偽指令助記符ENDIF,這個是統(tǒng)一的,必須的l 不同的條件指令助記符形式上可能有所不同,這里僅列出一般格式l 語句組可以包含有任意正確的語句,可以包含其他條件偽指令語句l ELSE語句組2部分是可選的l 條件匯編偽指令語句的一般意義是:如
21、果條件偽指令要求的條件滿足,那么匯編“語句組1”,否則,在ELSE+語句組2存在的情況下,匯編語句組2,如果沒有語句組2,且條件表達式不滿足,那么不進行匯編操作;l 匯編語言允許條件語句偽指令嵌套,且允許的嵌套次數(shù)足以滿足一般應(yīng)用需要;l 一個嵌套的ELSE偽指令,總是與最近的但又沒有ELSE相匹配的IFxxxx偽指令相匹配。b. 偽指令I(lǐng)F和IFE1) 一般格式:1. IF(IFE)表達式2. 語句組13. ELSE4. 語句組25. ENDIF6. ;示例如下:7. ;示例1:8. IFMFLAG;利用一個變量作為判定對象9. movah, 0;該條件匯編偽指令選擇的是是否匯編 匯編指令語
22、句10. int16H11. ELSE12. movah, 113. int21H14. ENDIF15. ;示例2:16. IFPORT EQ0;利用一個關(guān)系表達式作為判定對象17. PORTADDR=3F8H;該條件匯編偽指令選擇的是是否匯編 匯編偽指令語句,可以看出來,相當(dāng)靈活18. IVECTN=0BH19. IMASKV=11110111B20. ENDIF21. ;示例3(更加復(fù)雜的示例,與宏與重復(fù)塊相結(jié)合):22. SHIFTLMACROOP, N;定義了一個SHIFTL宏23. COUNT=024. REPTN;宏中包含了一個重復(fù)塊定義語句,將操作數(shù)OP每次向右算術(shù)左移一位,直
23、到,移位的次數(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)F:如果表達式的值不等于0,則條件滿足,條件為真。非零即為真。這類似于C語言中對于條件表達式的值的判定方法。l 偽指令I(lǐng)FE:如果表達式的值等于0,則條件滿足,條件為真。相當(dāng)于IF NOT 條件表達式,與IF偽指令恰恰相反。l 上述表達式不能包含向前引用(還不能明確這個意思
24、。),其結(jié)果應(yīng)為一常數(shù)值。一般為關(guān)系表達式或常數(shù)表達式c. 偽指令I(lǐng)FDEF和IFNDEF1) 一般格式:1. IFDEF(IFNDEF)符號2. 語句組13. ELSE4. 語句組25. ENDIF6. ;示例1:7. IFDEFMLARGE8. AXINCPROCFAR;如果MLARGE已被定義,那么將AXINC過程定義為遠過程。9. ELSE10. AXINCPROCNEAR;否則,將AXINC定義為近過程11. ENDIF12. incax13. ret14. AXINCENDP2) 說明:l 偽指令I(lǐng)FDEF:如果符號已定義 或已被說明為外部符號(EXTRN偽指令進行說明),則條件滿
25、足,即條件為真。l 偽指令I(lǐng)FNDEF:如果符號未定義或未被說明成外部符號,則條件滿足,即條件為真。又是一對兒相反的偽指令。l 符號可以在源程序中定義,也可以在匯編命令行中定義,后者參閱匯編器使用手冊。d. 偽指令I(lǐng)F1和IF21) 一般格式:1. IF1(IF2)2. 語句組13. ELSE4. 語句組25. ENDIF6. ;決定匯編程序在第幾趟掃描時,匯編語句組。2) 說明:l 偽指令I(lǐng)F1:若是第一趟則為真l 偽指令I(lǐng)F2:若是第二趟則為真3. 條件匯編與宏結(jié)合a. 宏中使用條件匯編1) 條件匯編與宏結(jié)合,能大大擴大宏的使用范圍。2) 以下為一示例:1. ADDNUMMACROREG,
26、 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ù)實際參數(shù)的不同擴展成不同的指令!l 宏,只有當(dāng)被調(diào)用時,才會在被調(diào)用的內(nèi)存空間,進行宏的展開;既然已經(jīng)被調(diào)用,那么肯定已經(jīng)有參數(shù)向其傳遞了,所以,條件匯編指令中才能根據(jù)參數(shù)進行一些判斷,而決定展開后的命令!l 根據(jù)以上的道理來看,匯編語言提供了有關(guān)測試宏參數(shù)的條件匯編偽指
27、令,這更加便利了我們將宏與條件匯編語句相結(jié)合!b. 用于測試宏參數(shù)的條件匯編偽指令1) 偽指令I(lǐng)FB和IFNBl 以下為一般格式:1. IFB<參數(shù)>2. IFNB<參數(shù)>3. ;以下為一示例:4. PRINTMACROMSG;該宏的作用:當(dāng)給定實參(偏移地址)時,顯示指定的字符串,當(dāng)未給定實參時,使用默認(rèn)實參,打印默認(rèn)信息。5. IFB<MSG>6. movsi, DEFAULTMSG7. ELSE8. movsi, MSG9. ENDIF10. CALLSHOWIT11. ENDM12. ;事實上,以上實現(xiàn),并沒有那么簡單!以下是正確的實現(xiàn)方法!詳情見注
28、釋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: push ds18. push dx19. push ax;要注意保護寄存器!20.21. IFB <MSG>IFB后面的形參必須用尖括號括起來,這里的尖括號并不是
29、字符串原樣輸出運算符!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 這兩條偽指令一般都用于宏定義體內(nèi)部。l 偽指令I(lǐng)FB:如果在宏調(diào)用時,沒有實參來代替形參,也就是沒有實參,那么條件滿足。l 偽指令I(lǐng)FNB:如果在宏調(diào)用時,有實參來代替形參,也
30、就是有實參,那么條件滿足l 又是一對條件相反的指令。2) 偽指令I(lǐng)FIDN和IFDIFl 一般格式:1. IFIDN<參數(shù)1>,<參數(shù)2>2. IFIDNI<參數(shù)1>,<參數(shù)2>3. 4. IFDIF<參數(shù)1>,<參數(shù)2>5. IFDIFI<參數(shù)1>,<參數(shù)2>6. 7. ;以下為示例:8. ;示例1:9. RDWRMACROBUFF,RWMODE10. leadx, BUFF11. IFIDNI<RWMODE>,<READ>如果宏參數(shù),讀寫模式字符與READ一致,則匯編調(diào)用
31、讀功能子程序部分12. callREADIT13. ENDIF14. IFIDNI<RWMODE>,<WRITE>如果宏參數(shù),讀寫模式與WRITE一致,則匯編調(diào)用寫功能子程序部分。15. callWRITEIT16. ENDIF17. ENDM18. ;示例2:19. GETCHMACROCHAR20. movah, 121. int21H22. IFNB<CHAR>23. IFDIFI<CHAR>,<AL>24. movCHAR, AL25. ENDIF26. ENDIF27. ENDMl 這兩條指令一般都用在宏定義體內(nèi)部。l 偽指
32、令I(lǐng)FIDN(IFIDNI):如果字符串參數(shù)1與字符串參數(shù)2相等,則條件滿足;后面添加的I是忽略大小寫的意思!l 偽指令I(lǐng)FDIF(IFDIFI):如果字符串參數(shù)1與字符串參數(shù)2不相等,則條件滿足。l 參數(shù)1和參數(shù)2:有可能是宏的形參,如果是形參,則比較之前,需先用實參進行替換后,再比較。如果不是宏的形參,則直接比較即可。l 參數(shù)一定是字符串,不需要添加引號,字符串會逐個比較大??;每一條指令都有兩種格式,普通格式時,大小寫有區(qū)別;+I格式時,大小寫沒有區(qū)別。并且該字符串一定是手動輸入到源代碼中的!Intel匯編語言程序設(shè)計1. 概述a. 宏過程(macro procedure):命名語句塊;可
33、被調(diào)用多次;調(diào)用時,宏的副本被直接插入到程序中b. 宏過程可以必須聲明在調(diào)用宏過程之前,或者聲明在單獨的文本文件中,通過INCLUDE包含之。c. 匯編器在預(yù)處理階段處理宏的展開。d. 在80X86匯編語言程序設(shè)計教程一書中同樣有關(guān)于宏的內(nèi)容2. 宏的定義a. 方法:使用MACRO和ENDM偽指令在源程序的任意位置定義宏。b. 定義格式:1. macronameMACROparameter-1, parameter-22. statement-list3. ENDM4. ;建議對宏的名字(macroname)和ENDM之間的語句進行縮進5. ;statement-list即語句列表在宏被調(diào)用的
34、時候才會被匯編;6. ;宏的定義中可以有任意多的參數(shù),參數(shù)之間用逗號間隔c. 宏的參數(shù)1) 宏的參數(shù)實際上是有名字的容器,以存放調(diào)用者傳遞給宏的文本參數(shù)。2) 說明:l 宏參數(shù)可以是整數(shù)、變量名、寄存器名等等l 預(yù)處理器把各種參數(shù)統(tǒng)一視為文本進行處理l 宏的參數(shù)沒有類型,因此預(yù)處理器并不檢查實參的類型是否與形參的類型匹配,如果不匹配,則會在匯編時由匯編器檢查。3) 示例:1. mPutcharMACROchar2. pusheax3. moval, char4. callWriteChar5. popeax6. ENDM3. 宏的調(diào)用a. 宏的調(diào)用:將宏的名字插入到需要調(diào)用宏的源碼中,并連接必
35、要的參數(shù),即完成宏的調(diào)用。b. 格式:1. 宏名稱參數(shù)1,參數(shù)22. ;其中宏名稱必須是宏被調(diào)用前已經(jīng)在源代碼中定義號的宏的名字3. ;宏調(diào)用時每個實際參數(shù)都是一個文本值。4. ;實際參數(shù)的順序必須按照宏定義時的參數(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修飾符可
36、以指定宏的某個或某幾個參數(shù)是必須的,如果在宏展開中沒有獲得與之對應(yīng)的實參,則顯示一條錯誤信息。2) 示例:1. mPutCharMACROchar:REQ;注意這樣的修飾方法2. pusheax3. moval, char4. callWriteChar5. popeax6. ENDMb. 宏的注釋1) 宏定義中如果有普通注釋,則每次展開時都會將該注釋一起展開。為了避免這樣,利用雙分號寫宏注釋,則不會展開。2) 示例:1. mPutCharMACROchar:REQ2. pusheax;注意保護寄存器3. moval, char4. callWriteChar5. popeax6. ENDMc
37、. ECHO偽指令1) 匯編器匯編源碼的過程中,ECHO偽指令可以在控制臺顯示一條消息。2) 示例:1. mPutcharMACRO char:REQ2. ECHO“Expanding the mPutchar 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)
38、使用LOCAL偽指令可以完美解決上述問題:3) 使用方法:1. makeStringMACROtext2. LOCALstring3. .data4. stringBYTEtext,05. ENDM6. ;另一個例子: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. L
39、OCALstring3. .data4. stringBYTEtext,05. .code6. pushedx7. movedx, OFFSET string8. callWriteString9. 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. 使用本書附帶的宏庫
40、a. 大概1) .inc文件是文本文件,即包含文件,我們可以將很多宏定義在一個獨立的文本文件中,然后在需要調(diào)用它們的源代碼文件中包含該文件即可!2) 本節(jié)所羅列的所有宏:宏的名字參數(shù)描述mDumpvarName,useLabel顯示一個變量,使用變量名及變量的默認(rèn)屬性mDumpMemaddress,itemCount,componentSize顯示一塊內(nèi)存的內(nèi)容mGotoxyx,y設(shè)置控制臺緩沖區(qū)中光標(biāo)的位置mShowvarName從鍵盤讀取一個字符串mReadStringitsName,fomat以多種格式顯示一個變量或寄存器mShowRegisterregName,regValue顯示一個
41、32位的寄存器的名字及其內(nèi)容,以十六進制格式mWritetext在控制臺窗口中顯示一個字符串mWriteSpacecount在控制臺窗口中顯示一個或多個空格mWriteStringbuffer在控制臺窗口中顯示一個字符變量的內(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:REQ
42、2. pushebx3. pushecx4. pushesi5. movesi, address6. movecx, itemCount7. movebx, componentSize8. callDumpMem9. popesi10. popecx11. popebx12. ENDMc. mDump1) 功能描述:以十六進制格式顯示變量的地址和內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):變量的名字l 第二個參數(shù):(可選的)傳遞一個字符Y或者是N表示是否顯示變量的名字3) 實現(xiàn)1. mDumpMACROvarName:REQ, useLabel2. callCrlf3. IFNB<useLabe
43、l4. mWrite “Variable name: &varName”5. ENDIF6. mDumpMemOFFSET varName,LENGTHOF varName,TYPE varName7. 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)
44、 功能描述:從鍵盤上讀取一個字符串并把該字符串存儲在一個緩沖區(qū)中2) 參數(shù)解釋:l 第一個參數(shù):緩沖區(qū)的名字,或者是存儲緩沖區(qū)偏移地址的寄存器3) 實現(xiàn)1. mReadStringMACROvarName:REQ2. 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 =
45、十六進制 D = 無符號十進制整數(shù) I = 有符號十進制整數(shù) B = 二進制 N = 添加一個換行符 可以組合多種輸出格式,也可以指定多個換行符默認(rèn)格式:HIN3) 實現(xiàn)該宏的實現(xiàn)過長,該宏定義在Macros.inc包含文件中g(shù). mShowRegister1) 功能描述:以十六進制格式顯示一個32位寄存器的內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):對于該寄存器要顯示的名字,被用作字符串。l 第二個參數(shù):該寄存器的名字,被用來取值3) 實現(xiàn)1. mShowRegisterMACROregName,regValue2. LOCAL tempStr3. .data4. tempStrBYTE“&
46、regName=”,05. .code6. pushedx7. movedx, OFFSET tempStr8. callWriteString9. popedx10. 11. moveax, regValue12. callWriteHex13. popeax14. ENDMh. mWriteString1) 功能描述:在控制臺窗口顯示一個字符串的內(nèi)容2) 參數(shù)解釋:l 第一個參數(shù):字符串名3) 實現(xiàn)1. mWriteStringMACRO buffer:REQ2. pushedx3. movedx, OFFSET buffer4. callWriteString5. popedx6. EN
47、DMi. mWriteSpace1) 功能描述:在控制臺窗口顯示一個或多個空格2) 參數(shù)解釋:l 第一個參數(shù):一個數(shù)字,指定空格的數(shù)量,默認(rèn)個數(shù)是13) 實現(xiàn)1. mWriteSpaceMACROcount:=<1>默認(rèn)實參的寫法2. LOCAL spaces3. .data4. spacesBYTEcount DUP( ),05. .code6. pushedx7. movecx, OFFSET spaces8. callWriteString9. popedx10. ENDM6. 例子程序:封裝10.3 條件匯編偽指令 與 宏0.前言a. 條件匯編偽指令和宏聯(lián)合使用可以使得宏更
48、加靈活。b. 本節(jié)看似在講述關(guān)于條件匯編偽指令的相關(guān)內(nèi)容,但是無不聯(lián)系了宏的應(yīng)用!c. 一般格式1. IFcondition2. statement3. ELSE4. statement5. ENDIFd. 本章介紹的是:常量條件偽指令;6.7節(jié)介紹的是:運行時偽指令e. 條件匯編偽指令概況偽指令說明IF 表達式如果表達式為真(非0)則允許匯編??梢允褂玫南嚓P(guān)操作符有LT,GT,NE,LE,GEIFB<參數(shù)>如果參數(shù)為空則允許匯編,參數(shù)名必須用尖括號(<>)括起來IFNB<參數(shù)>如果參數(shù)不為空則允許匯編,參數(shù)名必須用尖括號括起來IFIDN<參數(shù)1>
49、;,<參數(shù)2>如果兩個參數(shù)相同則允許匯編,參數(shù)比較是大小寫敏感的IFIDNI<參數(shù)1>,<參數(shù)2>如果兩個參數(shù)相同則允許匯編,參數(shù)比較是不區(qū)分大小寫的。IFDIF<參數(shù)1>,<參數(shù)2>如果兩個參數(shù)不同則允許匯編,參數(shù)比較是大小寫敏感的。IFDIFI<參數(shù)1>,<參數(shù)2>如果兩個參數(shù)不同則允許匯編,參數(shù)比較是不區(qū)分大小寫的。IFDEF 名字如果名字已經(jīng)定義則允許匯編IFNDEF 名字如果名字未定義則允許匯編ENDIF結(jié)束一個條件匯編偽指令開始的語句塊ELSE如果前面的條件匯編偽指令的條件均為假,則匯編該偽指令至E
50、NDIF偽指令之間的語句ELSEIF 表達式如果前面的條件匯編偽指令的條件均為假,則匯編該偽指令至下一條匯編偽指令之間的語句EXITM立即退出宏,組織其后任何語句的展開1. 檢查缺少的參數(shù)(介紹使用了IFB條件匯編偽指令的用途?。゛. 宏可以通過條件匯編偽指令檢查其任何一個參數(shù)是否為空。b. 背景:當(dāng)宏的用戶使用宏,某個參數(shù)為空時,有可能生成錯誤的指令,在匯編時產(chǎn)生錯誤。為了減少宏的用戶產(chǎn)生此類錯誤,需要檢查缺失參數(shù),并做防范措施。c. 示例:1. mWriteStrMACRO string2. IFB<string>當(dāng)用戶未提供參數(shù)時,在預(yù)處理階段就顯示出錯信息,并不展開宏3. ECHO -4. ECHO * Error: parameter missing in mWriteStr5. ECHO * (no code generated)6. ECHO -7.
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 重慶能源職業(yè)學(xué)院《機電系統(tǒng)建模與仿真》2023-2024學(xué)年第二學(xué)期期末試卷
- 甘孜職業(yè)學(xué)院《大跨度空間結(jié)構(gòu)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025屆寧夏吳忠市高三上學(xué)期適應(yīng)性考試(一模)歷史試卷
- 2024-2025學(xué)年浙江省六校聯(lián)盟高一上學(xué)期期中聯(lián)考歷史試卷
- 做賬實操-代理記賬行業(yè)的賬務(wù)處理分錄
- 長春大學(xué)旅游學(xué)院《幼兒舞蹈創(chuàng)編二》2023-2024學(xué)年第二學(xué)期期末試卷
- 2024-2025學(xué)年湖北省新高考聯(lián)考協(xié)作體高一上學(xué)期期中考試歷史試卷
- 濟南工程職業(yè)技術(shù)學(xué)院《信息安全基礎(chǔ)》2023-2024學(xué)年第二學(xué)期期末試卷
- 聊城大學(xué)東昌學(xué)院《病理學(xué)與病理生理學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 亳州職業(yè)技術(shù)學(xué)院《數(shù)據(jù)分析與可視化實驗》2023-2024學(xué)年第二學(xué)期期末試卷
- GB 1886.375-2024食品安全國家標(biāo)準(zhǔn)食品添加劑氫氧化鈣
- 物業(yè)員工晉升述職報告
- 建設(shè)工程施工專業(yè)分包合同(GF-2003-0213)
- 耳鼻喉科各項規(guī)章制度
- 玻璃分化板制作工藝
- 虹吸現(xiàn)象講解
- 設(shè)備采購計劃書
- 長興縣合溪水庫清淤工程(一期)環(huán)境影響報告
- 粒籽源永久性植入治療放射防護要求
- 新聞選題申報單
- 醫(yī)學(xué)倫理審查申請表
評論
0/150
提交評論