組合語言簡介處理器BIOS啟動程式微軟組譯器組合語言DOSWindowsVisualStudioGNUGNU 組譯器C 轉組語連結 C 語言嵌入 C 語言訊息相關網站參考文獻最新修改簡體版English |
簡介GNU 的組譯器名稱為 as,該程式屬於 GNU binutil 套件的一部分,在 Linux 與 Cygwin等環境中都有此組譯器,但是,由於保護機制的影響,單純使用 as 組譯器很難在 Cygwin 之下執行。 實際上,直接使用 as 組譯的情況並不多見,較常見的情況是使用 gcc 作為組譯器,由於 gcc 會在適當的時機呼叫組譯器 as與連結器 ld,因此,使用 GNU工具的程式設計師通常將 gcc 作為編譯、組譯與連結的萬用工具。在本節中,我們也將以 gcc 作為主要的組譯工具。 為了避免直接撰寫組合語言時誤觸作業系統的保護機制,我們可以利用 gcc 將 C 程式轉換為組合語言,然後再對這些組合語言進行修改,以此種方式『撰寫』組合語言,而非直接從零開始。 將C語言編譯為組合語言後修改首先,請讀者先撰寫如範例 4.20的 C語言程式 (swap.c),該程式宣告了x, y, t等 3 個變數,然後,利用三個指定敘述將 x 與 y 交換,這是一個在排序法中常見的動作。 範例 4.20 將 x 與 y 交換的C語言程式 (檔名:swap.c)
接著,我們利用 gcc -S swap.c -o swap.s 指令,將C語言程式 (swap.c) 編譯為組合語言檔 (swap.s),swap.s 組合語言的內容如範例 4.21 (a) 所示。其中,29行的call ___main 指令之前的程式碼,主要是進行堆疊與框架環境的設定動作。接著,30行的movl $5, -4(%ebp) 指令將常數 5 放入變數 -4(%ebp) 這個位址中,該位址即為變數a位於堆疊中的位址。然後,31行的movl $3, -8(%ebp) 指令則是將常數 3 放入變數 b 的位址 -8(%ebp) 中。接著,在32-37 行,執行了 t=x; x=y; y=t 的交換動作,其中的 t 變數位址為 -12(%ebp)。然後,在 38-39 行的兩個指令movl -4(%ebp), %eax; movl %eax, 4(%esp),將位於 -4(%ebp) 的x變數放到堆疊上,以便作為 printf 函數的第2個參數,然後在 40 行時,再度利用 movl $LC0, (%esp) 指令,將 LC0這個字串 (也就是 "x=%d\12\0" ) 放入堆疊的第一個參數中,然後用 call printf 指令呼叫 printf 函數,這就是輸出指令 printf("x=%d\n",x);的呼叫過程。接著,位於42-45 行內的是 printf("y=%d\n",y) 的組合語言程式,然後,在 46 行當中,movl $1, %eax 將傳回值 1 放入 eax 暫存器中,然後利用leave; ret兩個指令回到上一層。這就是整個C語言程式 (swap.c) 的 IA32 組合語言。 範例:指令 gcc -S swap.c -o swap.s 所產生的組合語言 (swap.s)
範例:將 swap.s 組合語言檔修改後儲存為 swap_asm.s
在讀懂了組合語言程式 (swap.s) 的意義之後,我們就可以修改該組合語言,試著在其中加上一些指令。 由於C語言編譯器使用堆疊暫存器 esp與框架暫存器 ebp 作為變數的存取點,這對我們來說並不容易理解。因此,筆者將 swap.c 編譯後的組合語言 swap.s 修改為 swap_asm.s,用自己定義的 x, y, t 變數,取代原先的版本。然後,我們再利用 gcc 組譯 swap_asm.s 檔,結果其輸出與 swap.s 一模一樣,這顯示了我們的修改方式是正確的。以下是筆者的編譯與修改過程,讀者也可自行測試看看。 範例: 將 C 程式 swap.c 編譯為組合語言並修改的過程
從以上的過程,我們可以看到 GNU 組合語言的語法,其中,我們修改的組合語言如範例 4.23所示。其中,我們在資料段 (.data) 中宣告了 x, y, t 等三個變數,並且分別設定初值,而在程式段中,我們利用暫存器 eax 作為中介,移動記憶體變數。例如,t=x 可以由 movl x,%eax與 movl %eax,t 等兩個指令完成。這就是程式的主要部分。接著,我們利用movl x, %eax, movl%eax, 4(%esp) 兩個指令,把 x 變數推入 printf 的參數區,再用 movl $LC0, (%esp) 指令把 "x=%d\n" 字串的指標推入參數區,然後才利用 call _printf指令呼叫 printf 函數。這就是該程式的主要邏輯。 範例:組合語言檔 swap_asm.s 經過修改的片段
透過編譯器產生組合語言的方式,系統程式設計師可以使用如上的修改法,以設計組合語言,而不需要完全從頭開始,這種方法在嵌入式系統的開發過程當中也相當常見,例如,我們可以將效率不好的程式碼修改掉,以增進程式的效率,如此,系統程式人員就能更輕鬆的完成工作,而不需要從頭開始撰寫組合語言。 |
組合語言 -- 使用 GNU 工具轉換 C 為組合語言後再修改
page revision: 0, last edited: 11 Oct 2010 07:30
Post preview:
Close preview