首頁 >後端開發 >C++ >在彙編中重新建立 strlen 和 strcmp:逐步指南

在彙編中重新建立 strlen 和 strcmp:逐步指南

DDD
DDD原創
2024-11-26 16:54:11884瀏覽

Recreating strlen and strcmp in Assembly: A Step-by-Step Guide

在彙編中編寫低階函數可能看起來令人畏懼,但這是加深您對事物底層工作原理的理解的絕佳方法。在本部落格中,我們將用彙編語言重新建立兩個流行的 C 標準函式庫函數 strlen 和 strcmp,並學習如何從 C 程式中呼叫它們。

本指南適合初學者,所以如果您是彙編程式設計新手,請不要擔心。讓我們深入了解一下! ?


目錄

  1. 彙編和 C 整合簡介
  2. strlen 和 strcmp 是什麼?
  3. 設定您的環境
  4. 在彙編中編寫 strlen
  5. 在彙編中編寫strcmp
  6. 將彙編與 C 集成
  7. 編譯並運行程式
  8. 預期輸出
  9. 結論
  10. 在 Twitter 上聯繫

1.彙編與 C 整合簡介

組合語言的運作等級非常低,接近機器碼。與 C 等高階語言結合使用時,您將獲得兩全其美的效果:

  • 高水準的可讀性。
  • 低階控制和最佳化。

在本指南中,我們將在彙編中編寫兩個函數 - my_strlen 和 my_strcmp - 並從 C 呼叫它們來演示這種整合。


2. strlen 和 strcmp 是什麼?

  • strlen:此函數計算以 null 結尾的字串(以 結尾的字串)的長度。
  • strcmp:此函數逐個字元比較兩個字串。它返回:
    • 如果字串相同則為 0。
    • 如果第一個字串較小,則為負值。
    • 如果第一個字串較大,則為正值。

我們將在組裝中複製他們的行為。


3.設定您的環境

所需工具:

  1. NASM(Netwide Assembler):彙編彙編程式碼。
  2. GCC(GNU 編譯器集合):編譯和連結 C 和彙編程式碼。

安裝工具(Linux):

執行以下指令:

sudo apt update
sudo apt install nasm gcc

4.在組譯中寫strlen

strlen的邏輯:

  1. 從初始化為 0 的計數器開始。
  2. 讀取字串的每個字符,直到找到空終止符 ( )。
  3. 返回計數器作為長度。

my_strlen 的彙編程式碼:

sudo apt update
sudo apt install nasm gcc
  • 使用的暫存器:
    • RDI:指向輸入字串。
    • RAX:儲存字串長度(輸出)。

5.在組譯中寫strcmp

strcmp 的邏輯:

  1. 比較兩個字串的字元。
  2. 當字元不同或到達空終止符 ( ) 時停止。
  3. 回傳:
    • 如果字串相等則為 0。
    • ASCII 值的差異(如果它們不同)。

my_strcmp 的彙編程式碼:

section .text
global my_strlen

my_strlen:
    xor rax, rax           ; Set RAX (length) to 0
.next_char:
    cmp byte [rdi + rax], 0 ; Compare current byte with 0
    je .done               ; If 0, jump to done
    inc rax                ; Increment RAX
    jmp .next_char         ; Repeat
.done:
    ret                    ; Return length in RAX
  • 使用的暫存器:
    • RDI 和 RSI:指向輸入字串的指標。
    • RAX:儲存結果(輸出)。

6.將彙編與 C 整合

讓我們來寫一個呼叫這些彙編函數的 C 程式。

C 代碼:

section .text
global my_strcmp

my_strcmp:
    xor rax, rax           ; Set RAX (result) to 0
.next_char:
    mov al, [rdi]          ; Load byte from first string
    cmp al, [rsi]          ; Compare with second string
    jne .diff              ; If not equal, jump to diff
    test al, al            ; Check if we’ve hit <pre class="brush:php;toolbar:false">#include <stdio.h>
#include <stddef.h>

// Declare the assembly functions
extern size_t my_strlen(const char *str);
extern int my_strcmp(const char *s1, const char *s2);

int main() {
    // Test my_strlen
    const char *msg = "Hello, Assembly!";
    size_t len = my_strlen(msg);
    printf("Length of '%s': %zu\n", msg, len);

    // Test my_strcmp
    const char *str1 = "Hello";
    const char *str2 = "Hello";
    const char *str3 = "World";

    int result1 = my_strcmp(str1, str2);
    int result2 = my_strcmp(str1, str3);

    printf("Comparing '%s' and '%s': %d\n", str1, str2, result1);
    printf("Comparing '%s' and '%s': %d\n", str1, str3, result2);

    return 0;
}
je .done ; If
   nasm -f elf64 functions.asm -o functions.o
   gcc main.c functions.o -o main
   ./main
, strings are equal inc rdi ; Advance pointers inc rsi jmp .next_char ; Repeat .diff: sub rax, [rsi] ; Return difference .done: ret

7.編譯並執行程式

  1. 將組譯程式碼儲存到functions.asm。
  2. 將 C 程式碼儲存到 main.c。
  3. 編譯並連結它們:
Length of 'Hello, Assembly!': 17
Comparing 'Hello' and 'Hello': 0
Comparing 'Hello' and 'World': -15

8.預期輸出


9.結論

透過在彙編中編寫 strlen 和 strcmp,您可以更好地理解:

  • 低階記憶體操作。
  • 如何在機器層級處理字串。
  • 將彙編與 C 整合以利用兩種語言的優勢。

您希望看到在組譯中重新建立哪些其他 C 標準函式庫函數?請在下面的評論中告訴我!


10。在 Twitter 上聯絡

喜歡本指南嗎?在 Twitter 上分享您的想法或提出問題!讓我們一起聯繫並探索更多底層程式設計。 ?

以上是在彙編中重新建立 strlen 和 strcmp:逐步指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn