# 什麼是組譯器

由於機械語言是直接給 CPU 看的語言，是站在 CPU 的角度所設計，並沒有考慮到人類讀寫的容易與否。想要透過二進制編輯器來讀寫機械語也不是不可能，但也是非常痛苦的作業。組合語言就是為了這個問題才被發明出來。組合語言和機械語言幾乎是一對一對應的語言，但是對人類來說，組合語言要容易讀寫多了。

一般非直譯式或透過虛擬機器（譯注：如 Java 的 JVM），直接輸出二進制執行檔的編譯器，通常都是輸出組合語言。有些編譯器看起來是直接輸出機械語言，其實多半也是先輸出組合語言，再在背後執行組譯器。本書所做的C編譯器也是輸出組合語言。

把組合語言轉換成機械語言也可以說是「編譯」的一種，但是為了強調輸入是組合語言，又被稱作「組譯」。

讀者可能以前也在別的地方看過組合語言也說不定。如果還沒見過的話，現在正好是認識一下組合語言的好機會。用`objdump`指令，隨便找一個執行檔反組譯看看，看一下該執行檔機械語言轉回組合語言的結果吧。以下是`ls`指令反組譯的結果：

```
$ objdump -d -M intel /bin/ls
/bin/ls:     file format elf64-x86-64

Disassembly of section .init:

0000000000003d58 <_init@@Base>:
  3d58:  48 83 ec 08           sub    rsp,0x8
  3d5c:  48 8b 05 7d b9 21 00  mov    rax,QWORD PTR [rip+0x21b97d]
  3d63:  48 85 c0              test   rax,rax
  3d66:  74 02                 je     366a <_init@@Base+0x12>
  3d68:  ff d0                 call   rax
  3d6a:  48 83 c4 08           add    rsp,0x8
  3d6e:  c3                    ret
...
```

在筆者的環境下，`ls`指令約含有2萬個以上的機械語言指令，反組譯就會變成大概有2萬行篇幅的怪物，上面只放了開頭的一部份。

組合語言基本上是一行一個機械語言指令。舉例來說我們來看下面這行：

```
3d58:  48 83 ec 08           sub    rsp,0x8
```

這行是什麼意思呢？`3d58`表示的是存放該機械語言的記憶體位址。也就是說，執行`ls`指令的時候，該行指令會被放到記憶體的 0x3d58 號位置，等程式計數器跑到 0x3d58 時就會執行該行指令。緊接著的四個16進制數字是實際的機械語言的長相。CPU 把這些值讀進去，然後將其作為指令執行。`sub    rsp,0x8`則是對應該機械語言指令的組合語言。關於 CPU 的指令集我們會逐章解釋，上面這個指令是把 RSP 這個暫存器的數值減掉（sub 是 subtract，減去的英文的開頭）8的指令。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://koshizuow.gitbook.io/compilerbook/machine_code_assembler/assembler.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
