iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
Security

picoCTF 刷題分享系列 第 27

picoCTF 刷題分享---Day 27(組語理論補足)

  • 分享至 

  • xImage
  •  

之前有次有個ARMv8的那篇讓我意識到自己的組語其實基底打得不好,所以趁這次補一下


先介紹一下assembly language:

Assembly language(組合語言),是一種介於高階語言與機器語言的低階語言。他會將要處理的機器碼
((machine code)0,1),以符號化表示。使得人類能更容易讀懂和編寫程式。他會針對特定的處理器架構進行設計,所以每一條指令( instruction )基本上都會對應到處理器的原生機械指令,針對特定的處理器架構進行設計。(大致先這樣概述)

架構依賴性

組合語言是架構依賴的,這意味著不同的硬體架構(如 x86, ARM, MIPS)會有不同的指令集。開發者在不同架構上使用組合語言時,必須熟悉該架構的寄存器配置、指令集和記憶體訪問方式。
以下是常見的架構與其應用的場合:

  • x86 組合語言:通常用於 Intel 或 AMD 的處理器。
  • ARM 組合語言:廣泛應用於移動裝置和嵌入式系統。
  • MIPS 組合語言:常用於嵌入式系統和學術研究。
  • RISC-V 組合語言:開放的指令集架構,受到嵌入式開發社群的關注,逐漸成為新興的架構選擇。

組合語言的特徵

  • 每行就代表一個指令,其格式為:mnemonic A , B 這樣就會完成每個動作了。
  //每行就代表一個指令,其格式為:mnemonic A, B。
  //例如:
  ADD R0, R1, R2 // 將 R1 和 R2 的值相加,結果存入 R0。
  • **符號化指令:**每一個機器指令會對應一個組合語言的符號,這些符號稱為助記符(mnemonic)。助記符通常表示指令的功能,EX: MOV 表示移動資料,ADD 表示加法運算。
  • **暫存器(Registers):**暫存器是處理器內部的高速儲存裝置,組合語言中很多操作都是在暫存器之間進行。每個架構的暫存器數量和名稱都不同。例如,ARM 架構使用 R0-R15 這樣的名稱,而 x86 使用 EAX, EBX 等。
  • **記憶體操作:**組合語言允許直接操作記憶體。指令如 LDR 和 STR(在 ARM 中)或 MOV(在 x86 中)可以讀取和寫入記憶體中的數據。通常,組合語言提供指令以加載(Load)或儲存(Store)資料到記憶體位置。
  • **條件執行:**有些架構允許指令根據條件執行。例如在 ARM 中,許多指令可以附加條件碼,如 EQ (equal), NE (not equal),允許某些指令在特定條件下執行。

組合語言的優點與缺點

  • 優點:

    • 高效能:組合語言能精確控制硬體資源,因此能夠撰寫非常高效的程式碼。
    • 靈活性:能夠直接操作硬體資源,適合處理對性能要求極高的應用,例如驅動程式、嵌入式系統開發。
    • 低階控制:開發者可以精確控制處理器內部資源,例如暫存器和記憶體的使用方式。
  • 缺點:

    • 複雜性:與高階語言相比,組合語言程式碼更難以理解與撰寫,因為它要求程式設計者深入了解硬體。
    • 可移植性低:組合語言是架構依賴的,在一種處理器上編寫的程式無法直接運行在另一種處理器上。
    • 維護成本高:由於其細節繁多且缺乏抽象,維護和修改大型的組合語言程式會相當困難。

語法

    // 1. 資料存取(Data Transfer)
    MOV R0, #5      // MOV (Move):將數據5移動到暫存器R0中
    STR R0, [R1]    // STR (Store Register):將暫存器R0的數據存入記憶體位置R1
    LDR R0, [R1]    // LDR (Load Register):從記憶體位置R1載入數據到暫存器R0

    // 2. 算術運算(Arithmetic Operations)
    ADD R0, R1, R2  // ADD (Add):將暫存器R1和R2中的值相加,結果存入R0
    SUB R0, R1, R2  // SUB (Subtract):將暫存器R1中的值減去R2中的值,結果存入R0
    MUL R0, R1, R2  // MUL (Multiply):將暫存器R1和R2中的值相乘,結果存入R0
    DIV R0, R1      // DIV (Divide):將暫存器R0中的值除以R1中的值,結果存入R0

    // 3. 邏輯運算(Logical Operations)
    AND R0, R1, R2  // AND (Logical AND):將暫存器R1和R2中的值按位與,結果存入R0
    ORR R0, R1, R2  // ORR (Logical OR):將暫存器R1和R2中的值按位或,結果存入R0
    EOR R0, R1, R2  // EOR (Exclusive OR):將暫存器R1和R2中的值按位異或,結果存入R0
    LSL R0, R1, #2  // LSL (Logical Shift Left):將暫存器R1中的值邏輯左移2位,結果存入R0
    LSR R0, R1, #2  // LSR (Logical Shift Right):將暫存器R1中的值邏輯右移2位,結果存入R0

    // 4. 比較與條件控制(Comparison and Conditional Control)
    CMP R0, R1      // CMP (Compare):比較暫存器R0與R1中的值,影響後續條件跳轉
    TST R0, R1      // TST (Test):對R0和R1進行按位與運算,僅影響標誌位,不改變暫存器值
    B label         // B (Branch):無條件跳轉到label位置繼續執行
    BL function_name// BL (Branch with Link):跳轉到子程序function_name並儲存返回地址
    BX LR           // BX (Branch and Exchange):跳轉到暫存器LR指示的地址,並可能切換處理器模式

    // 5. 堆疊操作(Stack Operations)
    PUSH {R0}       // PUSH (Push):將暫存器R0中的值壓入堆疊
    POP {R0}        // POP (Pop):從堆疊彈出數據到暫存器R0

在我們平常看到的語言裡eax, ebx...是屬於X86架構的通用變數名字,而R0,R1,R2則是ARM 架構的變數名字。
以下是更詳細的說明:

x86 架構(Intel/AMD 常見的桌面處理器架構)

  • 通用暫存器:
    • EAX、EBX、ECX、EDX:32 位元暫存器
    • RAX、RBX、RCX、RDX:在 x86-64 (64 位元) 中,它們的 64 位元對應
  • 指標暫存器:
    • RSP:堆疊指標(Stack Pointer),指向目前堆疊頂部
    • RBP:基底指標(Base Pointer),通常用來追蹤函數的呼叫框架
  • 其他暫存器:
    • RSI:源索引暫存器,用於字串操作
    • RDI:目的索引暫存器,用於字串操作

ARM 架構(應用於手機、嵌入式設備等)

  • 通用暫存器:
    • R0 到 R15:一般用途暫存器(依任務不同,如函數呼叫時 R0 可用來存放參數或返回值)
  • 特殊暫存器:
    • SP:堆疊指標(Stack Pointer)
    • LR:連結暫存器(Link Register),存放函數返回地址
    • PC:程式計數器(Program Counter),指向下一條將執行的指令

後記:
我知道各位讀得很痛苦,但其實一點都不輕鬆,一起加油慢慢搞懂吧,希望哪天可以用組語手搓一款小遊戲(我在發瘋別理我。


上一篇
picoCTF 刷題分享---Day 26(ELF理論補足)
下一篇
picoCTF 刷題分享---Day 28(組語理論補足)
系列文
picoCTF 刷題分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言