SlideShare une entreprise Scribd logo
1  sur  7
1
第6章 巨集處理器
巨集處理器 (Macro Processor) 乃是一種方便程式撰寫者使用,避免重複撰寫程
式的工具,在程式被編譯前,巨集處理器會先將程式當中的巨集展開,然後再交
給編譯器或組譯器進一步處理。
在組合語言當中,非常仰賴巨集的使用,因為組合語言沒有強大的編譯功能可以
提供高層次的語法,巨集就成了組合語言當中唯一可以採用的較高層次工具。
在本章中,我們將介紹組合語言中巨集的用途與作法,並且介紹巨集處理的演算
法。最後,在實務案例中,我們將焦點轉向高階語言,介紹 C 語言當中的巨集,
並利用 gcc 觀察巨集展開的過程。
6.1 組合語言的巨集
為了說明巨集在組合語言當中的功能,先讓我們來看一個具有巨集的組合語言範
例,我們以 max(x,y) 這樣一個函數為例,說明巨集的用法。範例 6.1 (a) 顯示了
一個具有巨集的 CPU0 組合語言,其中的 MAX 是巨集,該巨集被定義後被呼
叫了兩次。範例 6.1 (b) 是該程式被巨集處理器展開後的結果。
範例 6.1 具有巨集的組合語言 - 展開前與展開後的狀況
(a). 巨集展開前 (b) 巨集展開後
1
2
3
4
5
6
7
8
9
10
11
12
13
MAX MACRO &X, &Y, &Z
LD R1, &X
LD R2, &Y
CMP R1, R2
JLE $ELSE
ST R1, &Z
JMP $END
$ELSE:
ST R2, &Z
$END:
MEND
MAX(A, B, C)
// MAX(A,B,C)
LD R1, A
LD R2, B
CMP R1, R2
JLE $ELSE1
ST R1, C
JMP $END2
$ELSE1:
ST R2, C
$END2:
// MAX(C,D,E)
LD R1, C
LD R2, D
2
14
15
16
17
18
19
20
21
22
23
24
25
26
27
MAX(C, D, E)
RET
A: WORD 5
B: WORD 3
C: RESW 1
D: WORD 7
E: RESW 1
CMP R1, R2
JLE $ELSE3
ST R1, E
JMP $END4
$ELSE3:
ST R2, E
$END4:
RET
A: WORD 5
B: WORD 3
C: RESW 1
D: WORD 7
E: RESW 1
在範例 6.1 當中,左半部 (a) 是包含巨集的原始程式,而右半部 (b) 則是經過
巨集處理器展開後的狀況。讀者可以很清楚的看到,在第 1 行當中,我們用
MACRO 指令定義了一個名稱為 MAX 的巨集,而且在第 11 行中,我們用 MEND
指令結束巨集定義。接著,在 13 行當中我們以 MAX(A,B,C) 的方式呼叫了該巨
集一次,接著又在 14 行當中以 MAX(C,D,E) 第二次呼叫該巨集。於是,導致了
該巨集在程式當中被呼叫了兩次。
因此,在範例 6.1 右半部的 (b) 當中,MAX 巨集被展開了兩次,第一次是在的
第 1 行,第二次是在第 11 行。在第一次巨集展開的程式內 (1-10 行),參數 &X
被取代為 A, &Y 被取代為 B, 而 &Z 被取代為 C。同樣的,在第二次巨集展開的
程式碼內 (11-20 行),參數 &X, &Y, &Z 則分別被取代為 C, D, E。
除了參數的取代之外,為了避免同一巨集多次展開所造成的標記重複現象,因此,
巨集處理器會將標記加上編號,以避免重複的狀況。
在巨集當中,標記的前面必須被加上錢字號 $,舉例而言,像 $ELSE 與 $END 等
兩個標記就被加上了錢字號,這是用來提醒巨集處理器的一種方法。這兩個標記
展開後變成 $ELSE1, $END2, $ELSE3, $END4,如此就可以避免到標記重複的現
象。
3
6.2 巨集處理的演算法
單層的巨集處理器只能容許一層巨集呼叫,不能容許在巨集當中再度呼叫巨集。
這種巨集處理器的設計非常簡單,只要針對每一個巨集指令進行單層展開即可。
其演算法如圖 6.1 所示。
演算法 說明
Algorithm MacroProcessor
Input sourceFile, expandFile
inFile = open(sourcFile)
outFile = create(expandFile)
pass1()
pass2()
End Algorithm
Function pass1
while (not inFile.isEnd)
line = getLine()
if isMacroDefine(line)
macro = readMacro();
macroTable[macro.name] =macro
end while
End Function
Function pass2
inFile.goTop();
while (not inFile.isEnd)
line = getLine()
op = opCode(line)
search macroTable for op
if found
macroCall = parseMacroCall(line);
macro = macroTable[macroName];
body = replace macroCall.args in macro.body
replace label with label+id in body
write body to outFile
else
單層巨集處理器
輸入原始程式、輸出展開檔
開啟輸入檔 (原始程式)
建立輸出檔 (展開程式)
第一輪:定義巨集
第二輪:展開巨集
第一輪:定義巨集
當輸入檔未結束時
讀取一行
如果是巨集定義
讀取整個巨集
記錄到巨集表當中
第二輪:展開巨集
回到輸入檔開頭
當輸入檔未結束時
讀取一行
取得指令部分
看看是否為巨集呼叫
如果是巨集呼叫
剖析巨集呼叫
取得巨集內容
取代內容中的參數
為標記加上編號
將取代後的內容輸出
如果不是巨集呼叫
4
write source line to outFile
end while
End Function
將該指令直接輸出
圖 6.1 單層巨集處理器的演算法
圖 6.1 的演算法使用到兩種記錄結構,巨集記錄 macro 與呼叫結構 macroCall,
並且使用到一個符號表 macroTable。利用這些資料結構,巨集處理器先在第一
輪的讀取過程中建立巨集定義表,然後在第二輪的展開過程當中,展開每一行巨
集呼叫,輸出展開後的結果。
大部分的商業用巨集處理器會支援多層的巨集展開功能,這種多層的展開方式雖
然較為複雜,但是其基本動作與圖 6.1 相當類似,只是必須對每一行以遞迴的方
式進行展開呼叫,如果在巨集展開的過程當中又發現巨集呼叫的指令時,就必須
在呼叫巨集展開函數,以達成遞迴展開的功能。
6.3 實務案例
在本節中,我們將透過 gcc 的巨集展開功能,觀察 C 語言巨集的展開過程,以
便理解巨集展開的實務操作方式。
6.3.1 C 語言的巨集
在 C 語言的設計中,有兩種巨集宣告方式,您可以使用 #define 指令宣告巨集函
數,也可以利用 inline 指令,讓一般函數改為巨集函數,直接展開到程式當中。
通常,#define 指令是用來撰寫較短的巨集定義,而 inline 指令則用來撰寫較長
的巨集函數。
範例 6.2 中顯示了一個 C 語言的巨集定義與呼叫程式,其中定義了兩個巨集函
數 max(a,b) 與 min(a,b),分別傳回 a,b 兩者中的較大值與較小值。範例 6.2 左
半部的 (a) 部分是原始程式,而右半部的 (b) 部分是展開後的結果,請讀者對
照查看,以便理解 C 語言中的巨集運作方式。
我們可以使用 GNU 工具中的 gcc 編譯器,加上 -E 參數,以便將程式中的巨集
展開,但不執行編譯動作。範例 6.2 就是我們用指令 gcc -E macro.c -o macro_E.c
將 (a) 展開為 (b) 的結果,讀者可以親自操作看看。
5
範例 6.2 具有巨集的 C 語言 - 展開前與展開後的狀況
指令:gcc -E macro.c -o macro_E.c
(a) 展開前:macro.c (b) 展開後:macro_E.c
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
int main() {
int x = max(3,5);
int y = min(3,5);
printf("max(3,5)=%d,
min(3,5)=%dn",x,y);
}
int main() {
int x = (3>5?3:5);
int y = (3<5?3:5);
printf("max(3,5)=%d,
min(3,5)=%dn",x,y);
}
條件式展開
C 語言當中的巨集處理器,支援條件式展開的功能,這種功能對 C 語言相當重
要,尤其在專案管理上更是不可或缺,以下,我們將說明 C 語言中條件式展開的
巨集處理器之用途。首先,請讀者看範例 6.3 (a) 的程式,該程式用 #ifdef 條件
式巨集指令,定義了 bugs 變數與 error(msg) 巨集函數,並且在程式的最後利
用 error() 函數印出錯誤訊息,然後報告總共有幾個錯誤。
接著,請讀者利用 gcc 加上 -E 參數的方式,編譯該程式,指令如下所示。
gcc -E macroDebug.c -o MacroDebug_E.c
該指令會將程式的巨集展開,但因為編譯時沒有定義 _DEBUG_ 這個符號,因此,
展開後的程式不會印出除錯訊息,其原始碼如範例 6.3 (b) 所示。
範例 6.3 具有條件式巨集的 C 語言 - 展開前與展開後的狀況
(a) 檔案:MacroDebug.c (b) 檔案:MacroDebug_E.c
#ifdef _DEBUG_
int bugs = 0;
#define error(msg) {printf(msg);bugs++;}
#endif
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
int main() {
int x = (3>5?3:5);
int y = (3<5?3:5);
printf("max(3,5)=%dn",x);
printf("min(3,5)=%dn",y);
}
(c) 檔案:MacroDebug_DEBUG_E.c
6
int main() {
int x = max(3,5);
int y = min(3,5);
printf("max(3,5)=%dn",x);
printf("min(3,5)=%dn",y);
#ifdef _DEBUG_
if (x!=5)
error("max(3,5)");
if (y!=3)
error("min(3,5)");
printf("共有%d 個錯誤",bugs);
#endif
}
int bugs = 0;
int main() {
int x = (3>5?3:5);
int y = (3<5?3:5);
printf("max(3,5)=%dn",x);
printf("min(3,5)=%dn",y);
if (x!=5)
{printf("max(3,5)");bugs++;};
if (y!=3)
{printf("min(3,5)");bugs++;};
printf("共有 %d 個錯誤", bugs);
}
接著,再請讀者利用下列指令編譯該程式,其中的 –D_DEBUG_ 參數會動態的定
義一個 _DEBUG_ 巨集符號傳給 gcc 編譯器。
gcc -E -D_DEBUG_ macroDebug.c -o MacroDebug_DEBUG_E.c
此時,由於 _DEBUG_ 符號已被定義,因此,展開後的程式會定義 bugs 變數,
error(msg) 函數,並印出除錯訊息。其原始碼如範例 6.3 (c) 所示。
這種條件式的巨集定義的方式,在 C 語言當中相當常見,利用這種方式,我們
可以編譯出程式碼較大的除錯版本,以便於除錯時使用。然後,在程式要發行時,
編譯一個沒有 _DEBUG_ 符號的版本,如此,發行的軟體程式會較為精簡,也不
會動不動就跑出錯誤訊息來困擾使用者。這也是使用 C 語言開發軟體時必須具
備的巨集知識。
習題
6.1 請說明巨集處理器的輸入、輸出與功能為何?
6.2 請說明巨集處理器會如何處理巨集參數?
6.3 請說明巨集處理器在展開標記時會產生甚麼問題,應如何解決?
6.4 請使用 gcc 工具將範例 6.2 展開,觀察展開後的檔案,並說明展開前後的對
應關係。
7
6.5 請使用 gcc 工具將範例 6.3 展開,觀察展開後的檔案,並說明展開前後的對
應關係。

Contenu connexe

Tendances

系統程式 -- 第 3 章 組合語言
系統程式 -- 第 3 章 組合語言系統程式 -- 第 3 章 組合語言
系統程式 -- 第 3 章 組合語言鍾誠 陳鍾誠
 
系統程式 -- 第 11 章
系統程式 -- 第 11 章系統程式 -- 第 11 章
系統程式 -- 第 11 章鍾誠 陳鍾誠
 
系統程式 -- 第 7 章 高階語言
系統程式 -- 第 7 章 高階語言系統程式 -- 第 7 章 高階語言
系統程式 -- 第 7 章 高階語言鍾誠 陳鍾誠
 
系統程式 -- 第 9 章 虛擬機器
系統程式 -- 第 9 章 虛擬機器系統程式 -- 第 9 章 虛擬機器
系統程式 -- 第 9 章 虛擬機器鍾誠 陳鍾誠
 
系統程式 -- 第 8 章 編譯器
系統程式 -- 第 8 章 編譯器系統程式 -- 第 8 章 編譯器
系統程式 -- 第 8 章 編譯器鍾誠 陳鍾誠
 
系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統鍾誠 陳鍾誠
 
系統程式 -- 第 12 章 系統軟體實作
系統程式 -- 第 12 章 系統軟體實作系統程式 -- 第 12 章 系統軟體實作
系統程式 -- 第 12 章 系統軟體實作鍾誠 陳鍾誠
 
系統程式 -- 第 10 章
系統程式 -- 第 10 章系統程式 -- 第 10 章
系統程式 -- 第 10 章鍾誠 陳鍾誠
 
系統程式 -- 第 12 章
系統程式 -- 第 12 章系統程式 -- 第 12 章
系統程式 -- 第 12 章鍾誠 陳鍾誠
 
系統程式 -- 為何撰寫此書
系統程式 -- 為何撰寫此書系統程式 -- 為何撰寫此書
系統程式 -- 為何撰寫此書鍾誠 陳鍾誠
 

Tendances (20)

系統程式 -- 第 3 章 組合語言
系統程式 -- 第 3 章 組合語言系統程式 -- 第 3 章 組合語言
系統程式 -- 第 3 章 組合語言
 
系統程式 -- 第 3 章
系統程式 -- 第 3 章系統程式 -- 第 3 章
系統程式 -- 第 3 章
 
系統程式 -- 第 11 章
系統程式 -- 第 11 章系統程式 -- 第 11 章
系統程式 -- 第 11 章
 
系統程式 -- 第 7 章 高階語言
系統程式 -- 第 7 章 高階語言系統程式 -- 第 7 章 高階語言
系統程式 -- 第 7 章 高階語言
 
系統程式 -- 第 4 章
系統程式 -- 第 4 章系統程式 -- 第 4 章
系統程式 -- 第 4 章
 
系統程式 -- 第 2 章
系統程式 -- 第 2 章系統程式 -- 第 2 章
系統程式 -- 第 2 章
 
系統程式 -- 前言
系統程式 -- 前言系統程式 -- 前言
系統程式 -- 前言
 
系統程式 -- 第 9 章 虛擬機器
系統程式 -- 第 9 章 虛擬機器系統程式 -- 第 9 章 虛擬機器
系統程式 -- 第 9 章 虛擬機器
 
系統程式 -- 第 8 章 編譯器
系統程式 -- 第 8 章 編譯器系統程式 -- 第 8 章 編譯器
系統程式 -- 第 8 章 編譯器
 
系統程式 - 附錄
系統程式 - 附錄系統程式 - 附錄
系統程式 - 附錄
 
系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統系統程式 -- 第 11 章 嵌入式系統
系統程式 -- 第 11 章 嵌入式系統
 
系統程式 -- 第 1 章
系統程式 -- 第 1 章系統程式 -- 第 1 章
系統程式 -- 第 1 章
 
系統程式 -- 第 12 章 系統軟體實作
系統程式 -- 第 12 章 系統軟體實作系統程式 -- 第 12 章 系統軟體實作
系統程式 -- 第 12 章 系統軟體實作
 
系統程式 -- 第 7 章
系統程式 -- 第 7 章系統程式 -- 第 7 章
系統程式 -- 第 7 章
 
系統程式 -- 第 8 章
系統程式 -- 第 8 章系統程式 -- 第 8 章
系統程式 -- 第 8 章
 
系統程式 -- 第 10 章
系統程式 -- 第 10 章系統程式 -- 第 10 章
系統程式 -- 第 10 章
 
系統程式 -- 第 9 章
系統程式 -- 第 9 章系統程式 -- 第 9 章
系統程式 -- 第 9 章
 
系統程式 -- 第 12 章
系統程式 -- 第 12 章系統程式 -- 第 12 章
系統程式 -- 第 12 章
 
系統程式 -- 為何撰寫此書
系統程式 -- 為何撰寫此書系統程式 -- 為何撰寫此書
系統程式 -- 為何撰寫此書
 
LLVM introduction
LLVM introductionLLVM introduction
LLVM introduction
 

Similaire à 系統程式 -- 第 6 章 巨集處理器

Clipper@datacon.2019.tw
Clipper@datacon.2019.twClipper@datacon.2019.tw
Clipper@datacon.2019.twWei-Yu Chen
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)wangjiaz
 
Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)babyyellow li
 
Xcode开发员入门导引
Xcode开发员入门导引Xcode开发员入门导引
Xcode开发员入门导引Sophia Lindsey
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式Will Huang
 
C++工程实践
C++工程实践C++工程实践
C++工程实践Shuo Chen
 
Flex 3 Cookbook 中文版V1
Flex 3 Cookbook 中文版V1Flex 3 Cookbook 中文版V1
Flex 3 Cookbook 中文版V1yiditushe
 
Uc gui中文手册
Uc gui中文手册Uc gui中文手册
Uc gui中文手册호연 최
 
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)Will Huang
 
第1讲 开始编写程序
第1讲 开始编写程序第1讲 开始编写程序
第1讲 开始编写程序ruandao
 
3.架构设计篇2
3.架构设计篇23.架构设计篇2
3.架构设计篇2gavin shaw
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source ProjectsGeorge Ang
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojectsGeorge Ang
 
Java并发核心编程
Java并发核心编程Java并发核心编程
Java并发核心编程wavefly
 

Similaire à 系統程式 -- 第 6 章 巨集處理器 (20)

Clipper@datacon.2019.tw
Clipper@datacon.2019.twClipper@datacon.2019.tw
Clipper@datacon.2019.tw
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)
 
Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)Xcode开发员入门导引(简体中文版)
Xcode开发员入门导引(简体中文版)
 
Xcode开发员入门导引
Xcode开发员入门导引Xcode开发员入门导引
Xcode开发员入门导引
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
beidakejian
beidakejianbeidakejian
beidakejian
 
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
TypeScript 開發實戰:開發即時互動的 html5 websocket 聊天室應用程式
 
Go
GoGo
Go
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
 
Flex 3 Cookbook 中文版V1
Flex 3 Cookbook 中文版V1Flex 3 Cookbook 中文版V1
Flex 3 Cookbook 中文版V1
 
Uc gui中文手册
Uc gui中文手册Uc gui中文手册
Uc gui中文手册
 
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
 
第1讲 开始编写程序
第1讲 开始编写程序第1讲 开始编写程序
第1讲 开始编写程序
 
3.架构设计篇2
3.架构设计篇23.架构设计篇2
3.架构设计篇2
 
Recycle Open Source Projects
Recycle Open Source ProjectsRecycle Open Source Projects
Recycle Open Source Projects
 
2006 recycle opensourceprojects
2006 recycle opensourceprojects2006 recycle opensourceprojects
2006 recycle opensourceprojects
 
Exodus2 大局观
Exodus2 大局观Exodus2 大局观
Exodus2 大局观
 
Java并发核心编程
Java并发核心编程Java并发核心编程
Java并发核心编程
 
Ch01
Ch01Ch01
Ch01
 

Plus de 鍾誠 陳鍾誠

用十分鐘瞭解 新竹科學園區的發展史
用十分鐘瞭解  新竹科學園區的發展史用十分鐘瞭解  新竹科學園區的發展史
用十分鐘瞭解 新竹科學園區的發展史鍾誠 陳鍾誠
 
用十分鐘搞懂 λ-Calculus
用十分鐘搞懂 λ-Calculus用十分鐘搞懂 λ-Calculus
用十分鐘搞懂 λ-Calculus鍾誠 陳鍾誠
 
交⼤資訊⼯程學系備審資料 ⾱詠祥
交⼤資訊⼯程學系備審資料 ⾱詠祥交⼤資訊⼯程學系備審資料 ⾱詠祥
交⼤資訊⼯程學系備審資料 ⾱詠祥鍾誠 陳鍾誠
 
smallpt: Global Illumination in 99 lines of C++
smallpt:  Global Illumination in 99 lines of C++smallpt:  Global Illumination in 99 lines of C++
smallpt: Global Illumination in 99 lines of C++鍾誠 陳鍾誠
 
西洋史 (你或許不知道但卻影響現代教育的那些事)
西洋史  (你或許不知道但卻影響現代教育的那些事)西洋史  (你或許不知道但卻影響現代教育的那些事)
西洋史 (你或許不知道但卻影響現代教育的那些事)鍾誠 陳鍾誠
 
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列鍾誠 陳鍾誠
 
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列鍾誠 陳鍾誠
 
梯度下降法 (隱藏在深度學習背後的演算法) -- 十分鐘系列
梯度下降法  (隱藏在深度學習背後的演算法) -- 十分鐘系列梯度下降法  (隱藏在深度學習背後的演算法) -- 十分鐘系列
梯度下降法 (隱藏在深度學習背後的演算法) -- 十分鐘系列鍾誠 陳鍾誠
 
用十分鐘理解 《微分方程》
用十分鐘理解  《微分方程》用十分鐘理解  《微分方程》
用十分鐘理解 《微分方程》鍾誠 陳鍾誠
 
nand2tetris 舊版投影片 -- 第五章 計算機結構
nand2tetris 舊版投影片 -- 第五章 計算機結構nand2tetris 舊版投影片 -- 第五章 計算機結構
nand2tetris 舊版投影片 -- 第五章 計算機結構鍾誠 陳鍾誠
 
nand2tetris 舊版投影片 -- 第四章 機器語言
nand2tetris 舊版投影片 -- 第四章 機器語言nand2tetris 舊版投影片 -- 第四章 機器語言
nand2tetris 舊版投影片 -- 第四章 機器語言鍾誠 陳鍾誠
 
nand2tetris 舊版投影片 -- 第三章 循序邏輯
nand2tetris 舊版投影片 -- 第三章 循序邏輯nand2tetris 舊版投影片 -- 第三章 循序邏輯
nand2tetris 舊版投影片 -- 第三章 循序邏輯鍾誠 陳鍾誠
 
nand2tetris 舊版投影片 -- 第二章 布林算術
nand2tetris 舊版投影片 -- 第二章 布林算術nand2tetris 舊版投影片 -- 第二章 布林算術
nand2tetris 舊版投影片 -- 第二章 布林算術鍾誠 陳鍾誠
 
nand2tetris 舊版投影片 -- 第一章 布林邏輯
nand2tetris 舊版投影片 -- 第一章 布林邏輯nand2tetris 舊版投影片 -- 第一章 布林邏輯
nand2tetris 舊版投影片 -- 第一章 布林邏輯鍾誠 陳鍾誠
 

Plus de 鍾誠 陳鍾誠 (17)

用十分鐘瞭解 新竹科學園區的發展史
用十分鐘瞭解  新竹科學園區的發展史用十分鐘瞭解  新竹科學園區的發展史
用十分鐘瞭解 新竹科學園區的發展史
 
用十分鐘搞懂 λ-Calculus
用十分鐘搞懂 λ-Calculus用十分鐘搞懂 λ-Calculus
用十分鐘搞懂 λ-Calculus
 
交⼤資訊⼯程學系備審資料 ⾱詠祥
交⼤資訊⼯程學系備審資料 ⾱詠祥交⼤資訊⼯程學系備審資料 ⾱詠祥
交⼤資訊⼯程學系備審資料 ⾱詠祥
 
smallpt: Global Illumination in 99 lines of C++
smallpt:  Global Illumination in 99 lines of C++smallpt:  Global Illumination in 99 lines of C++
smallpt: Global Illumination in 99 lines of C++
 
西洋史 (你或許不知道但卻影響現代教育的那些事)
西洋史  (你或許不知道但卻影響現代教育的那些事)西洋史  (你或許不知道但卻影響現代教育的那些事)
西洋史 (你或許不知道但卻影響現代教育的那些事)
 
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
 
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列區塊鏈  (比特幣背後的關鍵技術)   -- 十分鐘系列
區塊鏈 (比特幣背後的關鍵技術) -- 十分鐘系列
 
梯度下降法 (隱藏在深度學習背後的演算法) -- 十分鐘系列
梯度下降法  (隱藏在深度學習背後的演算法) -- 十分鐘系列梯度下降法  (隱藏在深度學習背後的演算法) -- 十分鐘系列
梯度下降法 (隱藏在深度學習背後的演算法) -- 十分鐘系列
 
用十分鐘理解 《微分方程》
用十分鐘理解  《微分方程》用十分鐘理解  《微分方程》
用十分鐘理解 《微分方程》
 
nand2tetris 舊版投影片 -- 第五章 計算機結構
nand2tetris 舊版投影片 -- 第五章 計算機結構nand2tetris 舊版投影片 -- 第五章 計算機結構
nand2tetris 舊版投影片 -- 第五章 計算機結構
 
nand2tetris 舊版投影片 -- 第四章 機器語言
nand2tetris 舊版投影片 -- 第四章 機器語言nand2tetris 舊版投影片 -- 第四章 機器語言
nand2tetris 舊版投影片 -- 第四章 機器語言
 
nand2tetris 舊版投影片 -- 第三章 循序邏輯
nand2tetris 舊版投影片 -- 第三章 循序邏輯nand2tetris 舊版投影片 -- 第三章 循序邏輯
nand2tetris 舊版投影片 -- 第三章 循序邏輯
 
nand2tetris 舊版投影片 -- 第二章 布林算術
nand2tetris 舊版投影片 -- 第二章 布林算術nand2tetris 舊版投影片 -- 第二章 布林算術
nand2tetris 舊版投影片 -- 第二章 布林算術
 
nand2tetris 舊版投影片 -- 第一章 布林邏輯
nand2tetris 舊版投影片 -- 第一章 布林邏輯nand2tetris 舊版投影片 -- 第一章 布林邏輯
nand2tetris 舊版投影片 -- 第一章 布林邏輯
 
Boolean arithmetic
Boolean arithmeticBoolean arithmetic
Boolean arithmetic
 
Introduction
IntroductionIntroduction
Introduction
 
Computer architecture
Computer architectureComputer architecture
Computer architecture
 

Dernier

1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...
1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...
1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...黑客 接单【TG/微信qoqoqdqd】
 
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...黑客 接单【TG/微信qoqoqdqd】
 
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??testhelper Sobrenome
 
Grade 6 Lesson 7 Environment Protection.pptx
Grade 6 Lesson 7 Environment Protection.pptxGrade 6 Lesson 7 Environment Protection.pptx
Grade 6 Lesson 7 Environment Protection.pptxPriscilleXu
 
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...黑客 接单【TG/微信qoqoqdqd】
 
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...黑客 接单【TG/微信qoqoqdqd】
 
【創業簡報練習】當一個人吃飯會想起誰: (A)I-DOLL 陪吃娃娃|科技創業與營運實務
【創業簡報練習】當一個人吃飯會想起誰:(A)I-DOLL 陪吃娃娃|科技創業與營運實務【創業簡報練習】當一個人吃飯會想起誰:(A)I-DOLL 陪吃娃娃|科技創業與營運實務
【創業簡報練習】當一個人吃飯會想起誰: (A)I-DOLL 陪吃娃娃|科技創業與營運實務sardinesaying
 
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制bairnshajjes
 
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...ggbob1
 
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制gravestomas0
 
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptx
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptxJAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptx
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptxCHANSUITNEEMoe
 
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...黑客 接单【TG/微信qoqoqdqd】
 
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...ggbob1
 
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdfshanshanhui1
 

Dernier (14)

1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...
1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...
1.🔥承接黑客破解任务,你的难题我们来解决! 💡无论你是游戏玩家、企业用户还是个人用户,都能在这里找到满意的解决方案。 💪经验丰富的专业团队为您提供全方位...
 
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...
1.💥黑客接单,挑战你的想象力! 🚀💡从最炫酷的黑科技到神秘莫测的代码世界,这里都是你想要的技术。无论是破解密码、入侵系统还是开发软件,我们都能帮你实现!...
 
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??
保分服务在SAT考试作弊问题上的应对策略和措施是否充分,如何确保服务的可靠性??
 
Grade 6 Lesson 7 Environment Protection.pptx
Grade 6 Lesson 7 Environment Protection.pptxGrade 6 Lesson 7 Environment Protection.pptx
Grade 6 Lesson 7 Environment Protection.pptx
 
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...
我了解到黑客在某些领域拥有卓越的技术能力,特别是在处理系统漏洞方面。在当前的情境下,如果我想要改变我的毕业成绩,他们的帮助或许是我唯一可行的选择。【微 t...
 
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...
🎉一键更改成绩单,轻松点亮你的未来! 💡[书]想知道自己成绩怎么样?别担心!我们来帮您解答疑惑。 在这里,只需轻轻一点按钮,就能立即查看到分数、排名和其他...
 
【創業簡報練習】當一個人吃飯會想起誰: (A)I-DOLL 陪吃娃娃|科技創業與營運實務
【創業簡報練習】當一個人吃飯會想起誰:(A)I-DOLL 陪吃娃娃|科技創業與營運實務【創業簡報練習】當一個人吃飯會想起誰:(A)I-DOLL 陪吃娃娃|科技創業與營運實務
【創業簡報練習】當一個人吃飯會想起誰: (A)I-DOLL 陪吃娃娃|科技創業與營運實務
 
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制
加急代办一个日本鹿儿岛纯心女子大学学位记🌈学习成绩单电子版定制🌈仿制荷兰大学毕业证🌈日语JLPT证书定制
 
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...
30T.ppt【国外大学文凭样本】TWU毕业证认证Q/微:892798920办西三一大学毕业证留信留服使馆公证,TWU硕士毕业证,TWU研究生毕业证,文凭...
 
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制
未毕业在线购买日本熊本县立大学学位记🏆学习成绩单电子版定制🏆克隆爱尔兰大学文凭🏆CFA证书定制
 
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptx
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptxJAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptx
JAWAPAN BUKU AKTIVITI BAHASA CINA TAHUN 3.pptx
 
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...
GPA低怎么办? | 身份黑后回复方案 | 出入境激活 身份恢复美本GPA太低了怎么办黑客服务,黑客修改大学成绩,黑客改成绩单,黑客入侵教务系统,找黑客修...
 
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...
【国外大学文凭样本】多大毕业证认证Q/微:892798920办多伦多大学毕业证留信留服使馆公公证,多大硕士毕业证,U of T研究生毕业证,文凭,改U o...
 
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf
003 DSKP KSSR SEMAKAN 2017 BAHASA CINA TAHUN 3.pdf
 

系統程式 -- 第 6 章 巨集處理器

  • 1. 1 第6章 巨集處理器 巨集處理器 (Macro Processor) 乃是一種方便程式撰寫者使用,避免重複撰寫程 式的工具,在程式被編譯前,巨集處理器會先將程式當中的巨集展開,然後再交 給編譯器或組譯器進一步處理。 在組合語言當中,非常仰賴巨集的使用,因為組合語言沒有強大的編譯功能可以 提供高層次的語法,巨集就成了組合語言當中唯一可以採用的較高層次工具。 在本章中,我們將介紹組合語言中巨集的用途與作法,並且介紹巨集處理的演算 法。最後,在實務案例中,我們將焦點轉向高階語言,介紹 C 語言當中的巨集, 並利用 gcc 觀察巨集展開的過程。 6.1 組合語言的巨集 為了說明巨集在組合語言當中的功能,先讓我們來看一個具有巨集的組合語言範 例,我們以 max(x,y) 這樣一個函數為例,說明巨集的用法。範例 6.1 (a) 顯示了 一個具有巨集的 CPU0 組合語言,其中的 MAX 是巨集,該巨集被定義後被呼 叫了兩次。範例 6.1 (b) 是該程式被巨集處理器展開後的結果。 範例 6.1 具有巨集的組合語言 - 展開前與展開後的狀況 (a). 巨集展開前 (b) 巨集展開後 1 2 3 4 5 6 7 8 9 10 11 12 13 MAX MACRO &X, &Y, &Z LD R1, &X LD R2, &Y CMP R1, R2 JLE $ELSE ST R1, &Z JMP $END $ELSE: ST R2, &Z $END: MEND MAX(A, B, C) // MAX(A,B,C) LD R1, A LD R2, B CMP R1, R2 JLE $ELSE1 ST R1, C JMP $END2 $ELSE1: ST R2, C $END2: // MAX(C,D,E) LD R1, C LD R2, D
  • 2. 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 MAX(C, D, E) RET A: WORD 5 B: WORD 3 C: RESW 1 D: WORD 7 E: RESW 1 CMP R1, R2 JLE $ELSE3 ST R1, E JMP $END4 $ELSE3: ST R2, E $END4: RET A: WORD 5 B: WORD 3 C: RESW 1 D: WORD 7 E: RESW 1 在範例 6.1 當中,左半部 (a) 是包含巨集的原始程式,而右半部 (b) 則是經過 巨集處理器展開後的狀況。讀者可以很清楚的看到,在第 1 行當中,我們用 MACRO 指令定義了一個名稱為 MAX 的巨集,而且在第 11 行中,我們用 MEND 指令結束巨集定義。接著,在 13 行當中我們以 MAX(A,B,C) 的方式呼叫了該巨 集一次,接著又在 14 行當中以 MAX(C,D,E) 第二次呼叫該巨集。於是,導致了 該巨集在程式當中被呼叫了兩次。 因此,在範例 6.1 右半部的 (b) 當中,MAX 巨集被展開了兩次,第一次是在的 第 1 行,第二次是在第 11 行。在第一次巨集展開的程式內 (1-10 行),參數 &X 被取代為 A, &Y 被取代為 B, 而 &Z 被取代為 C。同樣的,在第二次巨集展開的 程式碼內 (11-20 行),參數 &X, &Y, &Z 則分別被取代為 C, D, E。 除了參數的取代之外,為了避免同一巨集多次展開所造成的標記重複現象,因此, 巨集處理器會將標記加上編號,以避免重複的狀況。 在巨集當中,標記的前面必須被加上錢字號 $,舉例而言,像 $ELSE 與 $END 等 兩個標記就被加上了錢字號,這是用來提醒巨集處理器的一種方法。這兩個標記 展開後變成 $ELSE1, $END2, $ELSE3, $END4,如此就可以避免到標記重複的現 象。
  • 3. 3 6.2 巨集處理的演算法 單層的巨集處理器只能容許一層巨集呼叫,不能容許在巨集當中再度呼叫巨集。 這種巨集處理器的設計非常簡單,只要針對每一個巨集指令進行單層展開即可。 其演算法如圖 6.1 所示。 演算法 說明 Algorithm MacroProcessor Input sourceFile, expandFile inFile = open(sourcFile) outFile = create(expandFile) pass1() pass2() End Algorithm Function pass1 while (not inFile.isEnd) line = getLine() if isMacroDefine(line) macro = readMacro(); macroTable[macro.name] =macro end while End Function Function pass2 inFile.goTop(); while (not inFile.isEnd) line = getLine() op = opCode(line) search macroTable for op if found macroCall = parseMacroCall(line); macro = macroTable[macroName]; body = replace macroCall.args in macro.body replace label with label+id in body write body to outFile else 單層巨集處理器 輸入原始程式、輸出展開檔 開啟輸入檔 (原始程式) 建立輸出檔 (展開程式) 第一輪:定義巨集 第二輪:展開巨集 第一輪:定義巨集 當輸入檔未結束時 讀取一行 如果是巨集定義 讀取整個巨集 記錄到巨集表當中 第二輪:展開巨集 回到輸入檔開頭 當輸入檔未結束時 讀取一行 取得指令部分 看看是否為巨集呼叫 如果是巨集呼叫 剖析巨集呼叫 取得巨集內容 取代內容中的參數 為標記加上編號 將取代後的內容輸出 如果不是巨集呼叫
  • 4. 4 write source line to outFile end while End Function 將該指令直接輸出 圖 6.1 單層巨集處理器的演算法 圖 6.1 的演算法使用到兩種記錄結構,巨集記錄 macro 與呼叫結構 macroCall, 並且使用到一個符號表 macroTable。利用這些資料結構,巨集處理器先在第一 輪的讀取過程中建立巨集定義表,然後在第二輪的展開過程當中,展開每一行巨 集呼叫,輸出展開後的結果。 大部分的商業用巨集處理器會支援多層的巨集展開功能,這種多層的展開方式雖 然較為複雜,但是其基本動作與圖 6.1 相當類似,只是必須對每一行以遞迴的方 式進行展開呼叫,如果在巨集展開的過程當中又發現巨集呼叫的指令時,就必須 在呼叫巨集展開函數,以達成遞迴展開的功能。 6.3 實務案例 在本節中,我們將透過 gcc 的巨集展開功能,觀察 C 語言巨集的展開過程,以 便理解巨集展開的實務操作方式。 6.3.1 C 語言的巨集 在 C 語言的設計中,有兩種巨集宣告方式,您可以使用 #define 指令宣告巨集函 數,也可以利用 inline 指令,讓一般函數改為巨集函數,直接展開到程式當中。 通常,#define 指令是用來撰寫較短的巨集定義,而 inline 指令則用來撰寫較長 的巨集函數。 範例 6.2 中顯示了一個 C 語言的巨集定義與呼叫程式,其中定義了兩個巨集函 數 max(a,b) 與 min(a,b),分別傳回 a,b 兩者中的較大值與較小值。範例 6.2 左 半部的 (a) 部分是原始程式,而右半部的 (b) 部分是展開後的結果,請讀者對 照查看,以便理解 C 語言中的巨集運作方式。 我們可以使用 GNU 工具中的 gcc 編譯器,加上 -E 參數,以便將程式中的巨集 展開,但不執行編譯動作。範例 6.2 就是我們用指令 gcc -E macro.c -o macro_E.c 將 (a) 展開為 (b) 的結果,讀者可以親自操作看看。
  • 5. 5 範例 6.2 具有巨集的 C 語言 - 展開前與展開後的狀況 指令:gcc -E macro.c -o macro_E.c (a) 展開前:macro.c (b) 展開後:macro_E.c #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) int main() { int x = max(3,5); int y = min(3,5); printf("max(3,5)=%d, min(3,5)=%dn",x,y); } int main() { int x = (3>5?3:5); int y = (3<5?3:5); printf("max(3,5)=%d, min(3,5)=%dn",x,y); } 條件式展開 C 語言當中的巨集處理器,支援條件式展開的功能,這種功能對 C 語言相當重 要,尤其在專案管理上更是不可或缺,以下,我們將說明 C 語言中條件式展開的 巨集處理器之用途。首先,請讀者看範例 6.3 (a) 的程式,該程式用 #ifdef 條件 式巨集指令,定義了 bugs 變數與 error(msg) 巨集函數,並且在程式的最後利 用 error() 函數印出錯誤訊息,然後報告總共有幾個錯誤。 接著,請讀者利用 gcc 加上 -E 參數的方式,編譯該程式,指令如下所示。 gcc -E macroDebug.c -o MacroDebug_E.c 該指令會將程式的巨集展開,但因為編譯時沒有定義 _DEBUG_ 這個符號,因此, 展開後的程式不會印出除錯訊息,其原始碼如範例 6.3 (b) 所示。 範例 6.3 具有條件式巨集的 C 語言 - 展開前與展開後的狀況 (a) 檔案:MacroDebug.c (b) 檔案:MacroDebug_E.c #ifdef _DEBUG_ int bugs = 0; #define error(msg) {printf(msg);bugs++;} #endif #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) int main() { int x = (3>5?3:5); int y = (3<5?3:5); printf("max(3,5)=%dn",x); printf("min(3,5)=%dn",y); } (c) 檔案:MacroDebug_DEBUG_E.c
  • 6. 6 int main() { int x = max(3,5); int y = min(3,5); printf("max(3,5)=%dn",x); printf("min(3,5)=%dn",y); #ifdef _DEBUG_ if (x!=5) error("max(3,5)"); if (y!=3) error("min(3,5)"); printf("共有%d 個錯誤",bugs); #endif } int bugs = 0; int main() { int x = (3>5?3:5); int y = (3<5?3:5); printf("max(3,5)=%dn",x); printf("min(3,5)=%dn",y); if (x!=5) {printf("max(3,5)");bugs++;}; if (y!=3) {printf("min(3,5)");bugs++;}; printf("共有 %d 個錯誤", bugs); } 接著,再請讀者利用下列指令編譯該程式,其中的 –D_DEBUG_ 參數會動態的定 義一個 _DEBUG_ 巨集符號傳給 gcc 編譯器。 gcc -E -D_DEBUG_ macroDebug.c -o MacroDebug_DEBUG_E.c 此時,由於 _DEBUG_ 符號已被定義,因此,展開後的程式會定義 bugs 變數, error(msg) 函數,並印出除錯訊息。其原始碼如範例 6.3 (c) 所示。 這種條件式的巨集定義的方式,在 C 語言當中相當常見,利用這種方式,我們 可以編譯出程式碼較大的除錯版本,以便於除錯時使用。然後,在程式要發行時, 編譯一個沒有 _DEBUG_ 符號的版本,如此,發行的軟體程式會較為精簡,也不 會動不動就跑出錯誤訊息來困擾使用者。這也是使用 C 語言開發軟體時必須具 備的巨集知識。 習題 6.1 請說明巨集處理器的輸入、輸出與功能為何? 6.2 請說明巨集處理器會如何處理巨集參數? 6.3 請說明巨集處理器在展開標記時會產生甚麼問題,應如何解決? 6.4 請使用 gcc 工具將範例 6.2 展開,觀察展開後的檔案,並說明展開前後的對 應關係。
  • 7. 7 6.5 請使用 gcc 工具將範例 6.3 展開,觀察展開後的檔案,並說明展開前後的對 應關係。