簡體   English   中英

處理器如何知道從堆棧中讀取多少函數參數(x64)

[英]How does processor know how much to read from the stack for function parameters (x64)

我有一個在 x64 上運行的小程序調用系統函數,其參數足夠長,這意味着據我所知,他將被推送到堆棧上運行。

#include <stdlib.h>

int main(void) {
    char command[] = "/bin/sh -c whoami";
    system(command);
    return EXIT_SUCCESS;
}

當我在 GDB 中檢查正在發生的事情時,我可以確認我的參數在 2 個字的堆棧上。

在此處輸入圖像描述

我想知道 CPU 是如何知道它需要讀取 2 個單詞並且之后不再繼續的。 什么將函數參數與其余參數分隔?

我在處理緩沖區溢出時問這個問題,雖然我在堆棧上遇到同樣的情況,但 CPU 只選擇一個詞(/bin/sh)而不是我想要的兩個詞。 輸出sh: line 1: $'Ћ\310\367\377\177': command not found

在此處輸入圖像描述

處理器如何知道從堆棧中讀取多少函數參數(x64)

CPU不知道。 我的意思是,它沒有收到一條指令說“從堆棧中檢索下一個參數,無論大小可能是什么。” 它接收指令以從特定位置檢索特定大小的數據,並對該數據進行操作,或將其放入寄存器中,或將其存儲在其他位置。 這些指令是由編譯器根據程序源代碼生成的,它們是程序二進制文件的一部分。

我想知道 CPU 是如何知道它需要讀取 2 個單詞並且之后不再繼續的。 什么將函數參數與其余參數分隔?

沒有任何東西可以將一個函數參數與下一個函數參數分隔——既不在堆棧上,也不在一般情況下。 程序(通常)不會通過內省數據來即時計算出這些事情。 相反,函數需要以特定方式設置參數,該方式由一組稱為“應用程序二進制接口”(ABI) 的約定管理,並且它們在數據確實以這種方式設置的假設下運行。 如果這些假設被證明是無效的,那么或多或少都會發生任何事情。

我在處理緩沖區溢出時問這個問題,雖然我在堆棧上遇到同樣的情況,但 CPU 只選擇一個詞(/bin/sh)而不是我想要的兩個詞。

函數將從堆棧中消耗的字數及其賦予它們的重要性是函數的特征,而不是(通常)堆棧上的數據。

取決於為函數實現的調用約定 通過指定 none,您可以讓編譯器做出決定,並且它可以發揮創意,有時甚至會因為分支預測優化而因任何顯式call而消失,否則您可以從大量指定這些調用約定如何指定的文檔源中准確地了解期望什么應該工作。

處理器非常非常愚蠢。 他們全部。 這就像問你如何駕駛火車......你沒有。 它只是跟隨軌道。 處理器只是跟隨它前面的位,如果它們是錯誤的或做壞事,那么處理器就會崩潰,就像如果軌道壞了火車會脫軌一樣。

變量的大小不是由處理器類型、x86、arm 等決定的。對於 C 也不是由語言決定的,x86 的 int 的大小不假定為一種大小。 像這樣的假設是不好的。 編譯器作者為該目標選擇該編譯器。 並且沒有理由假設同一目標處理器的任何兩個 C 編譯器使用相同的大小。

同樣,編譯器作者最終決定調用約定,寄存器中的內容,堆棧中的內容,堆棧中的順序,寄存器等。

編譯器作者還選擇堆棧的對齊或不對齊。

編譯器作者選擇使用或不使用堆棧幀或允許用戶選擇,但在任一選擇中,有或沒有仍然選擇如何使用堆棧或堆棧指針。

編譯器作者使用他們的調用約定、他們對變量大小的選擇等,然后作為編譯過程的一部分來決定使用哪些指令。 應根據上述選擇來選擇說明。 因此,一個兩字節大小的變量應該在堆棧中,這是基於編譯器根據編譯器選擇和可能的用戶選項相對於堆棧指針或堆棧幀指針做出的決定。

處理器不知道,它只是簡單地吸收比特並按照他們所說的去做,如果編譯器、匯編器和鏈接器已經完成了他們的工作,最終是程序員的責任,那么處理器就會按照它的指示去做,包括讀取正確數量的特定項目的字節。

由於在這個網站上被打死,檢查 main() 的堆棧往往會令人困惑,因為添加了神秘的填充,理想情況下你想用其他函數名編譯它並看到它。 編譯器選項也可以確定代碼的構建方式、使用的指令以及堆棧(如果有)。 優化級別。 沒有理由假設任何兩個編譯器都會從某個 C 源代碼生成相同的代碼,同樣沒有理由假設一個編譯器會根據編譯器選項生成相同的代碼。

所以堆棧在哪里,堆棧上有多少字節等是由程序員加上編譯器、匯編器和鏈接器的多層決定的。

暫無
暫無

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

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