簡體   English   中英

(ARM 程序集/C)將 C 函數轉換為 ARM 程序集?

[英](ARM Assembly/C) Converting C functions to ARM assembly?

本季度我正在使用 ARM 組件 class 並且我無法完全理解它。 明天有一個實驗室,我們可以在實驗室中搶占先機。 本實驗的任務是將以下 C 函數轉換為匯編:

int32_t Less1(int32_t a)
    {
    return a - 1 ;
    }

int32_t Add(int32_t a, int32_t b)
    {
    return a + b ;
    }

int32_t Square2x(int32_t x)
    {
    return Square(x + x) ;
    }

int32_t Last(int32_t x)
    {
    return x + SquareRoot(x) ;
    }

以下是具體說明:
您的任務是為這些 C 函數中的每一個創建匯編語言替換...函數 Square 和 SquareRoot 在主程序中提供。

我們提供了一個主程序,如果需要,我可以提供全部或部分。 我不理解其中的 90%,而且我不希望它有很多專門用於使功能顯示在帶有觸摸屏的測試板上。 它還具有 square 和 squareroot 函數,因為看起來匯編沒有這些操作。 我不確定我是否正確調用它們,但它們被命名為“Square”和“Squareroot”。

這是我在 ARM 程序集中寫的:

Add: PUSH {LR}
     MOV r0, a
     MOV r1, b
     ADD r2, r1, r0
     BX r2

Less1: PUSH {LR}
       MOV r0, a
       MOV r1, 1
       SUB r2, r0, r1
       BX r2

Square2x: PUSH {LR}
          MOV r0, x
          MOV r1, r0
          ADD r2, r0, r1
          Square r3, r2
          BX r3

Last: PUSH {LR}
      MOV r0, x
      Squareroot r1, r0
      ADD r2, r0, r1
      BX r2

我不知道這是否正確,因為我知道 C++ 並且剛剛開始組裝,所以我很感激任何輸入。 我還沒有完全理解寄存器和指令,但這是我根據我的教科書和我可以在網上找到的內容。

謝謝!

您正在使用哪個 ARM 指令集,根據您的代碼片段,它是 ARM(armv7 或更早版本)。 ARM 或拇指指令

int32_t Add(int32_t a, int32_t b)
    {
    return a + b ;
    }

我會讓你嘗試godbolt或命令行編譯器等。老師必須知道你可以訪問互聯網和工具。 但是你最好能夠理解和保護編譯器的代碼,否則它只是抄襲,它會變得很明顯。

所以 int32_t 表示 32 位,即寄存器的大小。 編譯語言具有“調用約定”或有時是 abi(應用程序二進制接口)。 基本上每個 function 都有一套規則。 第一個參數以這種方式傳遞,特定類型有一些例外。 第二個參數以這種方式傳遞,部分基於第一個及其類型,依此類推。 以這種方式處理返回值。

有指令集的東西,比如調用 function(查找 bl)將返回地址放在鏈接寄存器中,r14 所以你通常但不限於使用 bx lr 返回,它將是 bx 的東西,有些情況下它不是 lr,而是 lr 中的內容。

如果 function a 調用 function b,則返回 function a 將在鏈接寄存器中(假設只有一個鏈接寄存器)。 if b calls function c though that changes the link register to return to function b, how do we get back to function a? 您將鏈接寄存器保存在堆棧中並將其彈出。 您添加到堆棧中的所有內容都需要在返回之前刪除。

Add function 是否調用另一個 function? (no) 那是需要使用堆棧來保存鏈接寄存器的第一個測試。 Add function 是否在任何時候都有多個中間變量在運行? 這可能需要其中一些保留在堆棧上。 (不)

您可能不需要使用堆棧來添加 function,並不意味着您不能,非常歡迎您使用。

我會告訴你 arm 編譯器我用於 function 像這樣,這兩個參數是使用寄存器傳遞的,你可以弄清楚哪些是你分配的一部分,我將它們稱為 ra 和 rb。

所以你需要一個 label 它依賴於匯編語言(匯編程序,工具,而不是目標)所以它可能有也可能沒有冒號作為例子

Add:
   ...
   bx lr 

我給你的bx lr

在中間你需要添加兩個數字

rc = ra + rb

也許

ra = ra + rb

您需要弄清楚輸入寄存器名稱和 output 寄存器名稱(它是一個寄存器,而不是我在 ARM 上看到的 C 編譯器的堆棧)。

所以這將是類似的東西

Add:
   rc = ra + rb (a + b) 
   rd = rc      (put the result in the return register) 
   bx lr

你也許可以優化它,你必須弄清楚那些指令和寄存器是什么。 以及這些指令的規則。

執行 Add function 后,減法應該更容易。

int32_t Square2x(int32_t x)
    {
    return Square(x + x) ;
    }

它是否調用了 function,是的,那么這對於保留返回地址意味着什么? 這應該定義您的 function 的骨架或框架。

在調用 function 之前,您需要處理 x + x。 正如您所期望的那樣,調用約定有一個特定的寄存器,x 每次都會出現在這樣的 32 位參數中。 這與用於調用 Square2X 以及 Square 以及 Less1 和 Last 以及要添加的兩個操作數之一的寄存器相同。 因此,如果我調用該寄存器 rx,那么在調用 Square 之前,您需要計算 rx = rx + rx 是嗎? 或者還有另一種方法可以給出相同的結果。 然后你打電話給Square。 請注意,您可以在此處優化並節省一些東西。

int32_t Last(int32_t x)
    {
    return x + SquareRoot(x) ;
    }

您正在調用 function,它會觸發一些代碼。 您將傳入的 x 傳入 function 調用,可能不需要移動或修改。 但我會告訴你,基於我所知道的約定的特定寄存器可以被稱為 function 修改。 因此,當 SquareRoot 返回時,該 x 寄存器可能不再包含 x。 那么在調用 SquareRoot 之前如何保存它以供以后使用,以便將其添加到從 SquareRoot 返回的結果中?

從 Add 和 Less1 中,您應該已經知道像這樣的單個 32 位參數的傳入寄存器以及這樣的結果的返回寄存器,讓我們假設 SquareRoot 被傳遞並返回一個 int32_t 否則這會變得更加困難. 所有函數都使用相同的規則,因此您知道 x 傳遞給 SquareRoot 的寄存器,並且知道它返回的寄存器。因此您需要弄清楚如何保留傳遞給 Last 的 x,以便以后添加它。 您已經保存了另一個被弄亂的寄存器,您需要稍后保存。 但是你會看到編譯器可能會改變他們如何做到這一點以避免額外的一兩條指令。 根據 ARM 指令集,這個應該是 5。

添加您正在尋找兩個說明。

Less1、兩條指令

Square2X 先傳四條指令。 我想你可以做這兩個。

最后,五個指令

根據指令集和架構版本,其中一些可能會更多。

您不需要將參數一一加載到寄存器中。

因為它在通過 arguments 時自動設置在寄存器(使用 r0-r3)。

例如:

int32_t Add(int32_t a, int32_t b)
{
  return a + b ;
}

a自動設置為r0 , b 自動設置為r1

這是添加 function 的示例:

Add: stmfd sp!,{lr}
     ADD r0, r0, r1 // return value store into r0
     ldmfd sp!,{lr}
     mov pc,lr

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM