匯編語言 Part 1——簡介、基本語法、內存分段與內存地址


簡介

什么是匯編語言?

匯編語言是一種低級的編程語言,在程序的語句和體系結構的機器代碼指令之間有很強的對應關系。

每種匯編語言都特定於特定的計算機體系結構,但需要解釋或編譯。匯編語言也可以稱為符號機器代碼。

匯編語言通常每個機器指令都有一個語句,通常也支持匯編指令、程序和內存位置的宏和符號標簽。

匯編代碼被匯編器轉換為可執行的機器代碼。轉換過程稱為匯編。

計算機編程語言的演進

機器語言

與模擬和機電計算機的早期工作不涉及我們所了解編程語言。由於早期的計算機需要直接對每個問題集進行連線,所以設置插頭的過程取代了基於文本的算法蒸餾。

隨着汞延遲線和磁鼓記憶裝置取代機電設備,在無需重新布線的情況下直接寫入內存中的地址並提供指令變得更加容易。這通常指的是編寫我們稱之為 "機器代碼 "的內容。現在通常被稱為"十六進制",因為現代的32位和64位微處理器系統以8或16十六進制塊每時鍾周期的速度讀取二進制數據。

在計算機級別編寫代碼是困難的:它要求程序員知道在硬件中寄存器和處理器的指令集的特定位置。閱讀機器代碼通常比編寫它更困難,因此跟蹤代碼更改幾乎是不可能的。

匯編語言

匯編語言的出現意味着第一次升級到計算機代碼級別的編程。他提供了一種用字符串操縱符和名稱來編寫機器代碼的方法,而不是原始的二進制版本。它仍然是難以閱讀,仍然需要知道哪些指令和寄存器位置,但它可以在紙或屏幕上閱讀並匯編成機器代碼。

我們還在使用匯編,大多數計算機外設的設備驅動程序都是用C代碼編寫的,但有些實時故障最好通過手動優化C編譯器中途生成的匯編代碼來解決。

高級語言——FORTRAN

FORTRAN 代表了公式翻譯 (FORmula TRANslation)。這門語言是在上世紀50年代中期的IBM 704系列計算機上發明的。

高級語言——BASIC

在計算機編程中,BASIC (Beginner's All-purpose Symbolic Instruction Code) 是一個高級語言族。它最初於 1963年由Dartmouth College的John George Kemeny和Thomas Eugene Kurtz設計,使得非科學領域的學生接觸到了計算機。當時所有的電腦使用需要編寫自定義軟件,這是只有科學家和數學家傾向於做的事情。二十世紀八十年代,它在家用微型計算機上變得普遍,現在在少數大幅演變的語言中仍然流行。

高級語言——COBOL

COBOL (COmmon Business Oriented Language) 是一個上世紀60年代出現的高級編程語言,並仍然用於業務應用。它廣泛應用於金融服務行業使用的基於大型機的應用。它使用類似英語語句的指令,並為程序設定了一個整體框架。COBOL 的設計目標是一種自文檔化的語言,可以方便地對其進行修改和維護。

高級語言——PL/1

Programming Language 1 是為科學、工程和業務應用程序設計的高級編程語言。它是最具特色的編程語言之一,也是最具功能豐富的一類中的第一個。它自上世紀60年代代初推出以來,已被各種學術、商業和工業用戶使用,至今仍在積極使用。它支持遞歸和結構化編程。語言語法是類似於英語的,適合描述復雜的數據格式,有一組廣泛的可用於驗證和操作的函數。

匯編語言的優點

了解匯編語言使人知道——

  • 程序是如何與操作系統 (OS)、處理器和BIOS交互的;
  • 數據是如何在內存和其他外部設備中表示的;
  • 處理器是如何訪問和執行指令的;
  • 指令是如何訪問和處理數據的;
  • 程序是如何訪問外部設備的。

使用匯編語言的其他優點是——

  • 它需要較少的內存和執行時間;
  • 它以更簡單的方式允許特定於硬件的復雜工作;
  • 它適用於追求效率的工作;
  • 它最適合編寫中斷服務例程和其他內存駐留程序。

個人計算機硬件的基本特點

PC 的主要內部硬件由處理器、內存和寄存器組成。寄存器是保存數據和地址的處理器組件。在執行程序時,系統會將其從外部設備復制到內部內存中。處理器執行程序指令。

計算機存儲的基本單元是位 (bit);它可以 ON (1),也可以是 OFF (0)。一組九個相關位組成一個字節,其中八位用於數據,最后一個用於奇偶校驗。根據奇偶校驗規則,每個是ON (1) 字節上的位數應該總是奇數。

因此,奇偶校驗位的應用使由比特組成的字節數是奇數。如果奇偶校驗是偶數,系統假定出現了奇偶校驗錯誤 (盡管很少見),這可能是由於硬件故障或電氣干擾造成的。

處理器支持以下數據大小——

  • 字(Word): 2 字節數據項
  • 雙字(Doubleword): 4 字節(32位)數據項
  • 四字(Quadword): 8 字節(64位)數據項
  • 段落(Paragraph): 16 字節(128位)數據項
  • 千字節(Kilobyte): 1024 字節
  • 兆字節(Megabyte): 1,048,576 字節

在內存中尋址數據

處理器控制指令執行的過程被稱為回遷—解碼—執行 (fetch-decode-execute) 周期或執行周期 (execution cycle)。它包括三連續的步——

  • 從內存中獲取指令
  • 解碼或識別指令
  • 執行指令

處理器一次可以訪問一個或多個字節的內存。讓我們考慮一個十六進制數字0725H。此數字將需要兩個字節的內存。高階字節或最有效字節為 07,低階字節為25。

處理器以反向字節序列存儲數據,即低序字節存儲在低內存地址和高內存地址中的高階字節中。因此,如果處理器將值0725H從寄存器帶到內存,它將首先將25傳輸到較低的內存地址,然后將07轉換為下一個內存地址。

x: 內存地址

當處理器將內存中獲取數字數據送往寄存器時,它再次反轉字節。有兩種內存地址——

  • 絕對地址 (Absolute address) ——特定位置的直接引用。
  • 段地址 (或偏移量) (Segment address (or offset)) ——具有偏移值的內存段的起始地址。

基本語法

匯編程序可分為三部分——

  • 數據 (data) 部分,
  • bss (Block Started by Symbol) 部分,以及
  • 文本 (text) 部分。

數據 (data) 部分

數據 (data) 用於聲明初始化的數據或常量。此數據在運行時不會更改。可以在本節中聲明各種常量值、文件名或緩沖區大小等。

聲明數據的語法是——

section.data

bss 部分

bss 用於聲明變量。聲明 bss 的語法是——

section.bss

文本 (text) 部分

文本 (text) 用於保留實際代碼。本部分必須以聲明 global _start 開始,它告訴內核程序執行的開始位置。

聲明文本的語法為——

section.text
   global _start
_start:

注釋

匯編語言注釋以分號 (😉 開頭。它可能包含任何可打印字符,包括空白。它可以出現在同一行,例如——

; 這個程序在屏幕上顯示一條信息

或者,與指示在同一行,如——

add eax, ebx     ; 添加 ebx 到 eax

匯編語言語句

匯編語言程序包括三種類型的語句——

  • 可執行指令或指令,
  • 匯編指令 (assembler directives) 或偽指令 (pseudo-ops), 以及
  • 宏 (Macros)。

可執行指令或簡稱指令告訴處理器該做什么。每個指令由一個操作代碼 (operation code) (opcode) 組成。每個可執行指令生成一台計算機語言指令。

匯編程序指令 (assembler directives) 或偽指令 (pseudo-ops) 告訴匯編程序關於匯編過程的各個方面。這些是不可執行的,不生成機器語言指令。

(Macros) 基本上是一種文本替換機制。

匯編語言語句的語法

匯編語言語句每行輸入一個語句。每個語句遵循以下格式——

[標簽(label)]   指令(mnemonic)   [操作數(operands)]   [;注釋(comment)]

方括號中的字段是可選的。基本指令有兩個部分,第一個是要執行的指令 (或助記鍵) 的名稱,第二個是命令的操作數或參數。

以下是典型匯編語言語句的一些示例——

INC COUNT        ; 增加內存變量 COUNT

MOV TOTAL, 48    ; 將 48 傳入內存變量 TOTAL
					  
ADD AH, BH       ; 將 BH 寄存器的內容添加到 AH 寄存器中
					  
AND MASK1, 128   ; 對變量 MASK1 和 128 執行 AND 操作
					  
ADD MARKS, 10    ; 將 10 添加到變量 MARKS 中

MOV AL, 10       ; 將值 10 轉移到 AL 寄存器

內存分段 (Memory Segments)

分段內存模型將系統內存划分為位於段寄存器中的指針所引用的獨立段組。每個段都用於包含特定類型的數據。一個段用於包含指令代碼,另一個段存儲數據元素,第三個段保留程序堆棧。

根據上述討論,我們可以將各種內存段指定為——

  • 數據段 (Data segment) ——它由 .data.bss 表示。.data 部分用於聲明內存區域,其中數據元素存儲在該程序中。在聲明數據元素后,此部分不能展開,並且在整個程序中保持靜態。

    .bss 部分也是靜態內存部分,其中包含要在程序中稍后聲明的數據的緩沖區。此緩沖區內存為零填充。

  • 代碼段 (Code segment) ——它由 .text 表示。這定義內存中存儲指令代碼的區域。這也是一個固定的區域。

  • 堆棧 (Stack) ——此段包含傳遞給程序中的函數和過程的數據值。

內存地址

在計算中,內存地址是對不同級別的軟件和硬件所使用的特定內存位置的引用。內存地址是固定長度的數字序列,通常以無符號整數的形式顯示和操作。這樣的數字語義基於 CPU (如指令指針和增量地址寄存器) 的特性,以及內存的使用,如由各種編程語言支持的數組。

內存地址類型

物理地址

數字計算機的主內存由許多內存位置組成。每個內存位置都有一個物理地址(一個代碼)。CPU (或其他設備) 可以使用代碼訪問相應的內存位置。通常只有系統軟件,即 BIOS、操作系統和一些專門的實用程序 (如內存測試器),內存控制器使用機器代碼操作數或處理器寄存器來尋址物理內存,指示 CPU 引導硬件設備,用內存總線或系統總線,或單獨的控制地址和數據總線,以執行程序的命令。內存控制器總線由多個並行行組成,每個平行線由二進制數字 (位) 表示。因此,尋址存儲單元的數量,以及每個單元中的比特數,在計算機之間會有所不同。

邏輯地址

計算機程序使用內存地址來執行機器代碼,並存儲和檢索數據。在早期的計算機邏輯和物理地址對應,但自引入虛擬內存后,大多數應用程序對物理地址一無所知。而是使用計算機的內存管理單元和操作系統內存映射來處理邏輯地址或虛擬地址。

Virtual_address_space_and_physical_address_space_relationship_zh-CN

應用程序編程中的地址空間

在現代多任務環境中,應用程序進程通常在其地址空間中包含以下類型的內存塊:

  • 機器代碼,包括:
    • 程序本身的代碼 (曾稱為代碼段 (code segment) 或文本段 (text segment));
    • 共享庫 (shared libraries)。
  • 數據,包括:
    • 初始化數據 (數據段 (data segment));
    • 未初始化 (但已分配) 變量;
    • 運行時堆棧 (run-time stack);
    • 堆 (heap);
    • 共享內存和內存映射文件。

地址空間的某些部分可能根本沒有映射。

本文大部分資料來自網絡,本人對這些資料進行了總結,將課堂內容進行了擴充,有些方面翻譯欠佳,敬請諒解。點擊這里可以查看英文原版
附:在博客園中使用Markdown


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM