1. 程式人生 > >x86-64上的棧幀佈局

x86-64上的棧幀佈局

因為utilfunc僅有3個實參,呼叫它不要求棧使用,因為所有的實參都適用暫存器。另外,因為它是一個葉子函式,gcc選擇對其所有區域性變數使用紅區。這樣,無需減少rsp(隨後恢復)來為這些資料分配空間。

保留基地址指標

基地址指標rbp(以及x86上它的前身ebp),作為一個函式執行期間棧幀起始的一個穩定“錨點”,對手動反彙編程式碼以及除錯都十分便利[1]

不過,不久前,注意到編譯器生成的程式碼不是真正地需要它(編譯器很容易追蹤rsp的偏移),DWARF除錯格式提供了無需基地址指標訪問棧幀的方式(CFI)。

這是為什麼某些編譯器開始對進取的優化忽略基地址指標,因此縮短了函式的prologue與epilogue,並提供了多一個通用暫存器(記得嗎,在只有有限GPR的x86上這相當有用)。

Gcc在x86上預設保留基地址指標,但允許以-fomit-frame-pointer編譯選項進行優化。到底有多推薦使用這個選項是一個有爭議的問題——如果有興趣你可以google一下。

不管怎麼說,AMD64 ABI引入的另一個“革新”是使得基地址指標顯式可選,規定:

作為棧幀一個幀指標的%rbp的便利使用,可以通過使用%rsp(棧指標)索引棧幀來避免。這個技術在prologue與epilogue中節省了兩條指令,並使得另一個通用暫存器(%rbp)可用。

Gcc堅持這個建議,在以優化編譯上,在x64上預設忽略幀指標。通過提供-fno-omit-frame-pointer選項,給出了保留它的一個選擇。 為了清晰起見,上面顯示的棧幀的生成沒有忽略幀指標。

Windows x64 ABI

在x64上Windows實現自己與ADM64ABI稍有不同的版本。我將只是簡單地討論Windowsx64 ABI,談論它的棧幀與AMD64的如何不同。以下是主要的差別:

1.      僅4個整數/指標實參在暫存器中傳遞(rcx,rdx,r8,r9)。

2.      沒有紅區的概念。事實上,這個ABI明確宣告rsp以下區域被視為volatile,使用是不安全的。作業系統、偵錯程式或中斷處理控制代碼可能改寫這個區域。

3.      作為替代,由呼叫者在每個棧幀中提供了一個“暫存器引數區”[2]。在呼叫一個函式時,在返回地址之前,在棧上最後分配的是用於至少4個暫存器(每個8位元組)的空間。這個區域對被呼叫者可用,而無需顯式地分配它。這對可變引數函式以及除錯(提供引數已知的位置,與此同時暫存器可能重用於其他目的)是有用的。儘管這個區域最初的設想是用作濺出在暫存器中傳遞的4個引數,現在編譯器也為其他優化目的而使用它(例如,如果函式的區域性變數需要少於32位元組的棧空間,可以使用這個區域,而無需觸碰rsp)。

在Windows x64 ABI中進行的另一個重要的改變是呼叫慣例的清理。不再有cdecl/stdcall/fastcall/thiscall/register/safecall這些瘋狂的存在——只有一個“x64呼叫慣例”。為此歡呼!

關於此及Windows x64 ABI其他方面的更多資訊,下面是一些好的連結:

·        關於x64軟體約定的官方的MSDN頁面——組織良好的資料,個人認為比AMD64ABI文件更容易理解。


[1] 因為在一個函式裡,rbp總是指向前一個棧幀,它形成了棧幀的一種連結串列,在任何時候偵錯程式可以用來訪問棧執行追蹤(在core dump中也一樣)。

[2]有時也稱為“” called "home space" sometimes.

相關推薦

x86-64佈局

因為utilfunc僅有3個實參,呼叫它不要求棧使用,因為所有的實參都適用暫存器。另外,因為它是一個葉子函式,gcc選擇對其所有區域性變數使用紅區。這樣,無需減少rsp(隨後恢復)來為這些資料分配空間。 保留基地址指標 基地址指標rbp(以及x86上它的前身ebp),作為一個函式執行期間棧幀起始的一個穩定“

x86-64佈局分佈

A few months ago I’ve written an article named Where the top of the stack is on x86, which aimed to clear some misunderstandings

ARMv8架構下程式執行時佈局

結合ARM相關文件和在飛騰機器上使用gdb除錯實際程式來研究ARM的指令和執行時棧幀佈局。主要參考了三篇文件。 1. Procedure Call Standard for the ARM 64-bit Architecture。參考其中的過程呼叫標準和執行時棧幀佈局。 2

x86-64 下函式呼叫及原理

一蓑一笠一扁舟,一丈絲綸一寸鉤。 一曲高歌一樽酒,一人獨釣一江秋。 —— 題秋江獨釣圖 緣起 在 C/C++ 程式中,函式呼叫是十分常見的操作。那麼,這一操作的底層原理是怎樣的?編譯器幫我們做了哪些操作?CPU 中各暫存器及記憶體堆疊

X86-64暫存器和

概要 說到x86-64,總不免要說說AMD的牛逼,x86-64是x86系列中集大成者,繼承了向後相容的優良傳統,最早由AMD公司提出,代號AMD64;正是由於能向後相容,AMD公司打了一場漂亮翻身戰。導致Intel不得不轉而生產相容AMD64的CPU。這是IT行業以弱勝強的經典戰役。不過,大家為了名稱延續性

X86-64和ARM64用戶的結構 (2) ---進程用戶的初始化

.com roc mis goto war dump images thread prepare 用戶進程棧的初始化 在進程剛開始運行的時候,需要知道運行的環境和用戶傳遞給進程的參數,因此Linux在用戶進程運行前,將系統的環境變量和用戶給的參數保存到用戶虛擬地址空間的棧中

X86-64和ARM64用戶的結構 (3) ---_start到main

perf 分享 51cto down $0 inpu nts vpd ges _start到main()函數之間的棧 介紹將以如下函數為例: #include<stdio.h> #include <stdlib.h> int func_A(int

X86-64和ARM64用戶的結構 (0) ---目錄

結構 .com star 之間 介紹 進程 () x86-64 code X86-64和ARM64用戶棧的結構 (1) ---背景介紹 X86-64和ARM64用戶棧的結構 (2) ---進程用戶棧的初始化 X86-64和ARM64用戶棧的結構 (3) ---_start

-運算元資料區,分配

運算元棧主要用於儲存計算過程的中間結果,同時作為計算過程中變數臨時的儲存空間。 運算元棧也是先進後出的資料結構。 幀資料區: 除了區域性變量表和運算元棧,java棧還需要一些資料來支援常量池解析,正常方法返回和異常處理等,大部分java位元組碼指令需要進行常量池訪問,在

從IA32到X86-64的擴充套件所導致的函式傳參模型的變化

先來看一段小程式 #include <stdio.h> int main(){ float f = 2.5; int i = 2; printf("%d\n%f\n%d\n%f\n\n", f, f, i, i); //printf("%d\n%f\n

溢位攻擊系列:shellcode在linux x86 64位攻擊獲得root許可權(三)linux下程序中的多使用者

在linux程序中會存在兩個使用者狀態,一種是實際使用者ID, 一種是有效使用者ID 實際使用者ID uid, 就是我是誰,也就是你在操作時候的使用者ID, 通常你可以用命令id 來檢視自己的資訊 >id uid=1005(raintung) gid=100(use

x86 常見呼叫約定(cdecl,fastcall,stdcall) & x86和ARM呼叫約定的分析 & ARM ATPCS(ARM-THUMB procedure call standard)

#PS:要轉載請註明出處,本人版權所有 #PS:這個只是 《 我自己 》理解,如果和你的 #原則相沖突,請諒解,勿噴 由於某些工作的需要,我需要掌握X86以及ARM的一些呼叫規則,讓自己可以大致看懂ASM程式碼。於是,我總結了一下我需要的東西

溢位攻擊系列:shellcode在linux x86 64位攻擊獲得root許可權(二)shellcode

shellcode 是一組指令opcode, 是可以被程式執行,因為shellcode是要直接操作暫存器和函式,所以opcode 必須是十六進位制的形式。 既然是攻擊,那shellcode 主要的目的是呼叫系統函式,而在x86下 在linux下有兩種方式。 第一種是通過直接

在Eclipse除錯C++程式報錯:x86-64 is not compatible with target architecture i386.

背景:  在windows上使用Eclipse上除錯C++程式。 程式出錯如下: warning: `/cygdrive/c/Windows/SYSTEM32/ntdll.dll': Shared library architecture i386:x86-64 is n

表達式求值(數據結構書的應用之中的一個)

ble code 進行 。。 bre atoi 麻煩 scanf ios 主要內容:表達式求值。提交nyoj通過。。。 思路:主要就是一個開兩個棧,然後一個操作符棧。一個操作數棧。。 我的代碼例如以下(比較簡潔): /***** Author Gery *

如何在w7-64安裝postgresql-9.6.2-1-windows-x64

href 此外 分開 賬戶 需要 管理系統 輸入密碼 sys gem PostgreSQL安裝:一、windows下安裝過程安裝介質:postgresql-9.6.2-1-windows-x64(166M),安裝過程非常簡單,過程如下:1、開始安裝: 2、選擇程序安

各版本x86 / 64位MongoDB下載地址

.org x86 下載地址 ref god mon mongodb x86_64 inux 各版本x86 / 64位MongoDB下載地址: linux: http://dl.mongodb.org/dl/linux/x86_64 windows: http://dl.mo

函數的調用過程——

入棧 () stdio.h image 指向 span 下一條 之前 urn 今天我們來看一下函數的調用過程與棧幀。 我們通過一段簡單的代碼和圖示來介紹這個過程: #include<stdio.h> int add(int x,int y) { int

How a stack frame works

emp eight relative wid acc window img link temp http://en.citizendium.org/wiki/Stack_frame To use a stack frame, a thread keeps two point

計算機科學基礎知識(六)理解

符號 margin splay 參考文獻 gin wid sta div linux 一、前言 本文以一個簡單的例子來描述ARM linux下的stack frame。 本文也是對tigger網友問題的回復。 二、源代碼 #include <stdio.h>