X64的调用约定

来源:互联网 发布:孢子mac下载 编辑:程序博客网 时间:2024/04/29 10:26

接触x64之后继续看PG的文章,今天开始读msdn上有关x64的解释 http://msdn.microsoft.com/zh-cn/library/7kcdt6fy


调用约定简化了:一律使用__fastcall,前四个参数用 RCX、RDX、R8 和 R9传递,除了这四个外加RAX、R10、R11,其他寄存器都是非易失的。

比如下面这段NtCreateFile的代码:


PAGE:0000000140382B8C                 mov     r11, rsp;r11 保存rspPAGE:0000000140382B8F                 sub     rsp, 88h  ;开辟压栈参数空间,而不是用push,前四个参数在寄存器中所以不管PAGE:0000000140382B96                 xor     eax, eaxPAGE:0000000140382B98                 mov     [r11-10h], raxPAGE:0000000140382B9C                 mov     [rsp+88h+var_18], 20hPAGE:0000000140382BA4                 mov     [rsp+88h+var_20], eaxPAGE:0000000140382BA8                 mov     [r11-28h], raxPAGE:0000000140382BAC                 mov     [rsp+88h+var_30], eaxPAGE:0000000140382BB0                 mov     eax, [rsp+88h+EaLength] ;其他参数拷贝入栈PAGE:0000000140382BB7                 mov     [rsp+88h+var_38], eaxPAGE:0000000140382BBB                 mov     rax, [rsp+88h+EaBuffer]PAGE:0000000140382BC3                 mov     [r11-40h], raxPAGE:0000000140382BC7                 mov     eax, [rsp+88h+CreateOptions]PAGE:0000000140382BCE                 mov     [rsp+88h+var_48], eaxPAGE:0000000140382BD2                 mov     eax, [rsp+88h+CreateDisposition]PAGE:0000000140382BD9                 mov     [rsp+88h+var_50], eaxPAGE:0000000140382BDD                 mov     eax, [rsp+88h+ShareAccess]PAGE:0000000140382BE4                 mov     [rsp+88h+var_58], eaxPAGE:0000000140382BE8                 mov     eax, [rsp+88h+FileAttributes]PAGE:0000000140382BEF                 mov     [rsp+88h+var_60], eaxPAGE:0000000140382BF3                 mov     rax, [rsp+88h+AllocationSize]PAGE:0000000140382BFB                 mov     [r11-68h], raxPAGE:0000000140382BFF                 call    IopCreateFilePAGE:0000000140382C04                 add     rsp, 88h  ;平衡堆栈返回PAGE:0000000140382C0B                 retnPAGE:0000000140382C0B NtCreateFile    endpNtCreateFile是直接调用IoCreateFile的,比较特殊,下面跟进IoCreateFile PAGE:0000000140377CF0 ; FUNCTION CHUNK AT PAGE:00000001403D665F SIZE 0000008C BYTESPAGE:0000000140377CF0PAGE:0000000140377CF0                 mov     [rsp+arg_18], r9;无论是否有四个参数,函数开头都会把这四个参数入栈PAGE:0000000140377CF5                 mov     [rsp+arg_10], r8PAGE:0000000140377CFA                 mov     [rsp+arg_8], edxPAGE:0000000140377CFE                 mov     [rsp+arg_0], rcxPAGE:0000000140377D03                 push    rbx;微软承诺的非已易失寄存器,会全部入栈,这是PAGE:0000000140377D04                 push    rsiPAGE:0000000140377D05                 push    rdiPAGE:0000000140377D06                 push    r12PAGE:0000000140377D08                 push    r13PAGE:0000000140377D0A                 push    r14PAGE:0000000140377D0C                 push    r15PAGE:0000000140377D0E                 sub     rsp, 60hPAGE:0000000140377D12                 mov     r14d, edxPAGE:0000000140377D15                 xor     r15d, r15dPAGE:0000000140377D18                 mov     [rsp+98h+var_54], r15dPAGE:0000000140377D1D                 mov     rax, gs:188hPAGE:0000000140377D26                 mov     r13d, [rsp+98h+arg_68]PAGE:0000000140377D2E                 movzx   r12d, byte ptr [rax+1F6h]PAGE:0000000140377D36                 bt      r13d, 8PAGE:0000000140377D3B                 cmovb   r12d, r15dPAGE:0000000140377D3F                 mov     rsi, gs:20hPAGE:0000000140377D48                 mov     rbx, [rsi+800h]PAGE:0000000140377D4F                 inc     dword ptr [rbx+14h]PAGE:0000000140377D52                 mov     rcx, rbx        ; ListHeadPAGE:0000000140377D55                 call    RtlpInterlockedPopEntrySList;epilogadd     rsp, 60hpop     r15pop     r14pop     r13pop     r12pop     rdipop     rsipop     rbxretn


平衡堆栈的任务交给调用者来完成了,这里入参没有用push而是sub xx  调用之后再add xx

另外这里没有用rbp来存储父esp,因为这只是prolog的一个可选项

  MOV [RSP+8h],RCX
  MOV [RSP+10h],RDX
  MOV [RSP+18h],R8
  MOV [RSP+20h],R9
  PUSH RBP
  MOV RBP,RSP
  ;……
  LEA RSP,[RBP]
  POP RBP
  RET

具体可以看http://msdn.microsoft.com/zh-cn/library/tawsa7cb


寄存器的用法:


Register

状态

使用

RAX

易失的

返回值寄存器

RCX

易失的

第一个整型参数

RDX

易失的

第二个整型参数

R8

易失的

第三个整型参数

R9

易失的

第四个整型参数

R10:R11

易失的

必须根据需要由调用方保留;在 syscall/sysret 指令中使用

R12:R15

非易失的

必须由被调用方保留

RDI

非易失的

必须由被调用方保留

RSI

非易失的

必须由被调用方保留

RBX

非易失的

必须由被调用方保留

RBP

非易失的

可用作帧指针;必须由被调用方保留

RSP

非易失的

堆栈指针

XMM0

易失的

第一个 FP 参数

XMM1

易失的

第二个 FP 参数

XMM2

易失的

第三个 FP 参数

XMM3

易失的

第四个 FP 参数

XMM4:XMM5

易失的

必须根据需要由调用方保留

XMM6:XMM15

非易失的

必须根据需要由被调用方保留。


1: kd> bp iocreatefile1: kd> gBreakpoint 0 hitnt!IoCreateFile:fffff800`0418bf40 4c8bdc          mov     r11,rsp1: kd> dq rspfffff880`03727568  fffff960`000d8bad 00000000`00000000fffff880`03727578  00000000`000007ff 00000000`00000000fffff880`03727588  00000000`00000001 00000000`00000000fffff880`03727598  fffffa80`00000080 fffff8a0`00000001fffff880`037275a8  00000000`00000001 00000000`00000010fffff880`037275b8  00000000`00000000 fffff8a0`00000000fffff880`037275c8  fffff8a0`00000000 00000000`00000000fffff880`037275d8  fffff800`00000301 00000000`000000001: kd> u  fffff960`000d8badwin32k!bCreateSection+0x129:fffff960`000d8bad 408ace          mov     cl,silfffff960`000d8bb0 8bd8            mov     ebx,eaxfffff960`000d8bb2 ff15c88f2300    call    qword ptr [win32k!_imp_IoSetThreadHardErrorMode (fffff960`00311b80)]fffff960`000d8bb8 413bdd          cmp     ebx,r13dfffff960`000d8bbb 7d07            jge     win32k!bCreateSection+0x140 (fffff960`000d8bc4)fffff960`000d8bbd 33c0            xor     eax,eaxfffff960`000d8bbf e970020000      jmp     win32k!bCreateSection+0x3b0 (fffff960`000d8e34)fffff960`000d8bc4 488b4c2470      mov     rcx,qword ptr [rsp+70h]1: kd> r rax=fffff88003727688 rbx=fffff900c0081000 rcx=fffff880037275e0rdx=00000000001200a9 rsi=0000000000000001 rdi=0000000000000000rip=fffff8000418bf40 rsp=fffff88003727568 rbp=fffff880037277d0 r8=fffff88003727608  r9=fffff880037275f0 r10=0000000000000000r11=fffffa800ecc6860 r12=fffff88003727740 r13=0000000000000000r14=0000000000000001 r15=fffff88003727920iopl=0         nv up ei pl zr na po nccs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246nt!IoCreateFile:fffff800`0418bf40 4c8bdc          mov     r11,rsp1: kd> dt _OBJECT_ATTRIBUTES  fffff88003727608ntdll!_OBJECT_ATTRIBUTES   +0x000 Length           : 0x30   +0x008 RootDirectory    : (null)    +0x010 ObjectName       : 0xfffff880`03727688 _UNICODE_STRING "\??\C:\WINDOWS\FONTS\EUDC.TTE"   +0x018 Attributes       : 0x240   +0x020 SecurityDescriptor : (null)    +0x028 SecurityQualityOfService : (null) 

接下来要看的是x64异常处理


参考:

http://msdn.microsoft.com/zh-cn/library/7kcdt6fy

http://bbs.pediy.com/showthread.php?t=43967