windows程式設計 x64呼叫約定

2022-03-05 16:05:00 字數 2933 閱讀 9187

windows32位程式包括stdcall,thiscall,fastcall,cdecl,clrcall,vectorcall,nakedcall等呼叫方式,x64位程式預設使用新的fastcall呼叫方式。

這種呼叫方式得益於x64平台暫存器數量的增加。  

空間大於8位元組的引數用參照傳遞,不能把乙個引數分割到多個暫存器中進行傳遞;前四個整型或指標型別引數從左到右由rcx,rdx,r8,r9依次傳遞,前四個浮點型別引數從左到右由xmm0,xmm1,xmm2,xmm3依次傳遞。第五個和其後的引數通過棧傳遞,引數從右到左一次入棧。

__m128 型別, 陣列和字串不能通過值傳遞,只能通過指標。

結構體和union如果大小是1,2,4,8位元組,用整數的傳參方式;否則通過指標傳遞。

小於等於64位的整型或指標型別返回值由rax傳遞。

浮點返回值由xmm0傳遞。

更大的返回值(比如結構體),由呼叫方在棧上分配空間,並由rcx持有該空間的指標並傳遞給被呼叫函式,因

此整型引數使用的暫存器依次右移一格,實際只可以利用3個暫存器,其餘引數入棧。函式呼叫結束後,rax返

回該空間的指標(就是rcx的值)。

varargs(可變引數)也通過上述方式進行傳參。

呼叫函式為前四個引數在呼叫棧上保留相應的空間,稱作shadow space或spill slot。即使被呼叫方沒有或小

於4個引數,呼叫函式仍然保留那麼多的棧空間,這有助於在某些特殊情況下簡化呼叫約定。

由呼叫函式負責清理呼叫棧。

除rcx,rdx,r8,r9以外,rax、r10、r11、xmm4 和 xmm5也是易變化的(volatile)暫存器。

rbx, rbp, rdi, rsi, r12, r14, r14, and r15暫存器則必須在使用時進行保護。

在暫存器中,所有引數都是右對齊的。小於64位的引數並不進行高位零擴充套件,也就是高位是無法**的垃圾資料.

引數傳遞示例

1

int func1(int a, int b, int c, int d, int e, double

f) 4

5int func2(int a, int b, int c, int d, int e, double f,int

g) 8

9int

main()

反彙編:

1

int r2 = func2(1, 2, 3, 4, 5, 6.6,7

);2 00007ff65f263d0e mov dword ptr [rsp+30h],7

300007ff65f263d16 movsd xmm0,mmword ptr [__real@401a666666666666 (07ff65f269bb0h)]

4 00007ff65f263d1e movsd mmword ptr [rsp+28h],xmm0

5 00007ff65f263d24 mov dword ptr [rsp+20h],5

6 00007ff65f263d2c mov r9d,4

7 00007ff65f263d32 mov r8d,3

8 00007ff65f263d38 mov edx,2

9 00007ff65f263d3d mov ecx,1

1000007ff65f263d42 call func2 (07ff65f261375h)

1100007ff65f263d47 mov dword ptr [r2],eax

12return0;

13 00007ff65f263d4a xor eax,eax

返回結構體示例:

1 s1 func3(int a, int b, int c, int

d) ;

3returns;4

}5intmain()

反彙編

1 s1 func3(int a, int b, int c, int

d) ;

19 00007ff68a271795 mov dword ptr [s],6

20 00007ff68a27179c mov dword ptr [rbp+0ch],7

21 00007ff68a2717a3 mov dword ptr [rbp+10h],8

22 00007ff68a2717aa mov dword ptr [rbp+14h],9

23 00007ff68a2717b1 mov dword ptr [rbp+18h],0bh

24 00007ff68a2717b8 mov dword ptr [rbp+1ch],0ch

25return

s;26

00007ff68a2717bf lea rax,[s]

27 00007ff68a2717c3 mov rdi,qword ptr [rbp+110h] //rbp+110h裡存放的是從rcx裡傳進來的呼叫函式分配的使用者存放返回值的指標

2800007ff68a2717ca mov rsi,rax

2900007ff68a2717cd mov ecx,18h

30 00007ff68a2717d2 rep movs byte ptr [rdi],byte

ptr [rsi] //上面幾行是將s結構體的資料複製到呼叫函式分配好的空間裡(rcx傳進來的)

31 00007ff68a2717d4 mov rax,qword ptr [rbp+110h] //將返回值指標賦值給rax

32 }

X64呼叫規範

1.由於位址長度為64位,因此call指令把rsp 堆疊指標 暫存器的值減去8.2.第一批傳遞子程式的四個引數依次存放於暫存器rcx rdx r8 r9。因此,如果只傳遞乙個引數就會放到rcx暫存器中。如果還有第二引數就會將其放入rdx暫存器中,其他引數從右至左入棧。3.長度不足64位的引數不進行零...

x64內聯彙編

建立 asm,寫入測試彙編 code asmadd proc mov rax,rcx add rax,rdx retasmadd endp end整形引數順序 rcx,rdx,r8,r9,rsp 浮點引數順序 xmm1,xmm2,xmm3.混合引數順序 第乙個引數整形 rcx,第二個引數浮點 xmm...

windows 核心資料結構 x64

核心物件 分類 dispatcher kprocess ktherad kevent ktimer kqueue kmutex i o driver object device object file object irp vpb kprofile other eprocess ethread ep...