簡體   English   中英

了解aarch64匯編function調用,棧是如何操作的

[英]understanding aarch64 assembly function call, how is stack operated

test.c(裸機)

#include <stdio.h>

int add1(int a, int b)
{
int c;
c = a + b;
return c;
}

int main()
{
int x, y, z;
x = 3;
y = 4;
z = add1(x,y);
printf("z = %d\n", z);
}

我做aarch64-none-elf-gcc test.c -specs=rdimon.specs並得到 a.out。 我做aarch64-none-elf-objdump -d a.out並得到了匯編代碼。 這里主要是function。

00000000004002e0 <add1>:
  4002e0:   d10083ff    sub sp, sp, #0x20       <-- reduce sp by 0x20 (just above it are saved fp and lr of main)
  4002e4:   b9000fe0    str w0, [sp, #12]       <-- save first param x at sp + 12
  4002e8:   b9000be1    str w1, [sp, #8]        <-- save second param y at sp + 8
  4002ec:   b9400fe1    ldr w1, [sp, #12]       <-- load w1 with x
  4002f0:   b9400be0    ldr w0, [sp, #8]        <-- load w0 with y
  4002f4:   0b000020    add w0, w1, w0          <-- w0 = w1 + w0
  4002f8:   b9001fe0    str w0, [sp, #28]       <-- store x0 to sp+28
  4002fc:   b9401fe0    ldr w0, [sp, #28]       <-- load w0 with the result (seems redundant)
  400300:   910083ff    add sp, sp, #0x20       <-- increment sp by 0x20
  400304:   d65f03c0    ret
0000000000400308 <main>:
  400308:   a9be7bfd    stp x29, x30, [sp, #-32]!   <-- save x29(fp) and x30(lr) at sp - 0x20
  40030c:   910003fd    mov x29, sp                 <-- set fp to new sp, the base of stack growth(down)
  400310:   52800060    mov w0, #0x3                    // #3
  400314:   b9001fe0    str w0, [sp, #28]           <-- x is assigned in sp + #28
  400318:   52800080    mov w0, #0x4                    // #4
  40031c:   b9001be0    str w0, [sp, #24]           <-- y is assiged in sp + #24
  400320:   b9401be1    ldr w1, [sp, #24]            <-- load func param for y
  400324:   b9401fe0    ldr w0, [sp, #28]           <-- load func param for x
  400328:   97ffffee    bl  4002e0 <add1>           <-- call main1 (args are in w0, w1)
  40032c:   b90017e0    str w0, [sp, #20]           <-- store x0(result z) to sp+20
  400330:   b94017e1    ldr w1, [sp, #20]           <-- load w1 with the result (why? seems redundant. it's already in w0)
  400334:   d0000060    adrp    x0, 40e000 <__sfp_handle_exceptions+0x28>
  400338:   91028000    add x0, x0, #0xa0  <-- looks like loading param x0 for printf
  40033c:   940000e7    bl  4006d8 <printf>
  400340:   52800000    mov w0, #0x0                    // #0 <-- for main's return value..
  400344:   a8c27bfd    ldp x29, x30, [sp], #32  <-- recover x29 and x30 (look's like values in x29, x30 was used in the fuction who called main)
  400348:   d65f03c0    ret
  40034c:   d503201f    nop

我用<--標記添加了我的理解。 有人可以看到代碼並給我一些更正嗎? 任何小的評論將不勝感激。 (請參閱<main>

補充:感謝您的評論。 我想我忘了問我真正的問題。 在 main 的開頭,調用 main 的程序應該把它的返回地址(在 main 之后)放在 x30 中。 由於 main 應該調用另一個 function 本身,它應該修改 x30,所以它將 x30 保存在它的堆棧中。 但是為什么它把它存儲在 sp-#0x20 中呢? 為什么變量 x,y,z 存儲在 sp + #20, sp + #24, sp + #28 中? 如果主 function 調用 printf,我猜 sp 和 x29 會減少一些。 這個數量是否取決於被調用函數(此處為 printf)使用多少堆棧區域? 還是恆定的? 以及 main 中的 x29、x30 存儲位置是如何確定的? 是否確定這兩個值位於被調用函數(printf)的堆棧區域上方? 抱歉問了太多問題。

在為main布置堆棧時,編譯器必須滿足以下約束:

  • x29x30需要保存在堆棧中。 它們每個占用 8 個字節。

  • 局部變量x,y,z需要堆棧空間,每個 4 字節。 (如果您正在優化,您會看到它們被保存在寄存器中,或者完全不存在優化。)這使我們總共有8+8+4+4+4=28個字節。

  • 堆棧指針sp必須始終保持對齊到 16 個字節; 這是一個架構和 ABI 約束(操作系統可以選擇放寬此要求,但通常不會)。 所以我們不能只從sp中減去 28; 我們必須四舍五入到 16 的下一個倍數,即 32。

這就是您提到的 32 或0x20的來源。 請注意,它完全適用於main本身使用的堆棧 memory。 它不是一個普遍的常數。 如果您從main添加或刪除了足夠多的局部變量,您會看到它發生了變化。

它與printf需求無關。 如果printf需要堆棧空間來存放它自己的局部變量,那么printf中的代碼將不得不相應地調整堆棧指針。 編譯main時的編譯器不知道會有多少空間,也不在乎。

現在編譯器需要在它將為自己創建的 32 字節堆棧空間內組織這五個對象x29, x30, x, y, z 除了以下幾點之外,放置什么的選擇幾乎完全是任意的。

該函數的序言需要從堆棧指針中減去 32,並將寄存器x29, x30存儲在分配空間內的某個位置。 這一切都可以在一條指令中使用預索引存儲對指令stp x29, x30, [sp, #-32]! . 它從sp中減去32 ,然后將x29x30存儲在從sp現在指向的地址開始的 16 個字節中。 因此,為了使用該指令,我們必須接受將x29x30放置在分配空間的底部,相對於sp值偏移[sp+0][sp+8] 將它們放在其他任何地方都需要額外的說明並且效率較低。

(實際上,因為這是最方便的方法,所以ABI實際上要求堆棧幀以這種方式設置, x29, x30在堆棧上按順序連續,當它們被使用時(5.2.3) .)

我們還有從[sp+16]開始的 16 個字節可供使用,其中必須放置x,y,z 編譯器選擇將它們分別放在地址[sp+28], [sp+24], [sp+20]處。 [sp+16]處的 4 個字節仍未使用,但請記住,我們必須在某處浪費 4 個字節才能獲得正確的堆棧 alignment。 安排這些對象的選擇,以及讓哪個插槽不用,完全是任意的,任何其他安排都可以。

暫無
暫無

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

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