編譯器不識別stm指令 第2章 編譯器簡述

2021-10-12 04:37:38 字數 2360 閱讀 2984

在現代作業系統上,我們常見的檔案一般分為兩種:

文字檔案

二進位制檔案(可執行程式)

從作業系統的角度講,兩類檔案在儲存時沒有絲毫區別。文字檔案之所以可以直接看到文字資訊,是因為它們被寫入內容時,寫入的都是字元編碼對應的二進位制值,所以按照相同的編碼方式開啟時,就可以看到裡邊的內容。

vs code開啟乙個elf格式的二進位制可執行檔案

當我們寫好乙個c程式,確保無誤後,我們會使用編譯器(gcc、msvc或者是其他)對它進行編譯執行,那麼這些常見的編譯器是如何把我們撰寫的文字源程式轉為可執行檔案的呢?

簡單來說(簡單地不能再簡單),編譯器接受c源程式的輸入內容,先根據詞法、語法規則掃瞄源程式,如果在語法層面沒有問題,建立起一顆ast(抽象語法樹),根據抽象語法樹,將源程式轉為中間表示(ir)。最後,通過中間表示,生成適用於目標平台的目標**(彙編)。

如果你熟悉gcc,通過-s引數可以指定gcc只生成彙編**而不是目標程式。例如下邊的c**:

int main()
執行:

gcc -s test.c
可以發現,目錄下已經生成了乙個名為test.s的檔案,開啟這個檔案,我們可以看到彙編**

.file	"test.c"

.text

.globl main

.type main, @function

main:

.lfb0:

.cfi_startproc

pushq %rbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movq %rsp, %rbp

.cfi_def_cfa_register 6

movl $1, -4(%rbp)

addl $1, -4(%rbp)

movl $0, %eax

popq %rbp

.cfi_def_cfa 7, 8

ret.cfi_endproc

.lfe0:

.size main, .-main

.ident "gcc: (ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"

.section .note.gnu-stack,"",@progbits

眾所周知,組合語言可以與機器指令一一對應,根據生成的彙編**生成二進位制檔案。再經過鏈結操作,即可生成最終的可執行檔案。

總結一下,編譯器生成可執行檔案的操作一般要有如下步驟:

詞法分析

語法分析

中間**生成

**優化

目標**生成

目標程式生成

詞法分析是編譯過程的乙個階段。這個階段的任務是從左到右乙個字元乙個字元讀入源程式,對構成源程式的字元流進行掃瞄和分解,從而識別出乙個個單詞。以我們上邊的test.c檔案為例,其中的識別出的單詞序列為

int:型別說明

main:id

(:左小括號

):右小括號

:右大括號

語法分析是編譯過程的第二個階段。語法分析的任務是在詞法分析的基礎上將單詞序列分解成各類語法短語,然後生成一顆抽象語法樹。以test.c為例,生成的抽象語法樹如下(也可以有其他的形式)

test.c的語法樹

在經歷了上述的詞法分析和語法分析過程後,有的編譯程式將源程式變成一種內部表達形式,這種內部表示形式被稱為中間語言或者中間**。所謂中間**是一種結構簡單、含義明確的記號系統,這種中間**可以被設計成多種形式,主要的原則有兩點:一是容易生成,二是容易將其翻譯成機器**。我們主要採用「三位址指令」的四元式的中間**。這種四元式的形式為:

(operator, var1, var2, result)
以test.c為例,中間表示應該為

1: function define, null, null, null

2: :=, 1, null, v1

3: +=, 1, null, v1

4: return, 0, null, null

這一部分是對前一階段產生的中間**進行改進,目的是使生成的中間**更加高效。

這一部分的任務是將中間**轉換為特定機器上的絕對指令**或彙編指令**。

我們的專欄將會著重講述除了**優化的其他部分。

lldb編譯器除錯指令

xcode斷點 控制台除錯指令 lldb編譯器除錯指令 p 列印基本資料型別值 列印物件持有的位址 po 列印基本資料型別值 列印物件的詳細資訊 call 呼叫一行oc 指令並實時執行生效 bt 回溯追蹤棧資訊 位址 breakpoint list 列印斷點元素列表 thread list 列印執行...

編譯器實現之旅 第二章 編譯器前端概觀

在這一章的旅程中,我們將要深入編譯器前端一 竟。看看編譯器前端到底由哪些元件組成,其分別又是在做什麼。似乎比我們想象的要簡單,編譯器前端僅由兩個元件組成,詞法分析器與語法分析器。請看下圖 源 詞法分析器 記號流 語法分析器 抽象語法樹 詞法分析器 lexer 是 前端中的前端 作為整個編譯器的第乙個...

編譯器實現之旅 第一章 編譯器概觀

編譯器,近在咫尺卻又遠在天邊。當我們寫下任何非機器語言 後,我們都需要借助編譯器將這些 變為通過計算機可執行的狀態。但是,就是這樣乙個使用率極高的程式,我們對其卻知之甚少。什麼是編譯器?編譯器對我們的 做了什麼?又是怎麼做的呢?如果你也懷有這些疑問,想要深入編譯器內部一 竟的話,那就隨我一起踏上這趟...