系統程式 – 理論與實務

第 12 章、系統軟體

作者:陳鍾誠
旗標出版社

1.1 簡介:何謂系統程式?
 System Software v.s System Programming

 System Software ( 系統軟體 )
 凡是專門設計給程式設計師使用的軟體,就被稱為系統軟體,而設計給一般大

眾使用的軟體,則稱為應用軟體。

 System Programming ( 系統程式 )
 與『作業系統』或『電腦系統』相關的程式。
 通常與電腦硬體有密切的關係。

System Software
 程式設計師專用的軟體

一般使用者所用的軟體
試算表

 組譯器

排版軟體

 載入器

瀏覽器

 連結器

…

 巨集處理器
 編譯器
 直譯器

應用軟體

 虛擬機
 模擬器
 作業系統

系統軟體

System Programming
 作業系統相關的程式

電腦硬體相關的程式
組合語言

行程管理

C 語言

執行緒

嵌入式系統

行程通訊

系統程式

並行控制
記憶體管理
檔案輸出入
驅動程式

應用程式

些不是系統程式?
遊戲程式
資料庫程式
多媒體程式

本書所採用的角度
 廣義的系統軟體 (System Software)
程式設計師專用的軟體

 廣義的系統程式 (System Programming)
與電腦硬體相關的程式
與作業系統相關的程式

本書的架構
 第 1 章、系統軟體

第 7 章、巨集處理器

 第 2 章、電腦的硬體結構

第 8 章、高階語言

 第 3 章、組合語言

第 9 章、編譯器

 第 4 章、組譯器

第 10 章、虛擬機與模擬器

 第 5 章、連結與載入

第 11 章、作業系統

 第 6 章、嵌入式系統

第 12 章、系統軟體實作

圖 1.1 本書的章節導引圖
高階 語言 (C)
(第 8 章)

組合語言
(第 3 章)

巨集處理器 ( 第 7 章 )

系統軟體 ( 第 1 章 )
嵌入式系統 ( 第 6 章 )
系統軟體實作 ( 第 12 章 )
組譯器 ( 第 4
章)
其他目的檔
(第 5 章)

編譯器 ( 第 9 章 )

直譯器 ( 第 8 章 )

目的檔 ( 第 5 章 )
連結器 ( 第 5 章 )

函式庫
(第 5 章)

執行檔 ( 第 5 章 )
載入器 ( 第 5 章 )
執行

虛擬機與模擬器 ( 第 10
章)

作業系統 ( 第 11 章 )

電腦的硬體結構 ( 第 2 章 )

1.2 電腦硬體的基本概念
 馮紐曼電腦
處理器 (CPU)
記憶體 (Memory)
匯流排 (Bus)
輸出裝置 (Output device)
輸入 裝置 (Input device)

 公式
Computer = CPU+BUS+Memory+Input+Output

馮紐曼電腦架構
ALU
算術邏輯單元
Control Unit
控製單元

內部匯流排 Bus

暫存器
R0

RK

記憶體

IR
SW
PC

輸出入單元
控制匯流排
資料匯流排
位址匯流排

輸出裝置

輸出入
控制器

輸入裝置

圖 1.2 現代電腦的抽像架構 – 馮紐曼結構

馮紐曼電腦的運作方式
 CPU 、記憶體、與輸出入裝置之間,是透過匯流排進行溝通

 CPU 可以將資料透過匯流排傳給記憶體,也可以接收從記憶體傳來的資

 當 CPU 想要進行輸出,例如將資料傳送給螢幕或寫到硬碟時,也是透

過匯流排將資料傳到該輸出裝置。

 當資料進入到輸入裝置後,也是透過匯流排將資料傳送給 CPU 。

CPU 的內部結構
 CPU = ALU+ 控制單元 + 內部匯流排 + 暫存器 + 輸出入單元

ALU
算術邏輯單元
Control Unit
控製單元

內部匯流排 Bus

暫存器
R0

RK
IR
SW
PC

輸出入單元

 CPU 可以說是電腦當中的小型電腦,只是其記憶單元很少,只有幾個暫

存器而已

指令的執行過程
 階段 1 :提取階段
 步驟 1 、提取指令

: IR = [PC]

 步驟 2 、更新計數器

: PC = PC + 4

 階段 2 :解碼階段
 步驟 3 、解碼

:控制單元對 IR 進行解碼

   階段 3 :執行階段
 步驟 4 、設定

:設定資料流向開關與 ALU 的運算模式

 步驟 5 、執行

:資料流入 ALU 後流回指定的暫存器

指令 ADD R1, R2, R3 的執行過

 步驟 1 、提取指令

: IR = [PC]

 步驟 2 、更新計數器

: PC = PC + 4

 步驟 3 、解碼
 控制單元解碼 IR ,取得運算元 ADD 、目標暫存器 R1 與來源暫存器 R2, R3 。

 步驟 4 、設定:
 設定 R2 , R3 流向 ALU 的開關,設定 ALU 運算為加法,設定 ALU 輸出流向 R1 。

 步驟 5 、執行:
 執行並等待一小段週期,讓資料正確流出與流入。

 結果: R1 = R2 + R3 。

程式的載入過程
當程式被編譯成機器碼後,通常以二進位形式儲存

在目的檔或執行檔中。

在執行時,載入器會將執行檔會放入記憶體內。

最後,載入器會將 CPU 的控制權交給該程式,於

是程式開始執行。

程式的執行過程
從起始指令開始,處理器會一次提取一個指令

循序的執行每個指令,一個接著一個執行,直到出

現分支跳躍指令為止。

當分支跳躍指令被執行時,程式的流程會改變,這

使得程式可以具備迴圈,邏輯判斷等能力。

1.3 組合語言的角色
 學習組合語言是理解電腦軟硬體架構的捷徑

 組合語言扮演了軟體與硬體的中介橋樑

 整個 CPU 的設計精神可以從組合語言中觀察得到

 程式設計師可透過組合語言理解處理器的功能

組合語言優勢與缺點
 優點
 執行快速、可控制電腦硬體。
 程式設計師可以透過學習組合語言,理解電腦的硬體結構

 缺點
 多樣性:有多少種 CPU ,通常就有多少種組合語言,有時因組譯器的設計不同

,同一種 CPU 有很多種組合語言語法。
 組合語言很難學,商業用處理器的組合語言都有很多怪僻。
 組合語言難以跨越平台,換到另一台電腦上程式需重寫。

本書所採用的組合語言
一顆刻意簡化過的處理器 - CPU0 。

指令集與指令格式都很簡單。

容易學習,有助於理解『組合語言與目的檔之間的

對照關係』。

機器語言
 範例一: 00010011000100100011000000000000

 範例二: 0001 0011 0001 0010 0011 0000 0000 0000

 範例三: 13 12 30 00

 範例四: ADD R1, R2, R3

組合語言的常見指令
 指令 1 : ADD R1, R2, R3
 指令 2 : SUB R1, R2, R3
 指令 3 : ADD R2, R3, R1
 指令 4 : LD R1, [300]
 指令 5 : ADD R1, R2, [300]
 指令 6 : ADD R1, R2, COUNT
 指令 7 : ADD R1, COUNT
 指令 8 : ADD COUNT

1.4 高階語言的用途
 語言: C/C++/C#, VB, Java, Ruby, Perl, Python, PHP …

 執行:編譯、解譯、虛擬機器、…

 編譯:執行快速
 解譯:執行很慢、約較編譯式慢上數十倍
 虛擬機器:速度中等

 採用立即編譯 (JIT) 技術時,速度可達編譯式的一半

C 語言
 大部分的資訊工程系學生所學習的第一個語言

 C 語言是 K&R 兩人於發明 UNIX 時設計的
 設計上特別考慮了許多系統程式的因素
 組合語言的銜接
 硬體的控制
 執行速度的考量

 UNIX 的成功也帶動了 C 語言的進一步發展

 C 語言是系統程式、嵌入式系統與作業系統等領域的首選語言

C 語言的特點
 快速

 可用指標進行記憶體映射輸出入,以便控制硬體

 與組合語言連結容易

 許多作業系統都是用 C 語言撰寫的
UNIX, Linux, Windows, FreeBSD, ….

1.5 實務案例
1.5.1 GNU 開發工具

1.5.2 Visual Studio

1.5.1 GNU 開發工具
GNU 工具

開放原始碼 , 由 Richard Stallman 發起的

Linux 也是用 GNU 工具撰寫的

支援處理器非常眾多
 x86, IA32,ARM,MIPS,PowerPC, …

GNU 工具的開發環境
 在 Linux 中預設就有 GNU 工具。

 在 MS. Windows 中可用

Cygwin 環境,其中包含了大部

分 Linux 中常用的指令,當然也包含 GNU 工具。
 安裝時記得勾選 All/Devel/{gcc, binutils, make} 等選項

 安裝完後選『開始 / 所有程式 /Cygwin/Cygwin Bash Shell 』進

入 Cygwin 的 bash 命令列環境。

Cygwin 的命令列環境

GNU 的常用工具列表
工具
gcc

工具類型
C 語言編譯器
GNU C Compiler
as
組譯器
Assembler
ld
連結器
Linker
Ar
函式庫製作
Archive
Nm
name mangling
目標檔中的符號
objdump Object File Dump
目標檔傾印
objcopy Object File Copy
複製 / 轉換目標檔
strip
strip
去除除錯資訊
Strings 觀看字串表
Ltrace

追蹤函數呼叫路徑

說明
範例: gcc hello.c -o hello.o
範例: as hello.s -o hello.o
說明:將 hello.s 組譯為 hello.o
範例: ld -o abc.o a.o b.o c.o
說明:將 a.o, b.o, c.o 連結成執行檔 abc.o
範例: ar -r libabc.a a.o b.o c.o
說明:將 a.o, b.o, c.o 包裝成函數庫 libabc.a
範例: nm hello.o
說明:看 hello.o 目標檔的符號表。
範例: objdump -x hello.o
說明:查看目標檔資訊
範例: objcopy -O binary hello.elf hello.bin
說明:將 elf 檔轉換為 binary 檔
範例: strip a.o
說明:把 a.o 當中的符號表與除錯資訊去除。
範例: strings a.o
說明:觀看 a.o 檔中的字串表,會顯示符號名稱與分
段名稱。
範例: ltrace a.o
說明:追蹤函數呼叫路徑 ( 在 Cygwin 中沒有 ) 。

GNU 工具使用的基本流程
main.c

sum.c

main.o

gcc

sum.o

executable

ld

libm.a
printf.c

putc.c

kprintf.c

printf.o

gcc

putc.o

kprintf.o

ar

libc.a

編譯器 gcc 的用法
參數
-S
-E
-D
-g
-c
-I

範例
gcc -S sum.c -o sum.s
gcc -E hello.c -o hello.i
gcc -DDEBUG sum.c -o sum
gcc -g sum.c -o sum
gcc -c hello.c -o hello.o
gcc -c -I /home/kenny/include -o hello.o
hello.c
gcc -L /home/kenny/lib -o hello hello.o

說明
要求 gcc 產生組合語言程式碼
只執行巨集展開,但不產生目的檔
編譯時才定義巨集常數
編譯時加入除錯資訊,讓 gdb 可遠端除錯
編譯並組譯程式碼,但不做連結
指定引用檔 (*.h) 的路徑

gcc -L /home/kenny/lib -lm -lpthread -o
hello hello.o
gcc -shared a.o b.o c.o -o libabc.so

指定函式庫的名稱

-Werror

gcc -g -rdynamic -fPIC -o test
test.c
gcc -Werror sum.c -o sum.s

輸出 position-independent code ,一般在輸出動
態連結函式庫時使用
將警告視為錯誤,一但有警告就不輸出目標檔

-O0
-O1
-O2
-O3

gcc -S -O0 sum.c -o sum.s
gcc -S -O1 sum.c -o sum.s
gcc -S -O2 sum.c -o sum.s
gcc -S -O3 sum.c -o sum.s

不進行最佳化 ( 預設 )
第 1 級的最佳化 ( 較差 )
第 2 級的最佳化
第 3 級的最佳化 ( 最高等級 )

-L
-l
-shared
-fPIC

指定函式庫 (*.a) 的路徑

產生共享函式庫 (*.so)

範例:使用 gcc 進行編譯
C 語言主程式 (main.c)
#include <stdio.h>
int main(void) {
int sum1 = sum(10);
printf("sum=%d", sum1);
return 1;
}

C 語言函數 (sum.c)
int sum(int n) {
int s=0;
int i;
for (i=1; i<=n;i++) {
s = s + i;
}
return s;
}

範例 1.1 C 語言程式 - main.c 與 sum.c

gcc main.c sum.c –o sum.o
./sum.o
sum=55
圖 1.6 利用 gcc 同時編譯 main.c 與 sum.c 並輸出
執行檔

範例:使用 gcc 進行組譯
$gcc -S sum.c -o sum.s
$gcc -S main.c -o main.s
$gcc main.s sum.s –o sum2
$./sum2
sum=55

圖 1.7 將 gcc 當成組譯器使用

$gcc main.c sum.s –o sum3
$./sum3
sum=55

圖 1.8 利用 gcc 編譯 C 語言 main.c 同時組譯組合語言 sum.s

1.5.2 微軟 Visual Studio 整合
環境
GNU 工具的優點:
是短小精悍、支援平台眾多、而且開放原始碼

Visual Studio 的優點:
開發環境完整、視覺化開發介面優良、並且與微軟的

Windows 密切整合

Visual Studio
 版本
Visual Studio Professional 版本

Visual Studio Express 版本
 下載點: http://www.microsoft.com/Express/
 分為 Visual C#/Visual C++/Visual Basic/Visual Web Developer

等四個軟體。
 讀者可以下載 Visual C++ 版。

圖 1.9 利用 Visual Studio 編譯與執行
程式

GNU 工具與 Visual Studio 之
比較
GNU 工具的優點:
是短小精悍、支援平台眾多、而且開放原始碼

Visual Studio 的優點:
開發環境完整、視覺化開發介面優良、並且與微軟的

Windows 密切整合

本章摘要 (1)
1.1 系統程式
System Software + System Programming

1.2 電腦的硬體架構
馮紐曼架構
 Computer = CPU+Memory+Bus+Input+Output
 CPU = ALU + 控制單元 + 內部匯流排 + 輸出入

1.3 組合語言
是理解電腦硬體設計的關鍵
多樣、難懂、無法跨平台

本章摘要 (2)
1.4 高階語言
C 語言:是系統程式中最常用的語言

1.5 實務案例
1.5.1 GNU 開發工具
 gcc 的用法
1.5.2 Visual Studio