[書評] Programming from the Ground Up
Programming from the Ground Up
http://ftp.twaren.net/Unix/NonGNU/pgubook/
(免費下載)
----
這是一本觀點獨特的書, 他用組合語言的方式, 闡述程式最底層的世界
這樣講聽來有點空洞, 直接看這本書第一個程式吧
Chapter 3. Your First Programs
----
.section .text
.global _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
這是 Linux底下, 一段小到不能再小的程式
程式從 _start 進入, 然後設定 x86 暫存器: %eax = 1, %ebx = 0
int $80 是發出軟體中斷的指令, 其中 0x80 代表 Linux System Call
呼叫 System Call 的時候
%eax 放 system call ID, 1 表示離開程式
%ebx 表示 main function 的 return value
呼叫完這個 system call, Linux 就會結束程式
並把 %ebx 的內容當作 main() 的回傳值
User 接下來可以在 shell 裡, 打 echo $? 觀察這個回傳值
----
這個例子真的口味獨特 !!
他解釋一般程式是怎麼和 OS 溝通, 怎麼呼叫 system call
另外用很少的程式碼, 解釋組合語言的設施
看過這一小段程式, 起碼我知道, 當我呼叫 exit() 時, 原來做了這些事
書上還有用組合語言, 寫一小段程式, 開檔, 把所有字轉大寫, 存檔, 關檔
WHAT !! 用組合語言做這些事喔 !!
當我親自寫了這段程式, 心中的感動是無以言喻的 :)
推薦給所有想知道事物真正面貌的人閱讀 :)
----
Chapter 4 "All About Functions"
函數, 對應到的 assembly 語言, 這個是極端重要的 topic
靠這章的幫忙, 我總算是懂 x86的 stack frame
而且也真的寫了一些 assembly function 來呼叫
這章的範例是一個函數, 計算 2^3 + 2^5, 然後回傳
書上的玩法是從頭到尾都用 assembly, 我是先寫 C 版本, 搭配一個 main() 呼叫
int power(int base, int exp)
{
int ret = 1;
for(i=0; i< exp; i++)
ret *= base;
return ret;
}
下一步, 把 power() 改成用 assembly 寫, 混用 assembly 和 C
最後, 再把整個 C 都換成 assembly, 這樣玩下來收穫良多
----
Chapter 5 Dealing with Files
看到這章的標題, 我還真的懷疑看錯了... 檔案處理耶 !!
一般的檔案處理依賴神秘的 fopen/fwrite/fread, 或是底層的 open/read/write
書上告訴你, 這些東西都是藉由 OS 的 system call 完成
在呼叫 system call 之前, 把對應的 call ID 和參數放在暫存器裡
然後執行 INT 0x80, OS就會接手剩下的任務了
這章節真的很不錯, 隱藏在 open/read/write 底下的細節, 全部都出來了
而且用組合語言, 自己寫 open/read/write, 成就感滿點 !!
實現的手段和 chapter.4 一樣, 先用 C 刻出骨架, 再逐漸換成組合語言
我不知道這樣做對不對, 對 C我的掌握度高, 而且有骨架比較容易驗證 assembly
全系統直接從 assembly 開始寫, 我想我受不了 XD
----
Chapter 6 "Reading and Writing Simple Record"
這章揭露怎麼處理 struct (C 語言), 搭配 chapter 5 的檔案處理
我覺得受到的刺激沒有上一章那麼強悍
而且看到組語的數目直線上升, 我有點受不了了 XD
----
Chapter 7 "Developing Robust Programs"
這章有點像講軟體工程, 他告訴你程式設計師拙於估算 schedule XD
書上給了幾個建議, 基本上是 "testing-driven" 程式設計方式
有種開發方式建議在撰寫程式碼之前, 先寫好 test case
Test case 日後可以反覆驗證程式, IC的 test bench 就是類似的觀點
----
Chapter 8 "Sharing Functions with Code Libraries"
站在巨人的肩膀上, 所以我們在 Standard C Library 的基礎上寫程式
不然連 printf() 都得自己寫, 實在是太難過了
這章用深入淺出的方式, 介紹怎麼連結函式庫, 對應的 Linker 指令怎麼下
這一小段指令值得寫在這裡...
as helloworld.s -o helloworld.o
ld -dynamic-linker /lib/ld-linux.so.2 helloworld.o -lc -o helloworld
-dynamic-linker /lib/ld-linux.so.2 指示 Linker 去哪裡找 dynamic linker
-lc 表示連結 LIBC (Library C), 實際會連結到 /lib/libc.so.6
helloworld.o 表示連結的目標 (我們寫的程式)
-o helloworld 代表 linker 的輸出是 helloworld
書上最後一個範例, 作者介紹怎麼產生 shared library
我最近才剛在 debug 時, 感受過這些機制的威力, 看這章特別有感覺
Shared library 機制用範例講, 真的是無比清楚
----
Chapter 9 "Intermediate Memory Topics"
"The Memory Layout of a Linux Program"
搭配 Jserv 的 "深入淺出Hello World, 這裡看得到完整的記憶體配置
搭配 memory layout, 作者揭示了動態配置記憶體和 OS 之間的關聯
原來配置記憶體, 也是搭配 system call, 用 C++ 的 new/delete
最好知道底層"可能"的實作細節, 比較好
作者很有意思, 竟然用 assembly 寫了一套 new / delete 的程式庫 (雖然效能很差)
我很喜歡這個範例, 比如他透過實作, 告訴你 new 要記憶體時, 其實多要了一些
他在前面偷偷塞了一些資料, 從記憶體區塊中間把指標回傳
所以說, 小筆資料儘量不要用動態配置, 根本的原因在這裡 (overhead大)
這一章整體碰觸的 topic 很複雜, 但是作者拿捏的洽到好處, 值得一看
----
Chapter 10 "Counting Like a Computer"
2's complement
Binary <-> decimal
AND/OR/XOR logical operation
Bit-Wise operation
Big/Little Endian
像我這種每天被 fixed point 運算折磨的人, 這章是選擇直接跳過
畢竟我可是每天用身體感受啊
----
Chapter 11 "High-Level Language"
Chapter 12 "Optimization"
Chapter 13 "Moving On from Here"
這三章都比較短, 比較沒有我喜歡的底層的東西, 我當故事書很快的讀過
----
Appendix A. GUI Programming
用 gtk 在 Linux 上寫視窗程式... 而且是用 assembly... 算了...
----
Appendix B. Common x86 Instructions
這是一個不錯的 reference, 他還簡單的介紹 assembler 的虛指令 (directive)
基本上這些資料真的要找, google一大堆
----
Appendix C. Important System Calls
Linux 一些書上出現過的 system call 列表
----
Appendix D. ASCII Codes
----
Appendix E. C Idioms in Assembly Language
值得一看, 可以大概認識平常用的 C, 會怎麼對應到組語 (for x86)
----
Appendix F. Using GDB Debugger
托這本書的福? 我總算會用 GDB debug 了
用命令下中斷, 單步執行, 印 call stack 實在很有意思 (也很不直覺)
我覺得 GDB 值得學, 看完這本書, 我又多一個 debug 的武器了
http://ftp.twaren.net/Unix/NonGNU/pgubook/
(免費下載)
----
這是一本觀點獨特的書, 他用組合語言的方式, 闡述程式最底層的世界
這樣講聽來有點空洞, 直接看這本書第一個程式吧
Chapter 3. Your First Programs
----
.section .text
.global _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
這是 Linux底下, 一段小到不能再小的程式
程式從 _start 進入, 然後設定 x86 暫存器: %eax = 1, %ebx = 0
int $80 是發出軟體中斷的指令, 其中 0x80 代表 Linux System Call
呼叫 System Call 的時候
%eax 放 system call ID, 1 表示離開程式
%ebx 表示 main function 的 return value
呼叫完這個 system call, Linux 就會結束程式
並把 %ebx 的內容當作 main() 的回傳值
User 接下來可以在 shell 裡, 打 echo $? 觀察這個回傳值
----
這個例子真的口味獨特 !!
他解釋一般程式是怎麼和 OS 溝通, 怎麼呼叫 system call
另外用很少的程式碼, 解釋組合語言的設施
看過這一小段程式, 起碼我知道, 當我呼叫 exit() 時, 原來做了這些事
書上還有用組合語言, 寫一小段程式, 開檔, 把所有字轉大寫, 存檔, 關檔
WHAT !! 用組合語言做這些事喔 !!
當我親自寫了這段程式, 心中的感動是無以言喻的 :)
推薦給所有想知道事物真正面貌的人閱讀 :)
----
Chapter 4 "All About Functions"
函數, 對應到的 assembly 語言, 這個是極端重要的 topic
靠這章的幫忙, 我總算是懂 x86的 stack frame
而且也真的寫了一些 assembly function 來呼叫
這章的範例是一個函數, 計算 2^3 + 2^5, 然後回傳
書上的玩法是從頭到尾都用 assembly, 我是先寫 C 版本, 搭配一個 main() 呼叫
int power(int base, int exp)
{
int ret = 1;
for(i=0; i< exp; i++)
ret *= base;
return ret;
}
下一步, 把 power() 改成用 assembly 寫, 混用 assembly 和 C
最後, 再把整個 C 都換成 assembly, 這樣玩下來收穫良多
----
Chapter 5 Dealing with Files
看到這章的標題, 我還真的懷疑看錯了... 檔案處理耶 !!
一般的檔案處理依賴神秘的 fopen/fwrite/fread, 或是底層的 open/read/write
書上告訴你, 這些東西都是藉由 OS 的 system call 完成
在呼叫 system call 之前, 把對應的 call ID 和參數放在暫存器裡
然後執行 INT 0x80, OS就會接手剩下的任務了
這章節真的很不錯, 隱藏在 open/read/write 底下的細節, 全部都出來了
而且用組合語言, 自己寫 open/read/write, 成就感滿點 !!
實現的手段和 chapter.4 一樣, 先用 C 刻出骨架, 再逐漸換成組合語言
我不知道這樣做對不對, 對 C我的掌握度高, 而且有骨架比較容易驗證 assembly
全系統直接從 assembly 開始寫, 我想我受不了 XD
----
Chapter 6 "Reading and Writing Simple Record"
這章揭露怎麼處理 struct (C 語言), 搭配 chapter 5 的檔案處理
我覺得受到的刺激沒有上一章那麼強悍
而且看到組語的數目直線上升, 我有點受不了了 XD
----
Chapter 7 "Developing Robust Programs"
這章有點像講軟體工程, 他告訴你程式設計師拙於估算 schedule XD
書上給了幾個建議, 基本上是 "testing-driven" 程式設計方式
有種開發方式建議在撰寫程式碼之前, 先寫好 test case
Test case 日後可以反覆驗證程式, IC的 test bench 就是類似的觀點
----
Chapter 8 "Sharing Functions with Code Libraries"
站在巨人的肩膀上, 所以我們在 Standard C Library 的基礎上寫程式
不然連 printf() 都得自己寫, 實在是太難過了
這章用深入淺出的方式, 介紹怎麼連結函式庫, 對應的 Linker 指令怎麼下
這一小段指令值得寫在這裡...
as helloworld.s -o helloworld.o
ld -dynamic-linker /lib/ld-linux.so.2 helloworld.o -lc -o helloworld
-dynamic-linker /lib/ld-linux.so.2 指示 Linker 去哪裡找 dynamic linker
-lc 表示連結 LIBC (Library C), 實際會連結到 /lib/libc.so.6
helloworld.o 表示連結的目標 (我們寫的程式)
-o helloworld 代表 linker 的輸出是 helloworld
書上最後一個範例, 作者介紹怎麼產生 shared library
我最近才剛在 debug 時, 感受過這些機制的威力, 看這章特別有感覺
Shared library 機制用範例講, 真的是無比清楚
----
Chapter 9 "Intermediate Memory Topics"
"The Memory Layout of a Linux Program"
搭配 Jserv 的 "深入淺出Hello World, 這裡看得到完整的記憶體配置
搭配 memory layout, 作者揭示了動態配置記憶體和 OS 之間的關聯
原來配置記憶體, 也是搭配 system call, 用 C++ 的 new/delete
最好知道底層"可能"的實作細節, 比較好
作者很有意思, 竟然用 assembly 寫了一套 new / delete 的程式庫 (雖然效能很差)
我很喜歡這個範例, 比如他透過實作, 告訴你 new 要記憶體時, 其實多要了一些
他在前面偷偷塞了一些資料, 從記憶體區塊中間把指標回傳
所以說, 小筆資料儘量不要用動態配置, 根本的原因在這裡 (overhead大)
這一章整體碰觸的 topic 很複雜, 但是作者拿捏的洽到好處, 值得一看
----
Chapter 10 "Counting Like a Computer"
2's complement
Binary <-> decimal
AND/OR/XOR logical operation
Bit-Wise operation
Big/Little Endian
像我這種每天被 fixed point 運算折磨的人, 這章是選擇直接跳過
畢竟我可是每天用身體感受啊
----
Chapter 11 "High-Level Language"
Chapter 12 "Optimization"
Chapter 13 "Moving On from Here"
這三章都比較短, 比較沒有我喜歡的底層的東西, 我當故事書很快的讀過
----
Appendix A. GUI Programming
用 gtk 在 Linux 上寫視窗程式... 而且是用 assembly... 算了...
----
Appendix B. Common x86 Instructions
這是一個不錯的 reference, 他還簡單的介紹 assembler 的虛指令 (directive)
基本上這些資料真的要找, google一大堆
----
Appendix C. Important System Calls
Linux 一些書上出現過的 system call 列表
----
Appendix D. ASCII Codes
----
Appendix E. C Idioms in Assembly Language
值得一看, 可以大概認識平常用的 C, 會怎麼對應到組語 (for x86)
----
Appendix F. Using GDB Debugger
托這本書的福? 我總算會用 GDB debug 了
用命令下中斷, 單步執行, 印 call stack 實在很有意思 (也很不直覺)
我覺得 GDB 值得學, 看完這本書, 我又多一個 debug 的武器了
留言
您寫得真是不錯,看來我應該要把他看完。