x64呼叫約定是由硬體的彙編指令call和ret的微指令和軟體的彙編指令規範共同完成的
一般為如下順序
父函式引數入棧(軟體彙編**)
父函式call(硬體微指令)
子函式棧建立(軟體彙編**)
子函式棧清理(軟體彙編**)
子函式ret(硬體微指令)
父函式棧清理(軟體彙編**)
下文中將演示**f(a1, a2, a3, a4, ..., an-1, an)
和a.f(a1, a2, a3, a4, ..., an-1, an)
在不同的呼叫約定下, 棧的變化過程
其中, 用數字表示以上的6個階段, 其後緊接著的是該階段結束後的棧的狀態和暫存器引數的示意
"["表示棧底, 處於位址高部, 由ebp/rbp暫存器的值直接決定, 其左邊緊貼著的值的位址為ebp+0/rbp+0, 每往右乙個引數位址遞減4/8
最右邊的引數由esp/rsp暫存器的值直接決定, 其位址為esp+0/rsp+0, 每往左乙個引數位址遞增4/8
"_"表示任意值
call指令只有一種, 因此1到2的變化都是一樣的
ret指令有兩種, 一種只出棧eip, 另一種不僅出棧eip, 還令esp增加乙個數(即清理棧)
每個引數大小為4b
傳參暫存器: 無
[, …, an, an-1, …, a4, a3, a2, a1
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
…, an, an-1, …, a4, a3, a2, a1, 上級eip, 上級ebp [
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
[, …
[, …
返回值暫存器: eax
傳參暫存器: 無
[, …, an, an-1, …, a4, a3, a2, a1
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
…, an, an-1, …, a4, a3, a2, a1, 上級eip, 上級ebp [
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
[, …, an, an-1, …, a4, a3, a2, a1
[, …
返回值暫存器: eax
傳參暫存器: edx=a2, ecx=a1
[, …, an, an-1, …, a4, a3
[, …, an, an-1, …, a4, a3, 上級eip
…, an, an-1, …, a4, a3, 上級eip, 上級ebp [, a2, a1
[, …, an, an-1, …, a4, a3, 上級eip
[, …
[, …
返回值暫存器: eax
略(用到時再補充試驗)
傳參暫存器: ecx=this
[, …, an, an-1, …, a4, a3, a2, a1
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
…, an, an-1, …, a4, a3, a2, a1, 上級eip, 上級ebp [, this
[, …, an, an-1, …, a4, a3, a2, a1, 上級eip
[, …
[, …
返回值暫存器: eax
每個引數大小為8b
傳參暫存器: r9d=a4, r8d=a3, rdx=a2, rcx=a1
[, …, an, an-1, …, a6, a5, _, _, _, _
[, …, an, an-1, …, a6, a5, _, _, _, _, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1
[, …, an, an-1, …, a6, a5, _, _, _, _
返回值暫存器: eax
父函式不能假定子函式一定給a1到a4在記憶體中預留的空間賦了值, 故應為任意值
注: 當引數數少於4時, 依然要在呼叫棧留下32b的空間, 即
[, …, _, _, _, _
[, …, _, _, _, _, 上級eip
[, …, _, a3, a2, a1, 上級eip
[, …, _, a3, a2, a1, 上級eip
[, …, _, a3, a2, a1
[, …, _, _, _, _
當引數含__m128型資料時, 使用對應的xmm暫存器傳參, 同時應將呼叫約定改為__vectorcall
傳參暫存器: r9d/xmm3=a4, r8d/xmm2=a3, rdx/xmm1=a2, rcx/xmm0=a1
[, …, an, an-1, …, a6, a5, _, _, _, _
[, …, an, an-1, …, a6, a5, _, _, _, _, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, a2, a1
[, …, an, an-1, …, a6, a5, _, _, _, _
返回值暫存器: eax/xmm0
視具體情況, 第3步可能會騰出空間在記憶體中暫存資料, 如
傳參暫存器: r9d=a4, r8d=a3, xmm1=a2, xmm0=a1
[, …, an, an-1, …, a6, a5, _, _, _, _
[, …, an, an-1, …, a6, a5, _, _, _, _, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, &a2, &a1, 上級eip, _, a2(高位), a2(低位), a1(高位), a1(低位)
[, …, an, an-1, …, a6, a5, a4, a3, &a2, &a1, 上級eip
[, …, an, an-1, …, a6, a5, a4, a3, _, _
[, …, an, an-1, …, a6, a5, _, _, _, _
傳參暫存器: r9d/xmm3=a3, r8d/xmm2=a2, rdx/xmm1=a1, rcx/xmm0=this
[, …, an, an-1, …, a5, a4 _, _, _, _
[, …, an, an-1, …, a5, a4, _, _, _, _, 上級eip
[, …, an, an-1, …, a5, a4, a3, a2, a1, this, 上級eip
[, …, an, an-1, …, a5, a4, a3, a2, a1, this, 上級eip
[, …, an, an-1, …, a5, a4, a3, a2, a1, this
[, …, an, an-1, …, a5, a4, _, _, _, _
返回值暫存器: eax/xmm0
相當於this成了原第乙個引數的__fastcall或__vectorcall
i386的頁機制
i386cpu不僅有段機制,而且支援頁機制。乙個32位的邏輯位址經過段機制對映成線性位址後,還要經過頁機制對映成32位的邏輯位址。與頁機制有關的暫存器有 cr3,cr0 cr0的最高位pg是頁對映機制的總開關,如果pg位是1則開啟頁對映機制。cr3暫存器用來存放頁面目錄的首位址。頁面目錄dir,10...
i386和i686的區別
i386和i686 現在所有的intel 32位體系 包括amd等相容cpu 都叫i386體系,包括p4。i686仍然屬於i386體系,不過對cpu 相對於386 的特性作了指令優化。gnu linux分為alpha powerpc sun等各個不同版本,所有從intel386 p4都用i386版本...
i386段式記憶體管理
1 intel x86 cpu段式記憶體管理 1 在保護模式下改變段暫存器的功能,使其從乙個單純的基位址變成向這樣乙個資料結構的指標。這樣,當一條訪問記憶體的指令發出乙個記憶體位址時,cpu就可以這樣來歸納出實際應該放上資料 a.根據指令的性質來確定應該使用哪乙個段暫存器,例如轉移指令中的位址在 段...