編程語言的發(fā)展
- 機器語言: 由 0 和 1 組成.
- 匯編語言(Assembly Language): 用符號代替了 0 和 1, 比機器語言更加便于閱讀和記憶.
- 高級語言: C\C++\Java\Swift等, 更加接近于人類自然語言.
來源維基百科-匯編語言
操作:
將寄存器 BX 的內容送到寄存器 AX.
機器語言: 1000100111011000
匯編語言: mov ax, bx
高級語言: ax = bx
- 匯編語言與機器語言一一對應领突,每一條機器指令都有與之對應的匯編指令
- 匯編語言可以通過編譯得到機器語言案怯,機器語言可以通過反匯編得到匯編語言
- 高級語言可以通過編譯得到匯編語言\機器語言,但匯編語言\機器語言幾乎不可能還原成高級語言
匯編語言的特點
- 可以直接訪問, 控制各種硬件設備, 比如存儲器, CPU等, 能最大限度發(fā)揮硬件的功能.
- 匯編指令是機器指令的助記符, 和機器指令一一對應, 每一種CPU都有自己的機器指令集 \ 匯編指令集, 所以匯編語言不具備可移植性.
- 不區(qū)分大小寫, mov 和 MOV 是一樣的.
采用高級語言C++和匯編語言編寫同一個功能, 將 a + b 的結果賦值給 c, 然后打印 c 的結果.
語言 | 源文件大小 | 目標文件大小 | 可執(zhí)行文件大小 |
---|---|---|---|
匯編語言 | 近400字節(jié) | 近200字節(jié) | 近600字節(jié) |
C++ | 近150字節(jié) | 近550字節(jié) | 近9000字節(jié) |
由于C++會鏈接很多底層庫, 所以可執(zhí)行文件會大這么多.
匯編語言的分類
要弄清楚這個, 我們先講一下微處理器.
微處理器(Microprocessor)是可編程特殊集成電路, 其所有組件小型化至一塊或數(shù)塊集成電路內, 可在其一端或多端接受編碼指令局蚀,執(zhí)行此指令并輸出描述其狀態(tài)的信號. 又稱半導體中央處理器琅绅,是微型計算機的一個主要部件.
- 在具有微程序控制的指令集的微型計算機中, 微處理器不僅具有算術邏輯單元和控制邏輯單元, 還有控制存儲單元.
- 用于處理通用資料鹅巍,叫作 CPU (Central Processing Unit), 中央處理器.
- 用于圖像資料處理, 叫作 GPU (Graphics Processing Unit), 圖形處理器.
- 用于音訊資料處理, 叫作 APU (Audio Processing Unit), 音訊處理器.
- 其他
- 微處理器工作原理
- 通過設計好的指令集, 來輸入對應的指令, 控制處理器實現(xiàn)相應的功能.
- 所以指令集決定了處理器的架構, 由于不同的公司設計不一樣的指令集, 導致對應的硬件電路都可能不一樣.
- 匯編語言是用助記符來描述指令集. 便于人類編碼.
時間 | 事件 |
---|---|
1971年 | Intel公司發(fā)布世界第一款4位微處理器 4004 |
1972年 | Intel公司發(fā)布世界第一款8位微處理器 8008 |
1978年 | Intel公司發(fā)布16位微處理器 8086(是x86系列第一款) |
1982年 | AT&T貝爾實驗室設計的世界第一款32位微處理器BELLMAC-32A投產(chǎn) |
1990年 | 用RISC技術(精簡指令集)設計全球第一款64位微處理器 R4000 |
那么匯編語言怎么分類呢?
-
按照指令集架構分類:
- 8086匯編(16bit), x86系列第一款. 我們學習的就是這一種,
-
x86匯編(32bit), 這種架構常被稱為i386,
x86
, 它是 Intel 設計的 -
x86匯編(64bit), 這種架構常被稱為 AMD64, Intel64, x86-64,
x64
, 它是 AMD 設計的, 是x86架構的64位擴展, 后來公開, 也被Intel所采用, 故現(xiàn)在也稱為 Intel64. - ARM匯編, ARM處理器由于高性能, 低耗電, 常用于嵌入式, 移動設備.
- 其他
-
按照匯編格式分類: 這幾種基本上是符號系統(tǒng)的區(qū)別
- Intel 格式
- AT&T 格式
- ARM 格式
- 其他
指的一提的是
- x86 匯編指令的風格是 Intel 匯編, 被 Microsoft Windows, Visual C++ 采用.
- x64 匯編指令的風格是 AT&T 匯編, 被 GNU, Gas 采用(Gas 也可使用Intel匯編).
- ARM 匯編指令的風格是 ARM 匯編.被 Apple 采用. 應用于 iPhone 真機.
匯編語言的用途
- 編寫驅動程序, 操作系統(tǒng)(比如Linux內核的某些關鍵部分).
- 對性能要求極高的程序或者代碼片段,可與高級語言混合使用(內聯(lián)匯編).
- 軟件安全
- 病毒分析與防治.
- 逆向\加殼\脫殼\破解\外掛\免殺\加密解密\漏洞\黑客.
- 是理解整個計算機系統(tǒng)的最佳起點和最有效途徑, 為編寫高效代碼打下基礎.
了解 CPU 等硬件結構.
軟件\程序執(zhí)行的過程
每一個CPU芯片都有許多管腳, 這些管腳和總線(Bus)相連, CPU 通過總線跟外部器件交互.
- 地址總線(Address Bus): 它的寬度決定了 CPU 的尋址能力
- 數(shù)據(jù)總線(Data Bus): 它的寬度決定了 CPU 的單次數(shù)據(jù)傳送量, 也就是數(shù)據(jù)傳輸速度.
- 控制總線(Control Bus): 它的寬度決定了 CPU 對其他器件的控制能力, 能有多少控制.
- CPU 通過控制總線傳輸讀命令, 通過地址總線指定是內存中的3號單元, 通過數(shù)據(jù)總線傳輸數(shù)據(jù) 0000 1000 (08)
- 這里面的 0, 1 是指的是線路中的 高電平, 低電平. 線路越寬, 能傳輸?shù)臄?shù)據(jù)越多
數(shù)據(jù)總線
8088的數(shù)據(jù)總線寬度是 8 根, 8086 的數(shù)據(jù)總線寬度是 16根, 那么分別向內存中寫入 89D8H.
練習:
- 1 個 CPU 的尋址能力是 8 KB, 那么他的地址總線的寬度數(shù):
13
, 因為 - 8086, 8088, 80286, 80386 的地址總線寬度為16根, 20根, 24根, 32根, 那么他們的尋址能力分別是
64KB, 1MB, 16MB, 4GB
, 因為 - 8086, 8088, 8086, 80286, 80386 的數(shù)據(jù)總線寬度為8根, 8根, 16根, 16根, 32根, 那么他們一次可以傳送的數(shù)據(jù)是:
1B, 1B, 2B, 2B, 4B
,- 因為傳輸 1Byte 的數(shù)據(jù)實際是8bit .
- 從內存中讀取 1024 字節(jié)的數(shù)據(jù), 8086至少讀
512
次,- 因為 , 8086 的傳輸速度是 2B / 次, 所以需要 512 次.
這里再啰嗦一遍, 1 字節(jié) = 8 位, 1 Byte = 8 bit, 我們常說的 64 位操作系統(tǒng), 指的是CPU 每次能處理 64 bit 的數(shù)據(jù).
內存
各類存儲器的邏輯連接與物理連接對應圖.
所有的內存單元都有唯一的地址, 叫作物理地址, 內存地址空間的大小受 CPU 地址總線寬度的限制.
8086的地址地址總線寬度為20, 可以定位 個不同的內存單元, ( 內存地址范圍為0x00000 ~ 0xFFFFF), 所以8086的內存空間大小為 1 MB.
注: = 1048576 , 0xFFFFF => 1048575
- 0x00000 ~ 0x9FFFF: 主存儲器, 可讀可寫.
- 0xA0000 ~ 0xBFFFF: 向顯存中寫入數(shù)據(jù), 這些數(shù)據(jù)會被顯卡輸出到顯示器, 可讀可寫.
-
0xC0000 ~ 0xFFFFF: 存儲各種硬件\系統(tǒng)信息, 只讀.
8086的尋址方式
- CPU訪問內存單元時, 要給出內存單元地址.
- 8086有
20位
的地址總線, 可以傳送20
位的地址,1M
的尋址能力. - 但它又是
16位
結構的CPU, 它內部能夠一次性處理, 傳輸, 暫時存儲的地址為16位
. 如果將地址從內部簡單發(fā)出, 那么它只能送出16位
的地址, 表現(xiàn)出來的尋址能力只有64KB
- 所以8086采用了一種在內部使用
2個16位
地址合成的方式來生成1個20位
的物理地址.
地址加法器采用 物理地址 = 段地址 x 16 + 偏移地址 的方式合成物理地址.
比如 8086CPU 要訪問地址為 123C8H 的內存單元
我們又能發(fā)現(xiàn), 8086CPU的要訪問的同一個 物理地址 可以由不同的 段地址 和 偏移地址 組成.
內存的分段管理
- 8086采用
起始地址(段地址x16) + 偏移地址 = 物理地址
的方式來給出物理地址. - 為了開發(fā)方便, 我們采用分段的方式來管理內存.
- 比如地址 10000H ~ 100FFH 組成一段, 那么起始地址為 10000H, 段地址為 1000H, 大小為 100H.
如果給定一個段地址, 僅通過變化偏移地址來進行尋址, 最多可定位多少個內存單元?
偏移地址為 16 位, 變化范圍為 0 ~ FFFFH, 僅用偏移地址來尋址, 最多可尋64KB個內存單元() , 若給定段地址為 1000H, 用偏移地址尋址, CPU的尋址范圍為 10000H ~ 1FFFFH.
在 8086PC機中, 存儲單元的地址用段地址和偏移地址來描述,
比如數(shù)據(jù)在 21F60H 內存單元中, 對于 8086PC機來說, 數(shù)據(jù)存在內存2000: 1F60單元中,
或者數(shù)據(jù)存在 2000H段 中的 1F60H 單元中.
CPU的典型構成
不同的 CPU, 寄存器的個數(shù), 結構是不同的, 8086 有 14 個寄存器, 都是16位 寄存器, 每個可以存放 2個 字節(jié).
寄存器是有限存貯容量的高速存貯部件图焰,它們可用來暫存指令楞泼、數(shù)據(jù)和地址.
通用寄存器
- AX, BX, CX, DX這四個寄存器通常用來存放一般的數(shù)據(jù), 也被稱為是 通用寄存器, 通常, CPU會先將內存中的數(shù)據(jù)存儲到通用寄存器中, 然后再對通用寄存器中的數(shù)據(jù)進行運算.
- 假設內存中有一塊內存空間的值是 3, 現(xiàn)在想把它的值加 1 , 并將結果存儲在新的內存空間中.
- mov ax, srcMemory: CPU 先將原來內存空間的值存在寄存器中
- add ax, 1 : 讓寄存器ax與 1 相加.
- mov desMemory, ax : 將值賦給新的內存空間.
- AX, BX, CX, DX這四個通用寄存器是16位的, 里面AH, AL 分別代表高位寄存器, 和低位寄存器, 其他同理.
在匯編的數(shù)據(jù)存儲中
- 字節(jié): byte, 1 個字節(jié)由8 bit組成
- 字: word, 1個字由2個字節(jié)組成
上面展示的數(shù)據(jù) 20000 (4E20H), 字: 010011100 0100000B, 左邊是 高八位, 右邊是低八位.
段寄存器
8086 存在4個段寄存器, 當 CPU 需要訪問內存時, 由這4個提供段寄存器提供內存單元的 段地址.
- CS (Code Segmnet): 代碼段寄存器
- DS (Data Segmnet): 數(shù)據(jù)段寄存器
- SS (Stack Segmnet): 堆棧段寄存器
- ES (Extra Segmnet): 附加段寄存器
- 8086CPU 當前狀態(tài): CS 中的內容為 2000H, IP 中的內容是 0000H, CS 為代碼段寄存器, IP (Instruction Pointer Segment)為指令指針寄存器, 他們指示了 CPU 當前要讀取指令的地址.
- 內存 20000H ~ 20009H 單元存放著可執(zhí)行的機器碼.
- 地址: 20000H ~ 20002H, 內容: B8 23 01, 長度 3 Byte, 匯編指令: mov ax, 0123H
- 地址: 20003H ~ 20005H, 內容: BB 03 00, 長度 3 Byte, 匯編指令: mov bx, 0003H
- 地址: 20006H ~ 20007H, 內容: 89 D8, 長度 2 Byte, 匯編指令: mov ax, bx
- 地址: 20008H ~ 20009H, 內容: 01 D8, 長度 2 Byte, 匯編指令: mov ax, bx
下面將詳細就介紹 CPU 如何處理匯編指令.
- CS, IP 中的內容送到 地址加法器 中, 物理地址 = 段地址 x 16 + 偏移地址, 輸出 20000H
- 地址加法器 將物理地址送入到 輸入輸出控制電路.
- 輸入輸出控制電路 將物理地址 20000H 輸入到 地址總線 開始尋址.
- 從內存 20000H 單元開始存放的機器指令 B8 23 01 通過 數(shù)據(jù)總線 被送入到 CPU.
-
輸入輸出控制電路 將機器指令 B8 23 01 送入 指令緩沖器.
- 此時 IP 中的值自動增加, 以便CPU 可以讀取下一條指令
- 因為當前讀入的指令 B8 23 01 長度為 3 個字節(jié), 所以 IP 中的值加 3, 此時CS: IP執(zhí)行內存單元 2000: 0003
- 執(zhí)行控制器 執(zhí)行指令 B8 23 01, 即 mov ax, 0123H, 此時 AX 中的內容為 0123H.
- CPU 從內存 20003H 處讀取指令 BB 03 00, 送入 指令緩沖器, 此時 IP 再次加 3.
- 執(zhí)行指令 BB 03 00 即 mov bx, 0003H.
- CPU 從內存 20006H 處讀取指令 89 D8, 輸入指令緩沖器. 此時 IP 值加 2.
- 執(zhí)行指令 89 D8, 即 mov ax, bx, AX 中的內容變?yōu)?0003H.
- CPu 從內存 20008H 讀取指令 01 D8 入指令緩沖器. IP 的值加 2 .
- 執(zhí)行指令 01 D8, 即 add ax, bx, AX 中的內容變?yōu)?0006H.
上面這個過程可以簡述為
- 從 CS: IP 指向的內存單元讀取指令, 讀取的指令進入指令緩沖器.
- IP = IP + 所讀取指令的長度, 從而指向下一個指令的.
- 執(zhí)行指令, 重復步驟1, 重復這個過程.
指令和數(shù)據(jù)
看完上面這個過程, 我們會發(fā)現(xiàn) 指令和 數(shù)據(jù)都是二進制信息,
比如 內存中二進制信息 10001001 11011000, 既可當做數(shù)據(jù) 89D8H , 也可當做指令 mov ax, bx
那么 CPU 怎么區(qū)分兩者呢
- CPU 將 CS: IP 指向的內存單元的全部內容看做指令. 指令里面可能包含數(shù)據(jù).
- 如果內存中的某段內容曾被CPU執(zhí)行過,那么它所在的內存單元必然被CS:IP指向過
處理器架構超陆、指令集和匯編語言浦马,三者有何關系
維基百科-匯編語言
維基百科-X86
維基百科-ARM架構
維基百科-微處理器
維基百科-寄存器