程式

計算機概論[2]

講師:溫室蔡

程式如何運作

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 條件、迴圈與函式是如何實現的

  • 程式如何被 CPU 執行

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 條件、迴圈與函式是如何實現的

  • 程式如何被 CPU 執行

艾倫·圖靈

英國數學家

二戰期間研製 Bombe 電腦

破解德軍 Enigma 密碼機

提出圖靈測試

提出圖靈機與圖靈完備性

圖靈機

一條無限長的紙帶

分成很多格

每格可以放一個符號

一個讀寫頭,可以:

  • 在紙帶上左右移動

  • 讀取所在格子的符號

  • 寫入所在格子的符號

  • 儲存一個狀態

一套讀寫規則

根據讀到的符號和儲存的狀態

決定是否寫入、移動或更改狀態

圖靈機

根據圖靈的數學證明

圖靈機什麼都做得到*

*除了停機問題

而有能力模擬圖靈機的程式語言

我們稱它是「圖靈完備」的

程式語言

把指令流程設計的更加易讀

就變成了程式語言

越接近人類語言的越「高階」

越接近硬體指令則越「低階」

Python、JavaScript
C/C++
組合語言
機器碼

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

電腦如何讀懂程式語言

電腦怎麼讀得懂這個:

int main(void) {
    int a = 2;
    int b = a + 3;
    if (b < 4) {
        return 1;
    }
    return 0;
}

什麼是編譯

把人類可讀的程式碼

變成電腦可讀的機器碼

以 C 語言為例:

預處理

編譯

連結

組譯

原始碼

機器碼

展開巨集

組合語言

機器碼

+函式庫

什麼是編譯

編譯

原始碼

組合語言

什麼是編譯(進階)

Lexer

Parser

Code

Generator

原始碼

組合語言

Tokens

AST

什麼是編譯(進階)

Lexer

Parser

Code

Generator

原始碼

組合語言

Tokens

AST

Tokenization

把一連串的字元分成有意義的單字

int main(void) {
    int a = 2;
    int b = a + 3;
    if (b < 4) {
        return 1;
    }
    return 0;
}

Tokenization

把一連串的字元分成有意義的單字

[關鍵字 int][識別符 main][左括號][關鍵字 void][右括號][左大括號]
    [關鍵字 int][識別符 a][等號][數字 2][分號]
    [關鍵字 int][識別符 b][等號][識別符 a][加號][數字 3][分號]
    [關鍵字 if][左括號][識別符 b][小於][數字 4][右括號][左大括號]
        [關鍵字 return][數字 1][分號]
    [右大括號]
    [關鍵字 return][數字 0][分號]
[右大括號]

Expression

會回傳值的就叫 expression,如:

[expression] =

3	[數字]
a	[識別符]
a + 3	[識別符][加號][數字]
a < 4	[識別符][小於][數字]
a = 5	[識別符][等號][數字]
func()	[識別符][左括號][右括號]

func1() + func2()
[expression][加號][expression]

Statement

看了就懂

if (...) {
...
} else {
...
}
while (...) {
...
}
for (...;...;...) {
...
}
int func(...) {
...
}

Statement

[關鍵字 if][左括號][expression][右括號][左大括號]
	[expression]
[右大括號][關鍵字 else][左大括號]
	[expression]
[右大括號]
[關鍵字 while][左括號][expression][右括號][左大括號]
	[expression]
[右大括號]
[關鍵字 for][左括號][expression][分號][expression][分號][expression][右括號][左大括號]
	[expression]
[右大括號]
[關鍵字 型別名稱][識別符][左括號][關鍵字 型別名稱][識別符][右括號][左大括號]
	[expression]
[右大括號]

抽象語法樹

定義了文法之後

構建「抽象語法樹」

就可以開始分析結構

AST(Abstract Syntax Tree)

main

=

a

2

=

b

+

a

3

if

條件

本體

a

<

4

return

1

return

0

代碼生成

做出了 AST

就可以把對應的組合語言生出來了

不過這東西到底長什麼樣子呢

組合語言

到了這個階段

你的程式已經變成 CPU 的個別指令了

但還算是可讀

因為還不是真正的 1 跟 0

暫存器

x86 架構大致有這些暫存器:

ax、bx、cx、dx、di、si

前綴代表大小:

rax

eax

ax

ah

al

64 位元

32 位元

16 位元

8 位元

x86 指令集

x86 組合語言常用的指令包含:

MOV - 把值存到暫存器或記憶體中

ADD - 加法

SUB - 減法

INC - 加一

DEC - 加一

跳轉指令

JMP - 無條件跳轉

JE    - 等於就跳

CMP - 比較兩個數字

JNE - 不等於就跳

JZ    - 等於 0 就跳

JNZ - 不等於 0 就跳

JG   - 大於就跳

JGE - 大於等於就跳

JL    - 小於就跳

JLE - 小於等於就跳

那這是啥?!

rbp、rsp 也是暫存器嗎?

push、pop 是什麼指令?

.text、.data 是什麼意思?

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

執行檔格式

.text

.data

Heap

Free space

Stack

位址高

位址低

程式碼

全域變數

動態配置的記憶體

各函式的區域變數

執行檔中的堆疊

位址高

位址低

main 的空間

< rsp(stack 頂)

< rbp

(main 空間底)

舊 rbp

執行檔中的堆疊

位址高

位址低

main 的空間

< rsp

< rbp

舊 rbp

執行檔中的堆疊

位址高

位址低

main 的空間

< rbp

舊 rbp

< rsp / rbp

func 的空間

執行檔中的堆疊

位址高

位址低

main 的空間

< rbp

舊 rbp

< rsp

func 的空間

執行檔中的堆疊

位址高

位址低

main 的空間

< rbp

舊 rbp

< rsp / rbp

func 的空間

執行檔中的堆疊

位址高

位址低

main 的空間

< rsp

< rbp

舊 rbp

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

程式如何運作

>

  • 什麼是程式語言

  • 電腦如何讀懂程式語言

  • 執行檔裡裝什麼

  • 程式如何被 CPU 執行

更多暫存器

除了前面的通用暫存器外

CPU 還有兩個特殊的暫存器

程式計數器(Program Counter)

與指令暫存器(Instruction Register)

指令週期

所有的指令都會被 CPU

以一個三階段的周期執行

Fetch - PC+1,把指令讀入 IR

Decode - 把存在 IR 的指令解碼成信號

Execute - 執行指令

(算數、寫入記憶體/暫存器)

本日課程結束

以上幫各位對於「程式如何運作」

的小小解惑

下一堂課會進入作業系統的介紹

敬請期待~

Made with Slides.com