第 4 章 巨集處理器
description
Transcript of 第 4 章 巨集處理器
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
第第 44 章 巨集處理器章 巨集處理器
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
4.1 節將會介紹巨集處理器的基本概念 4.2 節討論巨集處理器的延伸功能 4.3 節將會介紹一些巨集處理器的設計選項 4.4 節將簡短地介紹三個巨集處理器的實際範
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
4.1.1 節:討論巨集處理器的定義、呼叫( invocation )、展開( expansion )和參數替換
4.1.2 節:介紹簡單巨集處理器的單階單演算法以及巨集處理上所需的資料結構
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
圖 4.1 的程式是巨集處理器的輸入 圖 4.2 所示程 二個巨集指令: RDBUFF 和 WRBUFF MACRO 指引( directive )之後的是構成巨
集之主體( body )的敘述(第 15 行到 90行)。這些敘述會在巨集展開時產生出來
MEND 指引(第 95 行)可以標示巨集定義的結尾。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
每ㄧ次呼叫巨集時,就會產生(和組譯)巨集所展開的敘述。但是,不論呼叫副程式多少次,副程式中的敘述都只會顯示一次。
巨集的主體中並沒有標籤
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
二階段巨集處理器 第一階段處理所有的巨集定義 第二次階段處理所有的巨集呼叫敘述的展開
此種二階段巨集處理器並不允許巨集指令的主體中,具有其他巨集的定義
單階段巨集處理器會在巨集定義與巨集展開之間切換,以順利處理一些巨集
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
巨集定義是儲存在「定義資料表」( DEFTAB ) 巨集定義的註解行( comment lines )並不會
進入到 DEFTAB 巨集名稱也會進入到「名稱資料表」
( NAMTAB )中,以做為 DEFTAB 的索引。 「引數資料表」( ARGTAB ):主要是用於
巨集呼叫的展開時間
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
4.2.1 節將討論巨集指令參數和字串的連接方法。
4.2.2 節將討論在巨集展開時,產生唯一標籤的方法
4.2.3 節是介紹條件巨集展開的重要議題,並且利用一些範例來說明其概念。
4.2.4 節所要介紹的是巨集指令的定義,以及關鍵字參數( keyword parameter )的使用。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
大部分的巨集處理器都會允許參數與其他字串進行連接。
假設此巨集指令的參數名稱是 &ID , 巨集定義的主體中應該包含一個敘述: LDA X&ID1
LDA X&ID→ 1 &ID 參數的結尾可以清楚地指定出來。
圖 4.7 展示在巨集展開中,裡產生唯一標籤的一個技術。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
大部分的巨集處理器可以根據在巨集呼叫中的引數,來修改巨集展開所產生的一系列敘述
IF 敘述是用來判斷一個布林的運算式,如果此運算式的值為「 TRUE 」時,則 IF 後跟的敘述將持續進行巨集展開,直到遭遇到 ELSE敘述為止;
否則,將會略過這些敘述,而展開 ELSE 之後的敘述
ENDIF 敘述將會終止由 IF 敘述啟始的條件式
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
只要 WHILE 敘述的條件成立時,就會ㄧ直重複展開 WHILE 敘述與 ENDW 敘述之間的敘述。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
迄今,所有的巨集指令定義都是使用位置參數( positional parameters )。
「關鍵參數」( Keyword parameters )是另一種不同形式的參數規範,每個引數值都會標示一個關鍵字,來表示對應的引數,因此引數可以用任何的順序來呈現。
GENER TYPE=DIRECT, CHANNEL=3
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
4.3.1 遞迴的巨集展開。 4.3.2 節將要討論不受任何特殊程式所束縛的
通用巨集處理器 4.3.3 節將探討此項議題的其它面向:巨集處
理器與一個特殊組譯器或編譯器的整合。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
一個巨集呼叫另一個巨集 當程序以遞迴方式進行呼叫時,編譯器必須確
定先前所宣告的變數值已經儲存起來。此外,它同時也要處理程序在回歸時的相關細節
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
Parameter Value
1 BUFFER
2 LENGTH
3 F1
4 (unused)
. .
Parameter Value
1 F1
2 (unused)
. .
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
巨集處理器是最常用於協助組合語言程式;巨集處理器也可以運用在高階語言上
程式語言之間的其它差異,是與程式語言之項目、運算式或敘述的分群機制有關。一般用途的巨集處理器在掃描原始程式時,需要考量這些的分群( groupings )。
另一個較為通常的問題是程式語言的符記( tokens )
巨集定義和巨集呼叫敘述的使用語法
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
巨集處理器可以稱之為「前置處理器」( preprocessors )
另一種方法:整合程式語言的轉譯器以及巨集處理器的功能。
逐行巨集處理器 以避免針對原始程式產生另一階段的處理 結合巨集處理器和語言轉譯器所需的資料結構
整合的巨集處理器 使用語言轉譯器從原始程式中所擷取出來的任何有用資訊
整合性和逐行式的巨集處理器也有其缺點。因為它們需要特別的設計和撰寫,並且必須與特定的組譯器或編譯器協同運作
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
4.4.1 MASM巨集處理器 4.4.2 ANSI C巨集語言 4.4.3 ELENA 巨集處理器
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
MASM 的巨集處理器是與組合語言的第一階段整合在一起
支援先前所討論之巨集處理器的所有功能 巨集可能在程式中重新定義 MASM 巨集處理器與 SIC 之間的差異在於條
件巨集展開敘述
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
( b)
( c)
( d)
( a)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
( a)
( b)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
巨集的定義和呼叫是由前置處理器來執行 此前置處理器通常並不會與編譯器整合在一起 二個簡單的 ANSI C 巨集定義的範例:
#define NULL 0 #define EOF (-1)
例如:定義巨集 #define EQ == 一個程式將可以寫成
while (I EQ 0)... 巨集處理器會將此轉換為
while (I == 0)...
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
#define ABSDIFF(X,Y) ((X) > (Y) ? (X) – (Y) : (Y) – (X)) ABSDIFF(I+1,J-5) 將會被巨集處理器轉換成 ((I+1) > (J-5) ? (I+1) – (J-5) : (J-5) – (I+1))
#define DISPLAY(EXPR) printf("EXPR = %d\n" EXPR) 此巨集呼叫 #DESPLAY(I*J+1) 將會展開成 . printf("EXPR = %d\n", I*J+1)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
#define DISPLAY(EXPR) printf(#EXPR “= %d\n”, EXPR) DISPLAY(I*J+1) 將會展開成為 printf("I*J+1" "= %d\n", EXPR)
DISPLAY(ABSDIFF(3,8)) 會展開成下列的程式
Printf(“ABSDIFF(3,8)” “= %d\n”, ABSDIFF(3,8)) 在重新掃描後,將會變成下列的程式
Printf(“ABSDIFF(3,8)” “= %D\N”,((3) > (8) ? (3) – (8) : *8) – (3)))
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
#define DEBUG 1.#if DEBUG == 1printf(...) /* debugging output */#endif 在此範例中, printf 敘述將會出現在前置處理程式的輸出中define DEBUG 0 則程式中將不會出現此 printf 。下列敘述也可以產生相同的結果#ifdef DEBUGprintf(...) /* debugging output */#endif 在此範例中,假如原始程式是用 #define 敘述來定義 DEBUG 時,
則程式中將會出現 printf 敘述。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
ELENA 的巨集定義中包括標頭( header )和主體( body )
一系列的關鍵字( keywords )和參數標誌(以特別符號 % 來辨識)。
例如:一個具有標頭的巨集如下列所示: %1 = %2 + %3 可以用下列方式來呼叫: ALPHA = BETA + GAMMA
巨集標頭與巨集呼叫的比對程序會比較複雜。
© 2007 台灣培生教育出版 (Pearson Education Taiwan)
© 2007 台灣培生教育出版 (Pearson Education Taiwan)